From f1b4602d44474a92983419c8d733fcac74e389f5 Mon Sep 17 00:00:00 2001 From: Ryan Block Date: Sun, 3 Sep 2023 13:33:26 -0700 Subject: [PATCH] Update lint rules --- .eslintrc | 46 - actions/batchGetItem.js | 35 +- actions/batchWriteItem.js | 35 +- actions/createTable.js | 30 +- actions/deleteItem.js | 18 +- actions/deleteTable.js | 20 +- actions/describeTable.js | 6 +- actions/describeTimeToLive.js | 6 +- actions/getItem.js | 12 +- actions/listTables.js | 8 +- actions/listTagsOfResource.js | 10 +- actions/putItem.js | 18 +- actions/query.js | 60 +- actions/scan.js | 30 +- actions/tagResource.js | 8 +- actions/untagResource.js | 8 +- actions/updateItem.js | 103 +- actions/updateTable.js | 41 +- cli.js | 4 +- db/index.js | 545 ++--- index.js | 86 +- package.json | 13 +- test/batchGetItem.js | 560 +++--- test/batchWriteItem.js | 507 ++--- test/bench.js | 14 +- test/connection.js | 225 +-- test/createTable.js | 1608 +++++++-------- test/deleteItem.js | 504 ++--- test/deleteTable.js | 78 +- test/describeTable.js | 36 +- test/describeTimeToLive.js | 48 +- test/getItem.js | 470 ++--- test/helpers.js | 539 ++--- test/listTables.js | 152 +- test/listTagsOfResource.js | 80 +- test/putItem.js | 1174 +++++------ test/query.js | 2836 +++++++++++++------------- test/scan.js | 3076 +++++++++++++++-------------- test/tagResource.js | 62 +- test/untagResource.js | 58 +- test/updateItem.js | 1178 +++++------ test/updateTable.js | 358 ++-- validations/batchGetItem.js | 10 +- validations/batchWriteItem.js | 13 +- validations/createTable.js | 29 +- validations/deleteItem.js | 14 +- validations/getItem.js | 6 +- validations/index.js | 454 ++--- validations/listTagsOfResource.js | 2 +- validations/putItem.js | 16 +- validations/query.js | 16 +- validations/scan.js | 16 +- validations/tagResource.js | 2 +- validations/untagResource.js | 2 +- validations/updateItem.js | 16 +- validations/updateTable.js | 6 +- 56 files changed, 7696 insertions(+), 7611 deletions(-) delete mode 100644 .eslintrc diff --git a/.eslintrc b/.eslintrc deleted file mode 100644 index bd4cbfc..0000000 --- a/.eslintrc +++ /dev/null @@ -1,46 +0,0 @@ -{ - "extends": "eslint:recommended", - "env": { - "node": true, - "mocha": true - }, - "rules": { - - // relaxed restrictions - "no-mixed-requires": 0, - "no-underscore-dangle": 0, - "no-shadow": 0, - "no-use-before-define": [2, "nofunc"], - "camelcase": [2, {"properties": "never"}], - "curly": 0, - "eqeqeq": 0, - "new-parens": 0, - "quotes": [2, "single", "avoid-escape"], - "semi": [2, "never"], - "strict": 0, - - // extra restrictions - "no-empty-character-class": 2, - "no-extra-parens": [2, "functions"], - "no-floating-decimal": 2, - "no-lonely-if": 2, - "no-self-compare": 2, - "no-throw-literal": 2, - "no-unused-vars": 2, - - // style - "array-bracket-spacing": [2, "never"], - "brace-style": [2, "1tbs", {"allowSingleLine": true}], - "comma-dangle": [2, "always-multiline"], - "comma-style": [2, "last"], - "consistent-this": [2, "self"], - "object-curly-spacing": [2, "never"], - "operator-assignment": [2, "always"], - "operator-linebreak": [2, "after"], - "keyword-spacing": 2, - "space-before-blocks": [2, "always"], - "space-before-function-paren": [2, "never"], - "space-in-parens": [2, "never"], - "spaced-comment": [2, "always"] - } -} diff --git a/actions/batchGetItem.js b/actions/batchGetItem.js index 62dd576..9f18b64 100644 --- a/actions/batchGetItem.js +++ b/actions/batchGetItem.js @@ -1,29 +1,29 @@ var async = require('async'), - getItem = require('./getItem'), - db = require('../db') + getItem = require('./getItem'), + db = require('../db') -module.exports = function batchGetItem(store, data, cb) { +module.exports = function batchGetItem (store, data, cb) { var requests = {} async.series([ async.each.bind(async, Object.keys(data.RequestItems), addTableRequests), async.parallel.bind(async, requests), - ], function(err, responses) { + ], function (err, responses) { if (err) return cb(err) - var res = {Responses: {}, UnprocessedKeys: {}}, table, tableResponses = responses[1], totalSize = 0, capacities = {} + var res = { Responses: {}, UnprocessedKeys: {} }, table, tableResponses = responses[1], totalSize = 0, capacities = {} for (table in tableResponses) { // Order is pretty random // Assign keys before we shuffle - tableResponses[table].forEach(function(tableRes, ix) { tableRes._key = data.RequestItems[table].Keys[ix] }) // eslint-disable-line no-loop-func + tableResponses[table].forEach(function (tableRes, ix) { tableRes._key = data.RequestItems[table].Keys[ix] }) // eslint-disable-line no-loop-func shuffle(tableResponses[table]) - res.Responses[table] = tableResponses[table].map(function(tableRes) { // eslint-disable-line no-loop-func + res.Responses[table] = tableResponses[table].map(function (tableRes) { // eslint-disable-line no-loop-func if (tableRes.Item) { // TODO: This is totally inefficient - should fix this var newSize = totalSize + db.itemSize(tableRes.Item) if (newSize > (1024 * 1024 + store.options.maxItemSize - 3)) { if (!res.UnprocessedKeys[table]) { - res.UnprocessedKeys[table] = {Keys: []} + res.UnprocessedKeys[table] = { Keys: [] } if (data.RequestItems[table].AttributesToGet) res.UnprocessedKeys[table].AttributesToGet = data.RequestItems[table].AttributesToGet if (data.RequestItems[table].ConsistentRead) @@ -44,12 +44,12 @@ module.exports = function batchGetItem(store, data, cb) { }).filter(Boolean) } - if (~['TOTAL', 'INDEXES'].indexOf(data.ReturnConsumedCapacity)) { - res.ConsumedCapacity = Object.keys(tableResponses).map(function(table) { + if (~[ 'TOTAL', 'INDEXES' ].indexOf(data.ReturnConsumedCapacity)) { + res.ConsumedCapacity = Object.keys(tableResponses).map(function (table) { return { CapacityUnits: capacities[table], TableName: table, - Table: data.ReturnConsumedCapacity == 'INDEXES' ? {CapacityUnits: capacities[table]} : undefined, + Table: data.ReturnConsumedCapacity == 'INDEXES' ? { CapacityUnits: capacities[table] } : undefined, } }) } @@ -57,8 +57,8 @@ module.exports = function batchGetItem(store, data, cb) { cb(null, res) }) - function addTableRequests(tableName, cb) { - store.getTable(tableName, function(err, table) { + function addTableRequests (tableName, cb) { + store.getTable(tableName, function (err, table) { if (err) return cb(err) var req = data.RequestItems[tableName], i, key, options, gets = [] @@ -66,9 +66,10 @@ module.exports = function batchGetItem(store, data, cb) { for (i = 0; i < req.Keys.length; i++) { key = req.Keys[i] - if ((err = db.validateKey(key, table)) != null) return cb(err) + let invalid = db.validateKey(key, table) + if (invalid != null) return cb(invalid) - options = {TableName: tableName, Key: key} + options = { TableName: tableName, Key: key } if (req._projection) options._projection = req._projection if (req.AttributesToGet) options.AttributesToGet = req.AttributesToGet if (req.ConsistentRead) options.ConsistentRead = req.ConsistentRead @@ -76,14 +77,14 @@ module.exports = function batchGetItem(store, data, cb) { gets.push(options) } - requests[tableName] = async.map.bind(async, gets, function(data, cb) { return getItem(store, data, cb) }) + requests[tableName] = async.map.bind(async, gets, function (data, cb) { return getItem(store, data, cb) }) cb() }) } } -function shuffle(arr) { +function shuffle (arr) { var i, j, temp for (i = arr.length - 1; i >= 1; i--) { j = Math.floor(Math.random() * (i + 1)) diff --git a/actions/batchWriteItem.js b/actions/batchWriteItem.js index d2e755d..2bb4788 100644 --- a/actions/batchWriteItem.js +++ b/actions/batchWriteItem.js @@ -1,33 +1,33 @@ var async = require('async'), - putItem = require('./putItem'), - deleteItem = require('./deleteItem'), - db = require('../db') + putItem = require('./putItem'), + deleteItem = require('./deleteItem'), + db = require('../db') -module.exports = function batchWriteItem(store, data, cb) { +module.exports = function batchWriteItem (store, data, cb) { var actions = [] async.series([ async.each.bind(async, Object.keys(data.RequestItems), addTableActions), async.parallel.bind(async, actions), - ], function(err, responses) { + ], function (err, responses) { if (err) { if (err.body && (/Missing the key/.test(err.body.message) || /Type mismatch for key/.test(err.body.message))) err.body.message = 'The provided key element does not match the schema' return cb(err) } - var res = {UnprocessedItems: {}}, tableUnits = {} + var res = { UnprocessedItems: {} }, tableUnits = {} - if (~['TOTAL', 'INDEXES'].indexOf(data.ReturnConsumedCapacity)) { - responses[1].forEach(function(action) { + if (~[ 'TOTAL', 'INDEXES' ].indexOf(data.ReturnConsumedCapacity)) { + responses[1].forEach(function (action) { var table = action.ConsumedCapacity.TableName if (!tableUnits[table]) tableUnits[table] = 0 tableUnits[table] += action.ConsumedCapacity.CapacityUnits }) - res.ConsumedCapacity = Object.keys(tableUnits).map(function(table) { + res.ConsumedCapacity = Object.keys(tableUnits).map(function (table) { return { CapacityUnits: tableUnits[table], TableName: table, - Table: data.ReturnConsumedCapacity == 'INDEXES' ? {CapacityUnits: tableUnits[table]} : undefined, + Table: data.ReturnConsumedCapacity == 'INDEXES' ? { CapacityUnits: tableUnits[table] } : undefined, } }) } @@ -35,8 +35,8 @@ module.exports = function batchWriteItem(store, data, cb) { cb(null, res) }) - function addTableActions(tableName, cb) { - store.getTable(tableName, function(err, table) { + function addTableActions (tableName, cb) { + store.getTable(tableName, function (err, table) { if (err) return cb(err) var reqs = data.RequestItems[tableName], i, req, key, seenKeys = {}, options @@ -44,21 +44,24 @@ module.exports = function batchWriteItem(store, data, cb) { for (i = 0; i < reqs.length; i++) { req = reqs[i] - options = {TableName: tableName} + options = { TableName: tableName } if (data.ReturnConsumedCapacity) options.ReturnConsumedCapacity = data.ReturnConsumedCapacity if (req.PutRequest) { - if ((err = db.validateItem(req.PutRequest.Item, table)) != null) return cb(err) + let invalid = db.validateItem(req.PutRequest.Item, table) + if (invalid != null) return cb(invalid) options.Item = req.PutRequest.Item actions.push(putItem.bind(null, store, options)) key = db.createKey(options.Item, table) - } else if (req.DeleteRequest) { + } + else if (req.DeleteRequest) { - if ((err = db.validateKey(req.DeleteRequest.Key, table) != null)) return cb(err) + let invalid = db.validateKey(req.DeleteRequest.Key, table) + if (invalid != null) return cb(invalid) options.Key = req.DeleteRequest.Key actions.push(deleteItem.bind(null, store, options)) diff --git a/actions/createTable.js b/actions/createTable.js index 437ecb6..19c993d 100644 --- a/actions/createTable.js +++ b/actions/createTable.js @@ -1,13 +1,13 @@ var crypto = require('crypto') -module.exports = function createTable(store, data, cb) { +module.exports = function createTable (store, data, cb) { var key = data.TableName, tableDb = store.tableDb - tableDb.lock(key, function(release) { + tableDb.lock(key, function (release) { cb = release(cb) - tableDb.get(key, function(err) { + tableDb.get(key, function (err) { if (err && err.name != 'NotFoundError') return cb(err) if (!err) { err = new Error @@ -24,18 +24,18 @@ module.exports = function createTable(store, data, cb) { data.CreationDateTime = Date.now() / 1000 data.ItemCount = 0 if (!data.ProvisionedThroughput) { - data.ProvisionedThroughput = {ReadCapacityUnits: 0, WriteCapacityUnits: 0} + data.ProvisionedThroughput = { ReadCapacityUnits: 0, WriteCapacityUnits: 0 } } data.ProvisionedThroughput.NumberOfDecreasesToday = 0 data.TableSizeBytes = 0 data.TableStatus = 'CREATING' if (data.BillingMode == 'PAY_PER_REQUEST') { - data.BillingModeSummary = {BillingMode: 'PAY_PER_REQUEST'} - data.TableThroughputModeSummary = {TableThroughputMode: 'PAY_PER_REQUEST'} + data.BillingModeSummary = { BillingMode: 'PAY_PER_REQUEST' } + data.TableThroughputModeSummary = { TableThroughputMode: 'PAY_PER_REQUEST' } delete data.BillingMode } if (data.LocalSecondaryIndexes) { - data.LocalSecondaryIndexes.forEach(function(index) { + data.LocalSecondaryIndexes.forEach(function (index) { index.IndexArn = 'arn:aws:dynamodb:' + tableDb.awsRegion + ':' + tableDb.awsAccountId + ':table/' + data.TableName + '/index/' + index.IndexName index.IndexSizeBytes = 0 @@ -43,28 +43,28 @@ module.exports = function createTable(store, data, cb) { }) } if (data.GlobalSecondaryIndexes) { - data.GlobalSecondaryIndexes.forEach(function(index) { + data.GlobalSecondaryIndexes.forEach(function (index) { index.IndexArn = 'arn:aws:dynamodb:' + tableDb.awsRegion + ':' + tableDb.awsAccountId + ':table/' + data.TableName + '/index/' + index.IndexName index.IndexSizeBytes = 0 index.ItemCount = 0 index.IndexStatus = 'CREATING' if (!index.ProvisionedThroughput) { - index.ProvisionedThroughput = {ReadCapacityUnits: 0, WriteCapacityUnits: 0} + index.ProvisionedThroughput = { ReadCapacityUnits: 0, WriteCapacityUnits: 0 } } index.ProvisionedThroughput.NumberOfDecreasesToday = 0 }) } - tableDb.put(key, data, function(err) { + tableDb.put(key, data, function (err) { if (err) return cb(err) - setTimeout(function() { + setTimeout(function () { // Shouldn't need to lock/fetch as nothing should have changed data.TableStatus = 'ACTIVE' if (data.GlobalSecondaryIndexes) { - data.GlobalSecondaryIndexes.forEach(function(index) { + data.GlobalSecondaryIndexes.forEach(function (index) { index.IndexStatus = 'ACTIVE' }) } @@ -73,21 +73,21 @@ module.exports = function createTable(store, data, cb) { data.BillingModeSummary.LastUpdateToPayPerRequestDateTime = data.CreationDateTime } - tableDb.put(key, data, function(err) { + tableDb.put(key, data, function (err) { // eslint-disable-next-line no-console if (err && !/Database is not open/.test(err)) console.error(err.stack || err) }) }, store.options.createTableMs) - cb(null, {TableDescription: data}) + cb(null, { TableDescription: data }) }) }) }) } -function uuidV4() { +function uuidV4 () { var bytes = crypto.randomBytes(14).toString('hex') return bytes.slice(0, 8) + '-' + bytes.slice(8, 12) + '-4' + bytes.slice(13, 16) + '-' + bytes.slice(16, 20) + '-' + bytes.slice(20, 28) diff --git a/actions/deleteItem.js b/actions/deleteItem.js index b94e5c0..7e96c7e 100644 --- a/actions/deleteItem.js +++ b/actions/deleteItem.js @@ -1,21 +1,23 @@ var db = require('../db') -module.exports = function deleteItem(store, data, cb) { +module.exports = function deleteItem (store, data, cb) { - store.getTable(data.TableName, function(err, table) { + store.getTable(data.TableName, function (err, table) { if (err) return cb(err) - if ((err = db.validateKey(data.Key, table)) != null) return cb(err) + let invalid = db.validateKey(data.Key, table) + if (invalid != null) return cb(invalid) var itemDb = store.getItemDb(data.TableName), key = db.createKey(data.Key, table) - itemDb.lock(key, function(release) { + itemDb.lock(key, function (release) { cb = release(cb) - itemDb.get(key, function(err, existingItem) { + itemDb.get(key, function (err, existingItem) { if (err && err.name != 'NotFoundError') return cb(err) - if ((err = db.checkConditional(data, existingItem)) != null) return cb(err) + let invalid = db.checkConditional(data, existingItem) + if (invalid != null) return cb(invalid) var returnObj = {} @@ -24,10 +26,10 @@ module.exports = function deleteItem(store, data, cb) { returnObj.ConsumedCapacity = db.addConsumedCapacity(data, false, existingItem) - db.updateIndexes(store, table, existingItem, null, function(err) { + db.updateIndexes(store, table, existingItem, null, function (err) { if (err) return cb(err) - itemDb.del(key, function(err) { + itemDb.del(key, function (err) { if (err) return cb(err) cb(null, returnObj) }) diff --git a/actions/deleteTable.js b/actions/deleteTable.js index e5930fa..da52a2c 100644 --- a/actions/deleteTable.js +++ b/actions/deleteTable.js @@ -1,10 +1,10 @@ var async = require('async') -module.exports = function deleteTable(store, data, cb) { +module.exports = function deleteTable (store, data, cb) { var key = data.TableName, tableDb = store.tableDb - store.getTable(key, false, function(err, table) { + store.getTable(key, false, function (err, table) { if (err) return cb(err) // Check if table is ACTIVE or not? @@ -20,30 +20,30 @@ module.exports = function deleteTable(store, data, cb) { table.TableStatus = 'DELETING' - var deletes = [store.deleteItemDb.bind(store, key), store.deleteTagDb.bind(store, key)] - ;['Local', 'Global'].forEach(function(indexType) { + var deletes = [ store.deleteItemDb.bind(store, key), store.deleteTagDb.bind(store, key) ] + ;[ 'Local', 'Global' ].forEach(function (indexType) { var indexes = table[indexType + 'SecondaryIndexes'] || [] - deletes = deletes.concat(indexes.map(function(index) { + deletes = deletes.concat(indexes.map(function (index) { return store.deleteIndexDb.bind(store, indexType, table.TableName, index.IndexName) })) }) delete table.GlobalSecondaryIndexes - tableDb.put(key, table, function(err) { + tableDb.put(key, table, function (err) { if (err) return cb(err) - async.parallel(deletes, function(err) { + async.parallel(deletes, function (err) { if (err) return cb(err) - setTimeout(function() { - tableDb.del(key, function(err) { + setTimeout(function () { + tableDb.del(key, function (err) { // eslint-disable-next-line no-console if (err && !/Database is not open/.test(err)) console.error(err.stack || err) }) }, store.options.deleteTableMs) - cb(null, {TableDescription: table}) + cb(null, { TableDescription: table }) }) }) }) diff --git a/actions/describeTable.js b/actions/describeTable.js index d7272ef..a172bc8 100644 --- a/actions/describeTable.js +++ b/actions/describeTable.js @@ -1,10 +1,10 @@ -module.exports = function describeTable(store, data, cb) { +module.exports = function describeTable (store, data, cb) { - store.getTable(data.TableName, false, function(err, table) { + store.getTable(data.TableName, false, function (err, table) { if (err) return cb(err) - cb(null, {Table: table}) + cb(null, { Table: table }) }) } diff --git a/actions/describeTimeToLive.js b/actions/describeTimeToLive.js index 644c08d..bb68025 100644 --- a/actions/describeTimeToLive.js +++ b/actions/describeTimeToLive.js @@ -1,8 +1,8 @@ -module.exports = function describeTimeToLive(store, data, cb) { - store.getTable(data.TableName, false, function(err) { +module.exports = function describeTimeToLive (store, data, cb) { + store.getTable(data.TableName, false, function (err) { if (err) return cb(err) - cb(null, {TimeToLiveDescription: {TimeToLiveStatus: 'DISABLED'}}) + cb(null, { TimeToLiveDescription: { TimeToLiveStatus: 'DISABLED' } }) }) } diff --git a/actions/getItem.js b/actions/getItem.js index ff2cc5a..c2b2901 100644 --- a/actions/getItem.js +++ b/actions/getItem.js @@ -1,17 +1,19 @@ var db = require('../db') -module.exports = function getItem(store, data, cb) { +module.exports = function getItem (store, data, cb) { - store.getTable(data.TableName, function(err, table) { + store.getTable(data.TableName, function (err, table) { if (err) return cb(err) - if ((err = db.validateKey(data.Key, table)) != null) return cb(err) + let invalidKey = db.validateKey(data.Key, table) + if (invalidKey != null) return cb(invalidKey) - if ((err = db.validateKeyPaths((data._projection || {}).nestedPaths, table)) != null) return cb(err) + let invalidKeyPath = db.validateKeyPaths((data._projection || {}).nestedPaths, table) + if (invalidKeyPath != null) return cb(invalidKeyPath) var itemDb = store.getItemDb(data.TableName), key = db.createKey(data.Key, table) - itemDb.get(key, function(err, item) { + itemDb.get(key, function (err, item) { if (err && err.name != 'NotFoundError') return cb(err) var returnObj = {}, paths = data._projection ? data._projection.paths : data.AttributesToGet diff --git a/actions/listTables.js b/actions/listTables.js index 6edec1b..7addf66 100644 --- a/actions/listTables.js +++ b/actions/listTables.js @@ -1,16 +1,16 @@ var once = require('once'), - db = require('../db') + db = require('../db') -module.exports = function listTables(store, data, cb) { +module.exports = function listTables (store, data, cb) { cb = once(cb) var opts, limit = data.Limit || 100 if (data.ExclusiveStartTableName) - opts = {gt: data.ExclusiveStartTableName} + opts = { gt: data.ExclusiveStartTableName } db.lazy(store.tableDb.createKeyStream(opts), cb) .take(limit + 1) - .join(function(names) { + .join(function (names) { var result = {} if (names.length > limit) { names.splice(limit) diff --git a/actions/listTagsOfResource.js b/actions/listTagsOfResource.js index bbf7627..af1285f 100644 --- a/actions/listTagsOfResource.js +++ b/actions/listTagsOfResource.js @@ -1,19 +1,19 @@ var once = require('once'), - db = require('../db') + db = require('../db') -module.exports = function listTagsOfResource(store, data, cb) { +module.exports = function listTagsOfResource (store, data, cb) { cb = once(cb) var tableName = data.ResourceArn.split('/').pop() - store.getTable(tableName, false, function(err) { + store.getTable(tableName, false, function (err) { if (err && err.name == 'NotFoundError') { err.body.message = 'Requested resource not found: ResourcArn: ' + data.ResourceArn + ' not found' } if (err) return cb(err) - db.lazy(store.getTagDb(tableName).createReadStream(), cb).join(function(tags) { - cb(null, {Tags: tags.map(function(tag) { return {Key: tag.key, Value: tag.value} })}) + db.lazy(store.getTagDb(tableName).createReadStream(), cb).join(function (tags) { + cb(null, { Tags: tags.map(function (tag) { return { Key: tag.key, Value: tag.value } }) }) }) }) } diff --git a/actions/putItem.js b/actions/putItem.js index e299dc0..b4ef48b 100644 --- a/actions/putItem.js +++ b/actions/putItem.js @@ -1,21 +1,23 @@ var db = require('../db') -module.exports = function putItem(store, data, cb) { +module.exports = function putItem (store, data, cb) { - store.getTable(data.TableName, function(err, table) { + store.getTable(data.TableName, function (err, table) { if (err) return cb(err) - if ((err = db.validateItem(data.Item, table)) != null) return cb(err) + let invalid = db.validateItem(data.Item, table) + if (invalid != null) return cb(invalid) var itemDb = store.getItemDb(data.TableName), key = db.createKey(data.Item, table) - itemDb.lock(key, function(release) { + itemDb.lock(key, function (release) { cb = release(cb) - itemDb.get(key, function(err, existingItem) { + itemDb.get(key, function (err, existingItem) { if (err && err.name != 'NotFoundError') return cb(err) - if ((err = db.checkConditional(data, existingItem)) != null) return cb(err) + let invalid = db.checkConditional(data, existingItem) + if (invalid != null) return cb(invalid) var returnObj = {} @@ -24,10 +26,10 @@ module.exports = function putItem(store, data, cb) { returnObj.ConsumedCapacity = db.addConsumedCapacity(data, false, existingItem, data.Item) - db.updateIndexes(store, table, existingItem, data.Item, function(err) { + db.updateIndexes(store, table, existingItem, data.Item, function (err) { if (err) return cb(err) - itemDb.put(key, data.Item, function(err) { + itemDb.put(key, data.Item, function (err) { if (err) return cb(err) cb(null, returnObj) }) diff --git a/actions/query.js b/actions/query.js index 229709b..7a76ed0 100644 --- a/actions/query.js +++ b/actions/query.js @@ -1,17 +1,17 @@ var once = require('once'), - db = require('../db') + db = require('../db') -module.exports = function query(store, data, cb) { +module.exports = function query (store, data, cb) { cb = once(cb) - store.getTable(data.TableName, function(err, table) { + store.getTable(data.TableName, function (err, table) { if (err) return cb(err) - var keySchema = table.KeySchema, startKeyNames = keySchema.map(function(key) { return key.AttributeName }), + var keySchema = table.KeySchema, startKeyNames = keySchema.map(function (key) { return key.AttributeName }), hashKey = startKeyNames[0], rangeKey = startKeyNames[1], fetchFromItemDb = false, isLocal if (data.IndexName) { - var index = db.traverseIndexes(table, function(attr, type, index, isGlobal) { + var index = db.traverseIndexes(table, function (attr, type, index, isGlobal) { if (index.IndexName == data.IndexName) { isLocal = !isGlobal return index @@ -25,7 +25,7 @@ module.exports = function query(store, data, cb) { } keySchema = index.KeySchema fetchFromItemDb = data.Select == 'ALL_ATTRIBUTES' && index.Projection.ProjectionType != 'ALL' - keySchema.forEach(function(key) { if (!~startKeyNames.indexOf(key.AttributeName)) startKeyNames.push(key.AttributeName) }) + keySchema.forEach(function (key) { if (!~startKeyNames.indexOf(key.AttributeName)) startKeyNames.push(key.AttributeName) }) hashKey = keySchema[0].AttributeName rangeKey = keySchema[1] && keySchema[1].AttributeName } @@ -34,7 +34,7 @@ module.exports = function query(store, data, cb) { return cb(db.validationError('The provided starting key is invalid')) } - err = db.traverseKey(table, keySchema, function(attr, type, isHash) { + err = db.traverseKey(table, keySchema, function (attr, type, isHash) { if (data.ExclusiveStartKey) { if (!data.ExclusiveStartKey[attr]) { return db.validationError('The provided starting key is invalid') @@ -56,11 +56,11 @@ module.exports = function query(store, data, cb) { var comparisonOperator = data.KeyConditions[attr].ComparisonOperator - if (~['NULL', 'NOT_NULL', 'NE', 'CONTAINS', 'NOT_CONTAINS', 'IN'].indexOf(comparisonOperator)) { + if (~[ 'NULL', 'NOT_NULL', 'NE', 'CONTAINS', 'NOT_CONTAINS', 'IN' ].indexOf(comparisonOperator)) { return db.validationError('Attempted conditional constraint is not an indexable operation') } - if (data.KeyConditions[attr].AttributeValueList.some(function(attrVal) { return attrVal[type] == null })) { + if (data.KeyConditions[attr].AttributeValueList.some(function (attrVal) { return attrVal[type] == null })) { return db.validationError('One or more parameter values were invalid: Condition parameter type does not match schema type') } @@ -74,19 +74,19 @@ module.exports = function query(store, data, cb) { var hashVal = data.KeyConditions[hashKey].AttributeValueList[0][hashType] if (data.ExclusiveStartKey) { - var tableStartKey = table.KeySchema.reduce(function(obj, attr) { + var tableStartKey = table.KeySchema.reduce(function (obj, attr) { obj[attr.AttributeName] = data.ExclusiveStartKey[attr.AttributeName] return obj }, {}) - if ((err = db.validateKey(tableStartKey, table)) != null) { - return cb(db.validationError('The provided starting key is invalid: ' + err.message)) - } + let invalid = db.validateKey(tableStartKey, table) + if (invalid != null) return cb(db.validationError('The provided starting key is invalid: ' + invalid.message)) if (!rangeKey || !data.KeyConditions[rangeKey]) { if (data.ExclusiveStartKey[hashKey][hashType] != hashVal) { return cb(db.validationError('The provided starting key is outside query boundaries based on provided conditions')) } - } else { + } + else { var matchesRange = db.compare(data.KeyConditions[rangeKey].ComparisonOperator, data.ExclusiveStartKey[rangeKey], data.KeyConditions[rangeKey].AttributeValueList) if (!matchesRange) { @@ -98,12 +98,14 @@ module.exports = function query(store, data, cb) { } } - if ((err = db.validateKeyPaths((data._projection || {}).nestedPaths, table)) != null) return cb(err) + let invalid + invalid = db.validateKeyPaths((data._projection || {}).nestedPaths, table) + if (invalid != null) return cb(invalid) if (data.QueryFilter || data._filter) { var pathHeads = data.QueryFilter ? data.QueryFilter : data._filter.pathHeads var propertyName = data.QueryFilter ? 'QueryFilter' : 'Filter Expression' - err = db.traverseKey(table, keySchema, function(attr) { + err = db.traverseKey(table, keySchema, function (attr) { if (pathHeads[attr]) { return db.validationError(propertyName + ' can only contain non-primary key attributes: ' + 'Primary key attribute: ' + attr) @@ -118,9 +120,10 @@ module.exports = function query(store, data, cb) { data.IndexName + ' because its projection type is not ALL')) } - if ((err = db.validateKeyPaths((data._filter || {}).nestedPaths, table)) != null) return cb(err) + invalid = db.validateKeyPaths((data._filter || {}).nestedPaths, table) + if (invalid != null) return cb(invalid) - var opts = {reverse: data.ScanIndexForward === false, limit: data.Limit ? data.Limit + 1 : -1} + var opts = { reverse: data.ScanIndexForward === false, limit: data.Limit ? data.Limit + 1 : -1 } opts.gte = db.hashPrefix(hashVal, hashType) + '/' + db.toRangeStr(hashVal, hashType) + '/' opts.lt = opts.gte + '~' @@ -133,20 +136,26 @@ module.exports = function query(store, data, cb) { opts.gte += rangeStr opts.lte = opts.gte + '~' delete opts.lt - } else if (comp == 'LT') { + } + else if (comp == 'LT') { opts.lt = opts.gte + rangeStr - } else if (comp == 'LE') { + } + else if (comp == 'LE') { opts.lte = opts.gte + rangeStr + '~' delete opts.lt - } else if (comp == 'GT') { + } + else if (comp == 'GT') { opts.gt = opts.gte + rangeStr + '~' delete opts.gte - } else if (comp == 'GE') { + } + else if (comp == 'GE') { opts.gte += rangeStr - } else if (comp == 'BEGINS_WITH') { + } + else if (comp == 'BEGINS_WITH') { opts.lt = opts.gte + rangeStrPrefix + '~' opts.gte += rangeStr - } else if (comp == 'BETWEEN') { + } + else if (comp == 'BETWEEN') { opts.lte = opts.gte + db.toRangeStr(data.KeyConditions[rangeKey].AttributeValueList[1]) + '/~' opts.gte += rangeStr delete opts.lt @@ -160,7 +169,8 @@ module.exports = function query(store, data, cb) { if (data.ScanIndexForward === false) { opts.lt = startKey delete opts.lte - } else { + } + else { opts.gt = startKey delete opts.gte } diff --git a/actions/scan.js b/actions/scan.js index 9f892c8..b6f1a15 100644 --- a/actions/scan.js +++ b/actions/scan.js @@ -1,17 +1,17 @@ var once = require('once'), - db = require('../db') + db = require('../db') -module.exports = function scan(store, data, cb) { +module.exports = function scan (store, data, cb) { cb = once(cb) - store.getTable(data.TableName, function(err, table) { + store.getTable(data.TableName, function (err, table) { if (err) return cb(err) - var keySchema = table.KeySchema, startKeyNames = keySchema.map(function(key) { return key.AttributeName }), + var keySchema = table.KeySchema, startKeyNames = keySchema.map(function (key) { return key.AttributeName }), fetchFromItemDb = false, isLocal if (data.IndexName) { - var index = db.traverseIndexes(table, function(attr, type, index, isGlobal) { + var index = db.traverseIndexes(table, function (attr, type, index, isGlobal) { if (index.IndexName == data.IndexName) { isLocal = !isGlobal return index @@ -25,7 +25,7 @@ module.exports = function scan(store, data, cb) { } keySchema = index.KeySchema fetchFromItemDb = data.Select == 'ALL_ATTRIBUTES' && index.Projection.ProjectionType != 'ALL' - keySchema.forEach(function(key) { if (!~startKeyNames.indexOf(key.AttributeName)) startKeyNames.push(key.AttributeName) }) + keySchema.forEach(function (key) { if (!~startKeyNames.indexOf(key.AttributeName)) startKeyNames.push(key.AttributeName) }) } if (data.ExclusiveStartKey && Object.keys(data.ExclusiveStartKey).length != startKeyNames.length) { @@ -34,7 +34,7 @@ module.exports = function scan(store, data, cb) { } if (data.IndexName && data.ExclusiveStartKey) { - err = db.traverseKey(table, keySchema, function(attr, type, isHash) { + err = db.traverseKey(table, keySchema, function (attr, type, isHash) { if (!data.ExclusiveStartKey[attr]) { return db.validationError('The provided starting key is invalid') } @@ -50,13 +50,12 @@ module.exports = function scan(store, data, cb) { } if (data.ExclusiveStartKey) { - var tableStartKey = table.KeySchema.reduce(function(obj, attr) { + var tableStartKey = table.KeySchema.reduce(function (obj, attr) { obj[attr.AttributeName] = data.ExclusiveStartKey[attr.AttributeName] return obj }, {}) - if ((err = db.validateKey(tableStartKey, table)) != null) { - return cb(db.validationError('The provided starting key is invalid: ' + err.message)) - } + let invalid = db.validateKey(tableStartKey, table) + if (invalid != null) return cb(db.validationError('The provided starting key is invalid: ' + invalid.message)) } if (data.TotalSegments > 1) { @@ -77,11 +76,14 @@ module.exports = function scan(store, data, cb) { hashStart = startKey } - if ((err = db.validateKeyPaths((data._projection || {}).nestedPaths, table)) != null) return cb(err) + let invalid + invalid = db.validateKeyPaths((data._projection || {}).nestedPaths, table) + if (invalid != null) return cb(invalid) - if ((err = db.validateKeyPaths((data._filter || {}).nestedPaths, table)) != null) return cb(err) + invalid = db.validateKeyPaths((data._filter || {}).nestedPaths, table) + if (invalid != null) return cb(invalid) - var opts = {limit: data.Limit ? data.Limit + 1 : -1} + var opts = { limit: data.Limit ? data.Limit + 1 : -1 } if (hashStart != null) { opts.gt = hashStart diff --git a/actions/tagResource.js b/actions/tagResource.js index 8b43b9c..e307e17 100644 --- a/actions/tagResource.js +++ b/actions/tagResource.js @@ -1,18 +1,18 @@ var once = require('once') -module.exports = function tagResource(store, data, cb) { +module.exports = function tagResource (store, data, cb) { cb = once(cb) var tableName = data.ResourceArn.split('/').pop() - store.getTable(tableName, false, function(err) { + store.getTable(tableName, false, function (err) { if (err && err.name == 'NotFoundError') { err.body.message = 'Requested resource not found: ResourcArn: ' + data.ResourceArn + ' not found' } if (err) return cb(err) - var batchPuts = data.Tags.map(function(tag) { return {type: 'put', key: tag.Key, value: tag.Value} }) - store.getTagDb(tableName).batch(batchPuts, function(err) { + var batchPuts = data.Tags.map(function (tag) { return { type: 'put', key: tag.Key, value: tag.Value } }) + store.getTagDb(tableName).batch(batchPuts, function (err) { if (err) return cb(err) cb(null, '') }) diff --git a/actions/untagResource.js b/actions/untagResource.js index 6ba2cf3..e00abea 100644 --- a/actions/untagResource.js +++ b/actions/untagResource.js @@ -1,18 +1,18 @@ var once = require('once') -module.exports = function untagResource(store, data, cb) { +module.exports = function untagResource (store, data, cb) { cb = once(cb) var tableName = data.ResourceArn.split('/').pop() - store.getTable(tableName, false, function(err) { + store.getTable(tableName, false, function (err) { if (err && err.name == 'NotFoundError') { err.body.message = 'Requested resource not found' } if (err) return cb(err) - var batchDeletes = data.TagKeys.map(function(key) { return {type: 'del', key: key} }) - store.getTagDb(tableName).batch(batchDeletes, function(err) { + var batchDeletes = data.TagKeys.map(function (key) { return { type: 'del', key: key } }) + store.getTagDb(tableName).batch(batchDeletes, function (err) { if (err) return cb(err) cb(null, '') }) diff --git a/actions/updateItem.js b/actions/updateItem.js index 72f7f7c..051934f 100644 --- a/actions/updateItem.js +++ b/actions/updateItem.js @@ -1,24 +1,27 @@ var Big = require('big.js'), - db = require('../db') + db = require('../db') -module.exports = function updateItem(store, data, cb) { +module.exports = function updateItem (store, data, cb) { - store.getTable(data.TableName, function(err, table) { + store.getTable(data.TableName, function (err, table) { if (err) return cb(err) - if ((err = db.validateKey(data.Key, table)) != null) return cb(err) + let invalidKey = db.validateKey(data.Key, table) + if (invalidKey != null) return cb(invalidKey) - if ((err = db.validateUpdates(data.AttributeUpdates, data._updates, table)) != null) return cb(err) + let invalidUpdate = db.validateUpdates(data.AttributeUpdates, data._updates, table) + if (invalidUpdate != null) return cb(invalidUpdate) var itemDb = store.getItemDb(data.TableName), key = db.createKey(data.Key, table) - itemDb.lock(key, function(release) { + itemDb.lock(key, function (release) { cb = release(cb) - itemDb.get(key, function(err, oldItem) { + itemDb.get(key, function (err, oldItem) { if (err && err.name != 'NotFoundError') return cb(err) - if ((err = db.checkConditional(data, oldItem)) != null) return cb(err) + let invalid = db.checkConditional(data, oldItem) + if (invalid != null) return cb(invalid) var returnObj = {}, item = data.Key, paths = data._updates ? data._updates.paths : Object.keys(data.AttributeUpdates || {}) @@ -27,7 +30,8 @@ module.exports = function updateItem(store, data, cb) { item = deepClone(oldItem) if (data.ReturnValues == 'ALL_OLD') { returnObj.Attributes = oldItem - } else if (data.ReturnValues == 'UPDATED_OLD') { + } + else if (data.ReturnValues == 'UPDATED_OLD') { returnObj.Attributes = db.mapPaths(paths, oldItem) } } @@ -41,16 +45,17 @@ module.exports = function updateItem(store, data, cb) { if (data.ReturnValues == 'ALL_NEW') { returnObj.Attributes = item - } else if (data.ReturnValues == 'UPDATED_NEW') { + } + else if (data.ReturnValues == 'UPDATED_NEW') { returnObj.Attributes = db.mapPaths(paths, item) } returnObj.ConsumedCapacity = db.addConsumedCapacity(data, false, oldItem, item) - db.updateIndexes(store, table, oldItem, item, function(err) { + db.updateIndexes(store, table, oldItem, item, function (err) { if (err) return cb(err) - itemDb.put(key, item, function(err) { + itemDb.put(key, item, function (err) { if (err) return cb(err) cb(null, returnObj) }) @@ -61,7 +66,7 @@ module.exports = function updateItem(store, data, cb) { } // Relatively fast deep clone of simple objects/arrays -function deepClone(obj) { +function deepClone (obj) { if (typeof obj != 'object' || obj == null) return obj var result if (Array.isArray(obj)) { @@ -69,7 +74,8 @@ function deepClone(obj) { for (var i = 0; i < obj.length; i++) { result[i] = deepClone(obj[i]) } - } else { + } + else { result = Object.create(null) for (var attr in obj) { result[attr] = deepClone(obj[attr]) @@ -78,47 +84,51 @@ function deepClone(obj) { return result } -function applyAttributeUpdates(updates, table, item) { +function applyAttributeUpdates (updates, table, item) { for (var attr in updates) { var update = updates[attr] if (update.Action == 'PUT' || update.Action == null) { item[attr] = update.Value - } else if (update.Action == 'ADD') { + } + else if (update.Action == 'ADD') { if (update.Value.N) { if (item[attr] && !item[attr].N) return db.validationError('Type mismatch for attribute to update') - if (!item[attr]) item[attr] = {N: '0'} + if (!item[attr]) item[attr] = { N: '0' } item[attr].N = new Big(item[attr].N).plus(update.Value.N).toFixed() - } else { + } + else { var type = Object.keys(update.Value)[0] if (item[attr] && !item[attr][type]) return db.validationError('Type mismatch for attribute to update') if (!item[attr]) item[attr] = {} if (!item[attr][type]) item[attr][type] = [] - var val = type == 'L' ? update.Value[type] : update.Value[type].filter(function(a) { // eslint-disable-line no-loop-func + var val = type == 'L' ? update.Value[type] : update.Value[type].filter(function (a) { // eslint-disable-line no-loop-func return !~item[attr][type].indexOf(a) }) item[attr][type] = item[attr][type].concat(val) } - } else if (update.Action == 'DELETE') { + } + else if (update.Action == 'DELETE') { if (update.Value) { type = Object.keys(update.Value)[0] if (item[attr] && !item[attr][type]) return db.validationError('Type mismatch for attribute to update') if (item[attr] && item[attr][type]) { - item[attr][type] = item[attr][type].filter(function(val) { // eslint-disable-line no-loop-func + item[attr][type] = item[attr][type].filter(function (val) { // eslint-disable-line no-loop-func return !~update.Value[type].indexOf(val) }) if (!item[attr][type].length) delete item[attr] } - } else { + } + else { delete item[attr] } } } } -function applyUpdateExpression(sections, table, item) { +function applyUpdateExpression (sections, table, item) { var toSquash = [] for (var i = 0; i < sections.length; i++) { var section = sections[i] @@ -140,38 +150,42 @@ function applyUpdateExpression(sections, table, item) { var alreadyExists = existing != null if (section.type == 'remove') { deleteFromParent(parent, attr) - } else if (section.type == 'delete') { + } + else if (section.type == 'delete') { if (alreadyExists && Object.keys(existing)[0] != section.attrType) { return db.validationError('An operand in the update expression has an incorrect data type') } if (alreadyExists) { - existing[section.attrType] = existing[section.attrType].filter(function(val) { // eslint-disable-line no-loop-func + existing[section.attrType] = existing[section.attrType].filter(function (val) { // eslint-disable-line no-loop-func return !~section.val[section.attrType].indexOf(val) }) if (!existing[section.attrType].length) { deleteFromParent(parent, attr) } } - } else if (section.type == 'add') { + } + else if (section.type == 'add') { if (alreadyExists && Object.keys(existing)[0] != section.attrType) { return db.validationError('An operand in the update expression has an incorrect data type') } if (section.attrType == 'N') { - if (!existing) existing = {N: '0'} + if (!existing) existing = { N: '0' } existing.N = new Big(existing.N).plus(section.val.N).toFixed() - } else { + } + else { if (!existing) existing = {} if (!existing[section.attrType]) existing[section.attrType] = [] - existing[section.attrType] = existing[section.attrType].concat(section.val[section.attrType].filter(function(a) { // eslint-disable-line no-loop-func + existing[section.attrType] = existing[section.attrType].concat(section.val[section.attrType].filter(function (a) { // eslint-disable-line no-loop-func return !~existing[section.attrType].indexOf(a) })) } if (!alreadyExists) { addToParent(parent, attr, existing, toSquash) } - } else if (section.type == 'set') { + } + else if (section.type == 'set') { if (section.path.length == 1) { - var err = db.traverseIndexes(table, function(attr, type) { + var err = db.traverseIndexes(table, function (attr, type) { if (section.path[0] == attr && section.val[type] == null) { return db.validationError('The update expression attempted to update the secondary index key to unsupported type') } @@ -181,13 +195,14 @@ function applyUpdateExpression(sections, table, item) { addToParent(parent, attr, section.val, toSquash) } } - toSquash.forEach(function(obj) { obj.L = obj.L.filter(Boolean) }) + toSquash.forEach(function (obj) { obj.L = obj.L.filter(Boolean) }) } -function resolveValue(val, item) { +function resolveValue (val, item) { if (Array.isArray(val)) { val = db.mapPath(val, item) - } else if (val.type == 'add' || val.type == 'subtract') { + } + else if (val.type == 'add' || val.type == 'subtract') { var val1 = resolveValue(val.args[0], item) if (typeof val1 == 'string') return val1 if (val1.N == null) { @@ -198,10 +213,12 @@ function resolveValue(val, item) { if (val2.N == null) { return 'An operand in the update expression has an incorrect data type' } - val = {N: new Big(val1.N)[val.type == 'add' ? 'plus' : 'minus'](val2.N).toFixed()} - } else if (val.type == 'function' && val.name == 'if_not_exists') { + val = { N: new Big(val1.N)[val.type == 'add' ? 'plus' : 'minus'](val2.N).toFixed() } + } + else if (val.type == 'function' && val.name == 'if_not_exists') { val = db.mapPath(val.args[0], item) || resolveValue(val.args[1], item) - } else if (val.type == 'function' && val.name == 'list_append') { + } + else if (val.type == 'function' && val.name == 'list_append') { val1 = resolveValue(val.args[0], item) if (typeof val1 == 'string') return val1 if (val1.L == null) { @@ -212,23 +229,25 @@ function resolveValue(val, item) { if (val2.L == null) { return 'An operand in the update expression has an incorrect data type' } - return {L: val1.L.concat(val2.L)} + return { L: val1.L.concat(val2.L) } } return val || 'The provided expression refers to an attribute that does not exist in the item' } -function deleteFromParent(parent, attr) { +function deleteFromParent (parent, attr) { if (parent.M) { delete parent.M[attr] - } else if (parent.L) { + } + else if (parent.L) { parent.L.splice(attr, 1) } } -function addToParent(parent, attr, val, toSquash) { +function addToParent (parent, attr, val, toSquash) { if (parent.M) { parent.M[attr] = val - } else if (parent.L) { + } + else if (parent.L) { if (attr > parent.L.length && !~toSquash.indexOf(parent)) { toSquash.push(parent) } diff --git a/actions/updateTable.js b/actions/updateTable.js index c5ea971..d327c0c 100644 --- a/actions/updateTable.js +++ b/actions/updateTable.js @@ -1,13 +1,13 @@ var db = require('../db') -module.exports = function updateTable(store, data, cb) { +module.exports = function updateTable (store, data, cb) { var key = data.TableName, tableDb = store.tableDb - tableDb.lock(key, function(release) { + tableDb.lock(key, function (release) { cb = release(cb) - store.getTable(key, false, function(err, table) { + store.getTable(key, false, function (err, table) { if (err) return cb(err) var tableBillingMode = (table.BillingModeSummary || {}).BillingMode || 'PROVISIONED' @@ -21,7 +21,8 @@ module.exports = function updateTable(store, data, cb) { try { updates = getThroughputUpdates(data, table) - } catch (err) { + } + catch (err) { return cb(err) } @@ -67,7 +68,7 @@ module.exports = function updateTable(store, data, cb) { table.ProvisionedThroughput.ReadCapacityUnits = 0 table.ProvisionedThroughput.WriteCapacityUnits = 0 if (table.GlobalSecondaryIndexes) { - table.GlobalSecondaryIndexes.forEach(function(index) { + table.GlobalSecondaryIndexes.forEach(function (index) { index.IndexStatus = 'UPDATING' index.ProvisionedThroughput = index.ProvisionedThroughput || {} index.ProvisionedThroughput.NumberOfDecreasesToday = index.ProvisionedThroughput.NumberOfDecreasesToday || 0 @@ -75,20 +76,21 @@ module.exports = function updateTable(store, data, cb) { index.ProvisionedThroughput.WriteCapacityUnits = 0 }) } - } else if (data.BillingMode == 'PROVISIONED' && tableBillingMode != 'PROVISIONED') { + } + else if (data.BillingMode == 'PROVISIONED' && tableBillingMode != 'PROVISIONED') { table.BillingModeSummary = table.BillingModeSummary || {} table.BillingModeSummary.BillingMode = 'PROVISIONED' table.TableThroughputModeSummary = table.TableThroughputModeSummary || {} table.TableThroughputModeSummary.TableThroughputMode = 'PROVISIONED' } - tableDb.put(key, table, function(err) { + tableDb.put(key, table, function (err) { if (err) return cb(err) - setTimeout(function() { + setTimeout(function () { // Shouldn't need to lock/fetch as nothing should have changed - updates.forEach(function(update) { + updates.forEach(function (update) { dataThroughput = update.dataThroughput tableThroughput = update.tableThroughput @@ -96,7 +98,8 @@ module.exports = function updateTable(store, data, cb) { if (update.readDiff > 0 || update.writeDiff > 0) { tableThroughput.LastIncreaseDateTime = Date.now() / 1000 - } else if (update.readDiff < 0 || update.writeDiff < 0) { + } + else if (update.readDiff < 0 || update.writeDiff < 0) { tableThroughput.LastDecreaseDateTime = Date.now() / 1000 tableThroughput.NumberOfDecreasesToday++ } @@ -111,7 +114,7 @@ module.exports = function updateTable(store, data, cb) { table.TableThroughputModeSummary.LastUpdateToPayPerRequestDateTime = Date.now() / 1000 delete table.ProvisionedThroughput.LastDecreaseDateTime if (table.GlobalSecondaryIndexes) { - table.GlobalSecondaryIndexes.forEach(function(index) { + table.GlobalSecondaryIndexes.forEach(function (index) { index.IndexStatus = 'ACTIVE' index.ProvisionedThroughput.NumberOfDecreasesToday++ index.ProvisionedThroughput.LastDecreaseDateTime = Date.now() / 1000 @@ -119,23 +122,23 @@ module.exports = function updateTable(store, data, cb) { } } - tableDb.put(key, table, function(err) { + tableDb.put(key, table, function (err) { // eslint-disable-next-line no-console if (err && !/Database is not open/.test(err)) console.error(err.stack || err) }) }, store.options.updateTableMs) - cb(null, {TableDescription: table}) + cb(null, { TableDescription: table }) }) }) }) } -function getThroughputUpdates(data, table) { +function getThroughputUpdates (data, table) { var tableBillingMode = (table.BillingModeSummary || {}).BillingMode || 'PROVISIONED' - var remainingIndexes = (table.GlobalSecondaryIndexes || []).reduce(function(map, index) { + var remainingIndexes = (table.GlobalSecondaryIndexes || []).reduce(function (map, index) { map[index.IndexName] = true return map }, Object.create(null)) @@ -144,12 +147,12 @@ function getThroughputUpdates(data, table) { updates.push({ dataThroughput: data.ProvisionedThroughput, tableThroughput: table.ProvisionedThroughput, - setStatus: function(status) { table.TableStatus = status }, + setStatus: function (status) { table.TableStatus = status }, }) } var globalUpdates = data.GlobalSecondaryIndexUpdates || [] if (globalUpdates.length > 5) throw db.limitError('Subscriber limit exceeded: Only 1 online index can be created or deleted simultaneously per table') - globalUpdates.forEach(function(update) { + globalUpdates.forEach(function (update) { var dataThroughput = update.Update && update.Update.ProvisionedThroughput if (!dataThroughput) { return @@ -157,13 +160,13 @@ function getThroughputUpdates(data, table) { if (dataThroughput.ReadCapacityUnits > 1000000000000 || dataThroughput.WriteCapacityUnits > 1000000000000) { throw db.validationError('This operation cannot be performed with given input values. Please contact DynamoDB service team for more info: Action Blocked: IndexUpdate') } - (table.GlobalSecondaryIndexes || []).forEach(function(index) { + (table.GlobalSecondaryIndexes || []).forEach(function (index) { if (index.IndexName == update.Update.IndexName) { delete remainingIndexes[index.IndexName] updates.push({ dataThroughput: dataThroughput, tableThroughput: index.ProvisionedThroughput, - setStatus: function(status) { index.IndexStatus = status }, + setStatus: function (status) { index.IndexStatus = status }, }) } }) diff --git a/cli.js b/cli.js index ceb082c..82b0894 100755 --- a/cli.js +++ b/cli.js @@ -1,6 +1,6 @@ #!/usr/bin/env node -var argv = require('minimist')(process.argv.slice(2), {alias: {debug: ['d'], verbose: ['v']}}) +var argv = require('minimist')(process.argv.slice(2), { alias: { debug: [ 'd' ], verbose: [ 'v' ] } }) if (argv.help || argv.h) { // eslint-disable-next-line no-console @@ -31,7 +31,7 @@ if (argv.help || argv.h) { if (process.pid == 1) process.on('SIGINT', process.exit) var server = require('./index.js')(argv) - .listen(argv.port || 4567, argv.host || undefined, function() { + .listen(argv.port || 4567, argv.host || undefined, function () { var address = server.address(), protocol = argv.ssl ? 'https' : 'http' // eslint-disable-next-line no-console var host = argv.host || 'localhost' diff --git a/db/index.js b/db/index.js index 03f29d4..d97f657 100644 --- a/db/index.js +++ b/db/index.js @@ -1,13 +1,13 @@ var crypto = require('crypto'), - events = require('events'), - async = require('async'), - Lazy = require('lazy'), - levelup = require('levelup'), - memdown = require('memdown'), - sub = require('subleveldown'), - lock = require('lock'), - Big = require('big.js'), - once = require('once') + events = require('events'), + async = require('async'), + Lazy = require('lazy'), + levelup = require('levelup'), + memdown = require('memdown'), + sub = require('subleveldown'), + lock = require('lock'), + Big = require('big.js'), + once = require('once') exports.MAX_SIZE = 409600 // TODO: get rid of this? or leave for backwards compat? exports.create = create @@ -39,7 +39,7 @@ exports.queryTable = queryTable exports.updateIndexes = updateIndexes exports.getIndexActions = getIndexActions -function create(options) { +function create (options) { options = options || {} if (options.createTableMs == null) options.createTableMs = 500 if (options.deleteTableMs == null) options.deleteTableMs = 500 @@ -47,59 +47,60 @@ function create(options) { if (options.maxItemSizeKb == null) options.maxItemSizeKb = exports.MAX_SIZE / 1024 options.maxItemSize = options.maxItemSizeKb * 1024 + // eslint-disable-next-line var db = levelup(options.path ? require('leveldown')(options.path) : memdown()), - subDbs = Object.create(null), - tableDb = getSubDb('table') + subDbs = Object.create(null), + tableDb = getSubDb('table') // XXX: Is there a better way to get this? tableDb.awsAccountId = (process.env.AWS_ACCOUNT_ID || '0000-0000-0000').replace(/[^\d]/g, '') tableDb.awsRegion = process.env.AWS_REGION || process.env.AWS_DEFAULT_REGION || 'us-east-1' - function getItemDb(name) { + function getItemDb (name) { return getSubDb('item-' + name) } - function deleteItemDb(name, cb) { + function deleteItemDb (name, cb) { deleteSubDb('item-' + name, cb) } - function getIndexDb(indexType, tableName, indexName) { + function getIndexDb (indexType, tableName, indexName) { return getSubDb('index-' + indexType.toLowerCase() + '~' + tableName + '~' + indexName) } - function deleteIndexDb(indexType, tableName, indexName, cb) { + function deleteIndexDb (indexType, tableName, indexName, cb) { deleteSubDb('index-' + indexType.toLowerCase() + '~' + tableName + '~' + indexName, cb) } - function getTagDb(name) { + function getTagDb (name) { return getSubDb('tag-' + name) } - function deleteTagDb(name, cb) { + function deleteTagDb (name, cb) { deleteSubDb('tag-' + name, cb) } - function getSubDb(name) { + function getSubDb (name) { if (!subDbs[name]) { - subDbs[name] = sub(db, name, {valueEncoding: 'json'}) + subDbs[name] = sub(db, name, { valueEncoding: 'json' }) subDbs[name].lock = lock.Lock() } return subDbs[name] } - function deleteSubDb(name, cb) { + function deleteSubDb (name, cb) { cb = once(cb) var subDb = getSubDb(name) delete subDbs[name] - lazyStream(subDb.createKeyStream(), cb).join(function(keys) { - subDb.batch(keys.map(function(key) { return {type: 'del', key: key} }), cb) + lazyStream(subDb.createKeyStream(), cb).join(function (keys) { + subDb.batch(keys.map(function (key) { return { type: 'del', key: key } }), cb) }) } - function getTable(name, checkStatus, cb) { + function getTable (name, checkStatus, cb) { if (typeof checkStatus == 'function') cb = checkStatus - tableDb.get(name, function(err, table) { + tableDb.get(name, function (err, table) { if (!err && checkStatus && (table.TableStatus == 'CREATING' || table.TableStatus == 'DELETING')) { err = new Error('NotFoundError') err.name = 'NotFoundError' @@ -120,9 +121,9 @@ function create(options) { }) } - function recreate() { + function recreate () { var self = this, newStore = create(options) - Object.keys(newStore).forEach(function(key) { + Object.keys(newStore).forEach(function (key) { self[key] = newStore[key] }) } @@ -142,7 +143,7 @@ function create(options) { } } -function lazyStream(stream, errHandler) { +function lazyStream (stream, errHandler) { if (errHandler) stream.on('error', errHandler) var streamAsLazy = new Lazy(stream) stream.removeAllListeners('readable') @@ -151,18 +152,18 @@ function lazyStream(stream, errHandler) { return streamAsLazy } -function validateKey(dataKey, table, keySchema) { +function validateKey (dataKey, table, keySchema) { if (keySchema == null) keySchema = table.KeySchema if (keySchema.length != Object.keys(dataKey).length) { return validationError('The provided key element does not match the schema') } - return traverseKey(table, keySchema, function(attr, type, isHash) { + return traverseKey(table, keySchema, function (attr, type, isHash) { return validateKeyPiece(dataKey, attr, type, isHash) }) } -function validateItem(dataItem, table) { - return traverseKey(table, function(attr, type, isHash) { +function validateItem (dataItem, table) { + return traverseKey(table, function (attr, type, isHash) { if (dataItem[attr] == null) { return validationError('One or more parameter values were invalid: ' + 'Missing the key ' + attr + ' in the item') @@ -177,7 +178,7 @@ function validateItem(dataItem, table) { 'The AttributeValue for a key attribute cannot contain an empty ' + (type === 'S' ? 'string' : 'binary') + ' value. Key: ' + attr) } return checkKeySize(dataItem[attr][type], type, isHash) - }) || traverseIndexes(table, function(attr, type, index) { + }) || traverseIndexes(table, function (attr, type, index) { if (dataItem[attr] != null && dataItem[attr][type] == null) { return validationError('One or more parameter values were invalid: ' + 'Type mismatch for Index Key ' + attr + ' Expected: ' + type + @@ -186,10 +187,10 @@ function validateItem(dataItem, table) { }) } -function validateUpdates(attributeUpdates, expressionUpdates, table) { +function validateUpdates (attributeUpdates, expressionUpdates, table) { if (attributeUpdates == null && expressionUpdates == null) return - return traverseKey(table, function(attr) { + return traverseKey(table, function (attr) { var hasKey = false if (expressionUpdates) { var sections = expressionUpdates.sections @@ -199,14 +200,15 @@ function validateUpdates(attributeUpdates, expressionUpdates, table) { break } } - } else { + } + else { hasKey = attributeUpdates[attr] != null } if (hasKey) { return validationError('One or more parameter values were invalid: ' + 'Cannot update attribute ' + attr + '. This attribute is part of the key') } - }) || traverseIndexes(table, function(attr, type, index) { + }) || traverseIndexes(table, function (attr, type, index) { var actualType if (expressionUpdates) { var sections = expressionUpdates.sections @@ -217,7 +219,8 @@ function validateUpdates(attributeUpdates, expressionUpdates, table) { break } } - } else { + } + else { actualType = attributeUpdates[attr] && attributeUpdates[attr].Value ? Object.keys(attributeUpdates[attr].Value)[0] : null } @@ -229,7 +232,7 @@ function validateUpdates(attributeUpdates, expressionUpdates, table) { }) || validateKeyPaths((expressionUpdates || {}).nestedPaths, table) } -function validateKeyPiece(key, attr, type, isHash) { +function validateKeyPiece (key, attr, type, isHash) { if (key[attr] == null || key[attr][type] == null) { return validationError('The provided key element does not match the schema') } @@ -240,14 +243,14 @@ function validateKeyPiece(key, attr, type, isHash) { return checkKeySize(key[attr][type], type, isHash) } -function validateKeyPaths(nestedPaths, table) { +function validateKeyPaths (nestedPaths, table) { if (!nestedPaths) return - return traverseKey(table, function(attr) { + return traverseKey(table, function (attr) { if (nestedPaths[attr]) { return validationError('Key attributes must be scalars; ' + 'list random access \'[]\' and map lookup \'.\' are not allowed: Key: ' + attr) } - }) || traverseIndexes(table, function(attr) { + }) || traverseIndexes(table, function (attr) { if (nestedPaths[attr]) { return validationError('Key attributes must be scalars; ' + 'list random access \'[]\' and map lookup \'.\' are not allowed: IndexKey: ' + attr) @@ -255,23 +258,23 @@ function validateKeyPaths(nestedPaths, table) { }) } -function createKey(item, table, keySchema) { +function createKey (item, table, keySchema) { if (keySchema == null) keySchema = table.KeySchema var keyStr - traverseKey(table, keySchema, function(attr, type, isHash) { + traverseKey(table, keySchema, function (attr, type, isHash) { if (isHash) keyStr = hashPrefix(item[attr][type], type) + '/' keyStr += toRangeStr(item[attr][type], type) + '/' }) return keyStr } -function createIndexKey(item, table, keySchema) { +function createIndexKey (item, table, keySchema) { var tableKeyPieces = [] - traverseKey(table, function(attr, type) { tableKeyPieces.push(item[attr][type], type) }) + traverseKey(table, function (attr, type) { tableKeyPieces.push(item[attr][type], type) }) return createKey(item, table, keySchema) + hashPrefix.apply(this, tableKeyPieces) } -function traverseKey(table, keySchema, visitKey) { +function traverseKey (table, keySchema, visitKey) { if (typeof keySchema == 'function') { visitKey = keySchema; keySchema = table.KeySchema } var i, j, attr, type, found for (i = 0; i < keySchema.length; i++) { @@ -286,7 +289,7 @@ function traverseKey(table, keySchema, visitKey) { } } -function traverseIndexes(table, visitIndex) { +function traverseIndexes (table, visitIndex) { var i, j, k, attr, type, found if (table.GlobalSecondaryIndexes) { for (i = 0; i < table.GlobalSecondaryIndexes.length; i++) { @@ -316,7 +319,7 @@ function traverseIndexes(table, visitIndex) { } } -function checkKeySize(keyPiece, type, isHash) { +function checkKeySize (keyPiece, type, isHash) { // Numbers are always fine if (type == 'N') return null if (type == 'B') keyPiece = Buffer.from(keyPiece, 'base64') @@ -328,7 +331,7 @@ function checkKeySize(keyPiece, type, isHash) { 'Aggregated size of all range keys has exceeded the size limit of 1024 bytes') } -function toRangeStr(keyPiece, type) { +function toRangeStr (keyPiece, type) { if (type == null) { type = Object.keys(keyPiece)[0] keyPiece = keyPiece[type] @@ -347,7 +350,7 @@ function toRangeStr(keyPiece, type) { // Digits are unchanged if sign is positive, or added to 10 if negative // Hence, in '07c009', the sign is negative, exponent is 125 - 124 = 1, digits are 10 + -0.09 = 9.91 => -9.91e1 // -function toLexiStr(keyPiece, type) { +function toLexiStr (keyPiece, type) { if (keyPiece == null) return '' if (type == null) { type = Object.keys(keyPiece)[0] @@ -356,52 +359,59 @@ function toLexiStr(keyPiece, type) { if (type == 'B') return Buffer.from(keyPiece, 'base64').toString('hex') if (type != 'N') return keyPiece var bigNum = new Big(keyPiece), digits, - exp = !bigNum.c[0] ? 0 : bigNum.s == -1 ? 125 - bigNum.e : 130 + bigNum.e + exp = !bigNum.c[0] ? 0 : bigNum.s == -1 ? 125 - bigNum.e : 130 + bigNum.e if (bigNum.s == -1) { bigNum.e = 0 digits = new Big(10).plus(bigNum).toFixed().replace(/\./, '') - } else { + } + else { digits = bigNum.c.join('') } return (bigNum.s == -1 ? '0' : '1') + ('0' + exp.toString(16)).slice(-2) + digits } -function hashPrefix(hashKey, hashType, rangeKey, rangeType) { +function hashPrefix (hashKey, hashType, rangeKey, rangeType) { if (hashType == 'S') { hashKey = Buffer.from(hashKey, 'utf8') - } else if (hashType == 'N') { + } + else if (hashType == 'N') { hashKey = numToBuffer(hashKey) - } else if (hashType == 'B') { + } + else if (hashType == 'B') { hashKey = Buffer.from(hashKey, 'base64') } if (rangeKey) { if (rangeType == 'S') { rangeKey = Buffer.from(rangeKey, 'utf8') - } else if (rangeType == 'N') { + } + else if (rangeType == 'N') { rangeKey = numToBuffer(rangeKey) - } else if (rangeType == 'B') { + } + else if (rangeType == 'B') { rangeKey = Buffer.from(rangeKey, 'base64') } - } else { + } + else { rangeKey = Buffer.from([]) } // TODO: Can use the whole hash if we deem it important - for now just first six chars return crypto.createHash('md5').update('Outliers').update(hashKey).update(rangeKey).digest('hex').slice(0, 6) } -function numToBuffer(num) { - if (+num === 0) return Buffer.from([-128]) +function numToBuffer (num) { + if (+num === 0) return Buffer.from([ -128 ]) num = new Big(num) var scale = num.s, mantissa = num.c, exponent = num.e + 1, appendZero = exponent % 2 ? 1 : 0, - byteArrayLengthWithoutExponent = Math.floor((mantissa.length + appendZero + 1) / 2), - byteArray, appendedZero = false, mantissaIndex, byteArrayIndex + byteArrayLengthWithoutExponent = Math.floor((mantissa.length + appendZero + 1) / 2), + byteArray, appendedZero = false, mantissaIndex, byteArrayIndex if (byteArrayLengthWithoutExponent < 20 && scale == -1) { byteArray = new Array(byteArrayLengthWithoutExponent + 2) byteArray[byteArrayLengthWithoutExponent + 1] = 102 - } else { + } + else { byteArray = new Array(byteArrayLengthWithoutExponent + 1) } @@ -415,9 +425,11 @@ function numToBuffer(num) { byteArray[byteArrayIndex] = 0 appendedZero = true mantissaIndex-- - } else if ((mantissaIndex + appendZero) % 2 === 0) { + } + else if ((mantissaIndex + appendZero) % 2 === 0) { byteArray[byteArrayIndex] = mantissa[mantissaIndex] * 10 - } else { + } + else { byteArray[byteArrayIndex] += mantissa[mantissaIndex] } if (((mantissaIndex + appendZero) % 2) || (mantissaIndex == mantissa.length - 1)) { @@ -431,7 +443,7 @@ function numToBuffer(num) { return Buffer.from(byteArray) } -function checkConditional(data, existingItem) { +function checkConditional (data, existingItem) { existingItem = existingItem || {} if (data._condition) { @@ -439,7 +451,8 @@ function checkConditional(data, existingItem) { return conditionalError() } return null - } else if (!data.Expected) { + } + else if (!data.Expected) { return null } if (!matchesFilter(existingItem, data.Expected, data.ConditionalOperator)) { @@ -447,7 +460,7 @@ function checkConditional(data, existingItem) { } } -function validationError(msg) { +function validationError (msg) { var err = new Error(msg) err.statusCode = 400 err.body = { @@ -457,7 +470,7 @@ function validationError(msg) { return err } -function conditionalError(msg) { +function conditionalError (msg) { if (msg == null) msg = 'The conditional request failed' var err = new Error(msg) err.statusCode = 400 @@ -468,7 +481,7 @@ function conditionalError(msg) { return err } -function limitError(msg) { +function limitError (msg) { var err = new Error(msg) err.statusCode = 400 err.body = { @@ -478,11 +491,11 @@ function limitError(msg) { return err } -function itemSize(item, compress, addMetaSize, rangeKey) { +function itemSize (item, compress, addMetaSize, rangeKey) { // Size of compressed item (for checking query/scan limit) seems complicated, // probably due to some internal serialization format. var rangeKeySize = 0 - var size = Object.keys(item).reduce(function(sum, attr) { + var size = Object.keys(item).reduce(function (sum, attr) { var size = valSizeWithStorage(item[attr], compress && attr != rangeKey) if (compress && attr == rangeKey) { rangeKeySize = size @@ -493,70 +506,70 @@ function itemSize(item, compress, addMetaSize, rangeKey) { return !addMetaSize ? size : 2 + size + ((1 + Math.floor((1 + size) / 3072)) * (18 + rangeKeySize)) } -function valSizeWithStorage(itemAttr, compress) { +function valSizeWithStorage (itemAttr, compress) { var type = Object.keys(itemAttr)[0] var val = itemAttr[type] var size = valSize(val, type, compress) if (!compress) return size switch (type) { - case 'S': - return size + (size < 128 ? 1 : size < 16384 ? 2 : 3) - case 'B': - return size + 1 - case 'N': - return size + 1 - case 'SS': - return size + val.length + 1 - case 'BS': - return size + val.length + 1 - case 'NS': - return size + val.length + 1 - case 'NULL': - return 0 - case 'BOOL': - return 1 - case 'L': - return size - case 'M': - return size - } -} - -function valSize(val, type, compress) { + case 'S': + return size + (size < 128 ? 1 : size < 16384 ? 2 : 3) + case 'B': + return size + 1 + case 'N': + return size + 1 + case 'SS': + return size + val.length + 1 + case 'BS': + return size + val.length + 1 + case 'NS': + return size + val.length + 1 + case 'NULL': + return 0 + case 'BOOL': + return 1 + case 'L': + return size + case 'M': + return size + } +} + +function valSize (val, type, compress) { switch (type) { - case 'S': - return val.length - case 'B': - return Buffer.from(val, 'base64').length - case 'N': - val = new Big(val) - var numDigits = val.c.length - if (numDigits == 1 && val.c[0] === 0) return 1 - return 1 + Math.ceil(numDigits / 2) + (numDigits % 2 || val.e % 2 ? 0 : 1) + (val.s == -1 ? 1 : 0) - case 'SS': - return val.reduce(function(sum, x) { return sum + valSize(x, 'S') }, 0) // eslint-disable-line no-loop-func - case 'BS': - return val.reduce(function(sum, x) { return sum + valSize(x, 'B') }, 0) // eslint-disable-line no-loop-func - case 'NS': - return val.reduce(function(sum, x) { return sum + valSize(x, 'N') }, 0) // eslint-disable-line no-loop-func - case 'NULL': - return 1 - case 'BOOL': - return 1 - case 'L': - return 3 + val.reduce(function(sum, val) { return sum + 1 + valSizeWithStorage(val, compress) }, 0) - case 'M': - return 3 + Object.keys(val).length + itemSize(val, compress) - } -} - -function capacityUnits(item, isRead, isConsistent) { + case 'S': + return val.length + case 'B': + return Buffer.from(val, 'base64').length + case 'N': + val = new Big(val) + var numDigits = val.c.length + if (numDigits == 1 && val.c[0] === 0) return 1 + return 1 + Math.ceil(numDigits / 2) + (numDigits % 2 || val.e % 2 ? 0 : 1) + (val.s == -1 ? 1 : 0) + case 'SS': + return val.reduce(function (sum, x) { return sum + valSize(x, 'S') }, 0) // eslint-disable-line no-loop-func + case 'BS': + return val.reduce(function (sum, x) { return sum + valSize(x, 'B') }, 0) // eslint-disable-line no-loop-func + case 'NS': + return val.reduce(function (sum, x) { return sum + valSize(x, 'N') }, 0) // eslint-disable-line no-loop-func + case 'NULL': + return 1 + case 'BOOL': + return 1 + case 'L': + return 3 + val.reduce(function (sum, val) { return sum + 1 + valSizeWithStorage(val, compress) }, 0) + case 'M': + return 3 + Object.keys(val).length + itemSize(val, compress) + } +} + +function capacityUnits (item, isRead, isConsistent) { var size = item ? Math.ceil(itemSize(item) / 1024 / (isRead ? 4 : 1)) : 1 return size / (!isRead || isConsistent ? 1 : 2) } -function addConsumedCapacity(data, isRead, newItem, oldItem) { - if (~['TOTAL', 'INDEXES'].indexOf(data.ReturnConsumedCapacity)) { +function addConsumedCapacity (data, isRead, newItem, oldItem) { + if (~[ 'TOTAL', 'INDEXES' ].indexOf(data.ReturnConsumedCapacity)) { var capacity = capacityUnits(newItem, isRead, data.ConsistentRead) if (oldItem != null) { capacity = Math.max(capacity, capacityUnits(oldItem, isRead, data.ConsistentRead)) @@ -564,71 +577,81 @@ function addConsumedCapacity(data, isRead, newItem, oldItem) { return { CapacityUnits: capacity, TableName: data.TableName, - Table: data.ReturnConsumedCapacity == 'INDEXES' ? {CapacityUnits: capacity} : undefined, + Table: data.ReturnConsumedCapacity == 'INDEXES' ? { CapacityUnits: capacity } : undefined, } } } -function valsEqual(val1, val2) { +function valsEqual (val1, val2) { if (Array.isArray(val1) && Array.isArray(val2)) { if (val1.length != val2.length) return false - return val1.every(function(val) { return ~val2.indexOf(val) }) - } else { + return val1.every(function (val) { return ~val2.indexOf(val) }) + } + else { return val1 == val2 } } -function matchesFilter(val, filter, conditionalOperator) { +function matchesFilter (val, filter, conditionalOperator) { for (var attr in filter) { var comp = filter[attr].Exists != null ? (filter[attr].Exists ? 'NOT_NULL' : 'NULL') : filter[attr].ComparisonOperator || 'EQ' var result = compare(comp, val[attr], filter[attr].AttributeValueList || filter[attr].Value) if (!result) { return false - } else if (conditionalOperator == 'OR') { + } + else if (conditionalOperator == 'OR') { return true } } return true } -function matchesExprFilter(item, expr) { +function matchesExprFilter (item, expr) { if (expr.type == 'and') { return matchesExprFilter(item, expr.args[0]) && matchesExprFilter(item, expr.args[1]) - } else if (expr.type == 'or') { + } + else if (expr.type == 'or') { return matchesExprFilter(item, expr.args[0]) || matchesExprFilter(item, expr.args[1]) - } else if (expr.type == 'not') { + } + else if (expr.type == 'not') { return !matchesExprFilter(item, expr.args[0]) } - var args = expr.args.map(function(arg) { return resolveArg(arg, item) }) + var args = expr.args.map(function (arg) { return resolveArg(arg, item) }) return compare(expr.type == 'function' ? expr.name : expr.type, args[0], args.slice(1)) } -function resolveArg(arg, item) { +function resolveArg (arg, item) { if (Array.isArray(arg)) { return mapPath(arg, item) - } else if (arg.type == 'function' && arg.name == 'size') { - var args = arg.args.map(function(arg) { return resolveArg(arg, item) }) + } + else if (arg.type == 'function' && arg.name == 'size') { + var args = arg.args.map(function (arg) { return resolveArg(arg, item) }) var val = args[0], length if (!val) { return null - } else if (val.S) { + } + else if (val.S) { length = val.S.length - } else if (val.B) { + } + else if (val.B) { length = Buffer.from(val.B, 'base64').length - } else if (val.SS || val.BS || val.NS || val.L) { + } + else if (val.SS || val.BS || val.NS || val.L) { length = (val.SS || val.BS || val.NS || val.L).length - } else if (val.M) { + } + else if (val.M) { length = Object.keys(val.M).length } - return length != null ? {N: length.toString()} : null - } else { + return length != null ? { N: length.toString() } : null + } + else { return arg } } -function compare(comp, val, compVals) { - if (!Array.isArray(compVals)) compVals = [compVals] +function compare (comp, val, compVals) { + if (!Array.isArray(compVals)) compVals = [ compVals ] var attrType = val ? Object.keys(val)[0] : null var attrVal = attrType ? val[attrType] : null @@ -636,98 +659,98 @@ function compare(comp, val, compVals) { var compVal = compType ? compVals[0][compType] : null switch (comp) { - case 'EQ': - case '=': - if (compType != attrType || !valsEqual(attrVal, compVal)) return false - break - case 'NE': - case '<>': - if (compType == attrType && valsEqual(attrVal, compVal)) return false - break - case 'LE': - case '<=': - if (compType != attrType || + case 'EQ': + case '=': + if (compType != attrType || !valsEqual(attrVal, compVal)) return false + break + case 'NE': + case '<>': + if (compType == attrType && valsEqual(attrVal, compVal)) return false + break + case 'LE': + case '<=': + if (compType != attrType || (attrType == 'N' && !new Big(attrVal).lte(compVal)) || (attrType != 'N' && toLexiStr(attrVal, attrType) > toLexiStr(compVal, attrType))) return false - break - case 'LT': - case '<': - if (compType != attrType || + break + case 'LT': + case '<': + if (compType != attrType || (attrType == 'N' && !new Big(attrVal).lt(compVal)) || (attrType != 'N' && toLexiStr(attrVal, attrType) >= toLexiStr(compVal, attrType))) return false - break - case 'GE': - case '>=': - if (compType != attrType || + break + case 'GE': + case '>=': + if (compType != attrType || (attrType == 'N' && !new Big(attrVal).gte(compVal)) || (attrType != 'N' && toLexiStr(attrVal, attrType) < toLexiStr(compVal, attrType))) return false - break - case 'GT': - case '>': - if (compType != attrType || + break + case 'GT': + case '>': + if (compType != attrType || (attrType == 'N' && !new Big(attrVal).gt(compVal)) || (attrType != 'N' && toLexiStr(attrVal, attrType) <= toLexiStr(compVal, attrType))) return false - break - case 'NOT_NULL': - case 'attribute_exists': - if (attrVal == null) return false - break - case 'NULL': - case 'attribute_not_exists': - if (attrVal != null) return false - break - case 'CONTAINS': - case 'contains': - return contains(compType, compVal, attrType, attrVal) - case 'NOT_CONTAINS': - return !contains(compType, compVal, attrType, attrVal) - case 'BEGINS_WITH': - case 'begins_with': - if (compType != attrType) return false - if (compType == 'B') { - attrVal = Buffer.from(attrVal, 'base64').toString() - compVal = Buffer.from(compVal, 'base64').toString() - } - if (attrVal.indexOf(compVal) !== 0) return false - break - case 'IN': - case 'in': - if (!attrVal) return false - if (!compVals.some(function(compVal) { - compType = Object.keys(compVal)[0] - compVal = compVal[compType] - return compType == attrType && valsEqual(attrVal, compVal) - })) return false - break - case 'BETWEEN': - case 'between': - if (!attrVal || compType != attrType || + break + case 'NOT_NULL': + case 'attribute_exists': + if (attrVal == null) return false + break + case 'NULL': + case 'attribute_not_exists': + if (attrVal != null) return false + break + case 'CONTAINS': + case 'contains': + return contains(compType, compVal, attrType, attrVal) + case 'NOT_CONTAINS': + return !contains(compType, compVal, attrType, attrVal) + case 'BEGINS_WITH': + case 'begins_with': + if (compType != attrType) return false + if (compType == 'B') { + attrVal = Buffer.from(attrVal, 'base64').toString() + compVal = Buffer.from(compVal, 'base64').toString() + } + if (attrVal.indexOf(compVal) !== 0) return false + break + case 'IN': + case 'in': + if (!attrVal) return false + if (!compVals.some(function (compVal) { + compType = Object.keys(compVal)[0] + compVal = compVal[compType] + return compType == attrType && valsEqual(attrVal, compVal) + })) return false + break + case 'BETWEEN': + case 'between': + if (!attrVal || compType != attrType || (attrType == 'N' && (!new Big(attrVal).gte(compVal) || !new Big(attrVal).lte(compVals[1].N))) || (attrType != 'N' && (toLexiStr(attrVal, attrType) < toLexiStr(compVal, attrType) || toLexiStr(attrVal, attrType) > toLexiStr(compVals[1][compType], attrType)))) return false - break - case 'attribute_type': - if (!attrVal || !valsEqual(attrType, compVal)) return false + break + case 'attribute_type': + if (!attrVal || !valsEqual(attrType, compVal)) return false } return true } -function contains(compType, compVal, attrType, attrVal) { +function contains (compType, compVal, attrType, attrVal) { if (compType === 'S') { if (attrType === 'S') return !!~attrVal.indexOf(compVal) - if (attrType === 'SS') return attrVal.some(function(val) { + if (attrType === 'SS') return attrVal.some(function (val) { return val === compVal }) - if (attrType === 'L') return attrVal.some(function(val) { + if (attrType === 'L') return attrVal.some(function (val) { return val && val.S && val.S === compVal }) return false } if (compType === 'N') { - if (attrType === 'NS') return attrVal.some(function(val) { + if (attrType === 'NS') return attrVal.some(function (val) { return val === compVal }) - if (attrType === 'L') return attrVal.some(function(val) { + if (attrType === 'L') return attrVal.some(function (val) { return val && val.N && val.N === compVal }) return false @@ -739,7 +762,7 @@ function contains(compType, compVal, attrType, attrVal) { var attrValString = Buffer.from(attrVal, 'base64').toString() return !!~attrValString.indexOf(compValString) } - return attrVal.some(function(val) { + return attrVal.some(function (val) { if (attrType !== 'L') return compValString === Buffer.from(val, 'base64').toString() if (attrType === 'L' && val.B) return compValString === Buffer.from(val.B, 'base64').toString() return false @@ -747,11 +770,11 @@ function contains(compType, compVal, attrType, attrVal) { } } -function mapPaths(paths, item) { +function mapPaths (paths, item) { var returnItem = Object.create(null), toSquash = [] for (var i = 0; i < paths.length; i++) { var path = paths[i] - if (!Array.isArray(path)) path = [path] + if (!Array.isArray(path)) path = [ path ] var resolved = mapPath(path, item) if (resolved == null) { continue @@ -760,7 +783,7 @@ function mapPaths(paths, item) { returnItem[path[0]] = resolved continue } - var curItem = {M: returnItem} + var curItem = { M: returnItem } for (var j = 0; j < path.length; j++) { var piece = path[j] if (typeof piece == 'number') { @@ -771,36 +794,41 @@ function mapPaths(paths, item) { if (j < paths[i].length - 1) { curItem.L[piece] = curItem.L[piece] || {} curItem = curItem.L[piece] - } else { + } + else { curItem.L[piece] = resolved } - } else { + } + else { curItem.M = curItem.M || {} if (j < paths[i].length - 1) { curItem.M[piece] = curItem.M[piece] || {} curItem = curItem.M[piece] - } else { + } + else { curItem.M[piece] = resolved } } } } - toSquash.forEach(function(obj) { obj.L = obj.L.filter(Boolean) }) + toSquash.forEach(function (obj) { obj.L = obj.L.filter(Boolean) }) return returnItem } -function mapPath(path, item) { +function mapPath (path, item) { if (path.length == 1) { return item[path[0]] } - var resolved = {M: item} + var resolved = { M: item } for (var i = 0; i < path.length; i++) { var piece = path[i] if (typeof piece == 'number' && resolved.L) { resolved = resolved.L[piece] - } else if (resolved.M) { + } + else if (resolved.M) { resolved = resolved.M[piece] - } else { + } + else { resolved = null } if (resolved == null) { @@ -810,28 +838,29 @@ function mapPath(path, item) { return resolved } -function queryTable(store, table, data, opts, isLocal, fetchFromItemDb, startKeyNames, cb) { +function queryTable (store, table, data, opts, isLocal, fetchFromItemDb, startKeyNames, cb) { cb = once(cb) var itemDb = store.getItemDb(data.TableName), vals if (data.IndexName) { var indexDb = store.getIndexDb(isLocal ? 'local' : 'global', data.TableName, data.IndexName) vals = lazyStream(indexDb.createValueStream(opts), cb) - } else { + } + else { vals = lazyStream(itemDb.createValueStream(opts), cb) } var tableCapacity = 0, indexCapacity = 0, - calculateCapacity = ~['TOTAL', 'INDEXES'].indexOf(data.ReturnConsumedCapacity) + calculateCapacity = ~[ 'TOTAL', 'INDEXES' ].indexOf(data.ReturnConsumedCapacity) if (fetchFromItemDb) { var em = new events.EventEmitter - var queue = async.queue(function(key, cb) { + var queue = async.queue(function (key, cb) { if (!key) { em.emit('end') return cb() } - itemDb.get(key, function(err, item) { + itemDb.get(key, function (err, item) { if (err) { em.emit('error', err) return cb(err) @@ -844,7 +873,7 @@ function queryTable(store, table, data, opts, isLocal, fetchFromItemDb, startKey var oldVals = vals vals = new Lazy(em) - oldVals.map(function(item) { + oldVals.map(function (item) { if (calculateCapacity) indexCapacity += itemSize(item) queue.push(createKey(item, table)) }).once('pipe', queue.push.bind(queue, '')) @@ -852,7 +881,7 @@ function queryTable(store, table, data, opts, isLocal, fetchFromItemDb, startKey var size = 0, count = 0, rangeKey = table.KeySchema[1] && table.KeySchema[1].AttributeName - vals = vals.takeWhile(function(val) { + vals = vals.takeWhile(function (val) { if (count >= data.Limit || size >= 1024 * 1024) { return false } @@ -861,7 +890,8 @@ function queryTable(store, table, data, opts, isLocal, fetchFromItemDb, startKey var capacitySize = itemSize(val) if (data.IndexName) { indexCapacity += capacitySize - } else { + } + else { tableCapacity += capacitySize } } @@ -873,22 +903,23 @@ function queryTable(store, table, data, opts, isLocal, fetchFromItemDb, startKey return true }) - vals.join(function(items) { + vals.join(function (items) { var lastItem = items[items.length - 1] var queryFilter = data.QueryFilter || data.ScanFilter if (data._filter) { - items = items.filter(function(val) { return matchesExprFilter(val, data._filter.expression) }) - } else if (queryFilter) { - items = items.filter(function(val) { return matchesFilter(val, queryFilter, data.ConditionalOperator) }) + items = items.filter(function (val) { return matchesExprFilter(val, data._filter.expression) }) + } + else if (queryFilter) { + items = items.filter(function (val) { return matchesFilter(val, queryFilter, data.ConditionalOperator) }) } - var result = {ScannedCount: count} + var result = { ScannedCount: count } if (count >= data.Limit || size >= 1024 * 1024) { if (data.Limit) items.splice(data.Limit) if (lastItem) { - result.LastEvaluatedKey = startKeyNames.reduce(function(key, attr) { + result.LastEvaluatedKey = startKeyNames.reduce(function (key, attr) { key[attr] = lastItem[attr] return key }, {}) @@ -910,11 +941,11 @@ function queryTable(store, table, data, opts, isLocal, fetchFromItemDb, startKey TableName: data.TableName, } if (data.ReturnConsumedCapacity == 'INDEXES') { - result.ConsumedCapacity.Table = {CapacityUnits: tableUnits} + result.ConsumedCapacity.Table = { CapacityUnits: tableUnits } if (data.IndexName) { var indexAttr = isLocal ? 'LocalSecondaryIndexes' : 'GlobalSecondaryIndexes' result.ConsumedCapacity[indexAttr] = {} - result.ConsumedCapacity[indexAttr][data.IndexName] = {CapacityUnits: indexUnits} + result.ConsumedCapacity[indexAttr][data.IndexName] = { CapacityUnits: indexUnits } } } } @@ -922,52 +953,52 @@ function queryTable(store, table, data, opts, isLocal, fetchFromItemDb, startKey }) } -function updateIndexes(store, table, existingItem, item, cb) { +function updateIndexes (store, table, existingItem, item, cb) { if (!existingItem && !item) return cb() var puts = [], deletes = [] - ;['Local', 'Global'].forEach(function(indexType) { + ;[ 'Local', 'Global' ].forEach(function (indexType) { var indexes = table[indexType + 'SecondaryIndexes'] || [] var actions = getIndexActions(indexes, existingItem, item, table) - puts = puts.concat(actions.puts.map(function(action) { + puts = puts.concat(actions.puts.map(function (action) { var indexDb = store.getIndexDb(indexType, table.TableName, action.index) return indexDb.put.bind(indexDb, action.key, action.item) })) - deletes = deletes.concat(actions.deletes.map(function(action) { + deletes = deletes.concat(actions.deletes.map(function (action) { var indexDb = store.getIndexDb(indexType, table.TableName, action.index) return indexDb.del.bind(indexDb, action.key) })) }) - async.parallel(deletes, function(err) { + async.parallel(deletes, function (err) { if (err) return cb(err) async.parallel(puts, cb) }) } -function getIndexActions(indexes, existingItem, item, table) { - var puts = [], deletes = [], tableKeys = table.KeySchema.map(function(key) { return key.AttributeName }) - indexes.forEach(function(index) { - var indexKeys = index.KeySchema.map(function(key) { return key.AttributeName }), key = null, itemPieces = item +function getIndexActions (indexes, existingItem, item, table) { + var puts = [], deletes = [], tableKeys = table.KeySchema.map(function (key) { return key.AttributeName }) + indexes.forEach(function (index) { + var indexKeys = index.KeySchema.map(function (key) { return key.AttributeName }), key = null, itemPieces = item - if (item && indexKeys.every(function(key) { return item[key] != null })) { + if (item && indexKeys.every(function (key) { return item[key] != null })) { if (index.Projection.ProjectionType != 'ALL') { var indexAttrs = indexKeys.concat(tableKeys, index.Projection.NonKeyAttributes || []) - itemPieces = indexAttrs.reduce(function(obj, attr) { + itemPieces = indexAttrs.reduce(function (obj, attr) { obj[attr] = item[attr] return obj }, Object.create(null)) } key = createIndexKey(itemPieces, table, index.KeySchema) - puts.push({index: index.IndexName, key: key, item: itemPieces}) + puts.push({ index: index.IndexName, key: key, item: itemPieces }) } - if (existingItem && indexKeys.every(function(key) { return existingItem[key] != null })) { + if (existingItem && indexKeys.every(function (key) { return existingItem[key] != null })) { var existingKey = createIndexKey(existingItem, table, index.KeySchema) if (existingKey != key) { - deletes.push({index: index.IndexName, key: existingKey}) + deletes.push({ index: index.IndexName, key: existingKey }) } } }) - return {puts: puts, deletes: deletes} + return { puts: puts, deletes: deletes } } diff --git a/index.js b/index.js index 37f36f2..4ec2f06 100644 --- a/index.js +++ b/index.js @@ -1,27 +1,27 @@ var http = require('http'), - https = require('https'), - fs = require('fs'), - path = require('path'), - url = require('url'), - crypto = require('crypto'), - crc32 = require('buffer-crc32'), - validations = require('./validations'), - db = require('./db') + https = require('https'), + fs = require('fs'), + path = require('path'), + url = require('url'), + crypto = require('crypto'), + crc32 = require('buffer-crc32'), + validations = require('./validations'), + db = require('./db') var MAX_REQUEST_BYTES = 16 * 1024 * 1024 var verbose = false var debug = false -var validApis = ['DynamoDB_20111205', 'DynamoDB_20120810'], - validOperations = ['BatchGetItem', 'BatchWriteItem', 'CreateTable', 'DeleteItem', 'DeleteTable', - 'DescribeTable', 'DescribeTimeToLive', 'GetItem', 'ListTables', 'PutItem', 'Query', 'Scan', 'TagResource', - 'UntagResource', 'ListTagsOfResource', 'UpdateItem', 'UpdateTable'], - actions = {}, - actionValidations = {} +var validApis = [ 'DynamoDB_20111205', 'DynamoDB_20120810' ], + validOperations = [ 'BatchGetItem', 'BatchWriteItem', 'CreateTable', 'DeleteItem', 'DeleteTable', + 'DescribeTable', 'DescribeTimeToLive', 'GetItem', 'ListTables', 'PutItem', 'Query', 'Scan', 'TagResource', + 'UntagResource', 'ListTagsOfResource', 'UpdateItem', 'UpdateTable' ], + actions = {}, + actionValidations = {} module.exports = dynalite -function dynalite(options) { +function dynalite (options) { options = options || {} if (options.verbose) verbose = true if (options.debug) debug = true @@ -33,17 +33,18 @@ function dynalite(options) { options.cert = options.cert || fs.readFileSync(path.join(__dirname, 'ssl', 'server-crt.pem')) options.ca = options.ca || fs.readFileSync(path.join(__dirname, 'ssl', 'ca-crt.pem')) server = https.createServer(options, requestHandler) - } else { + } + else { server = http.createServer(requestHandler) } // Ensure we close DB when we're closing the server too var httpServerClose = server.close, httpServerListen = server.listen - server.close = function(cb) { - store.db.close(function(err) { + server.close = function (cb) { + store.db.close(function (err) { if (err) return cb(err) // Recreate the store if the user wants to listen again - server.listen = function() { + server.listen = function () { store.recreate() httpServerListen.apply(server, arguments) } @@ -54,20 +55,22 @@ function dynalite(options) { return server } -validOperations.forEach(function(action) { +validOperations.forEach(function (action) { action = validations.toLowerFirst(action) + // eslint-disable-next-line actions[action] = require('./actions/' + action) + // eslint-disable-next-line actionValidations[action] = require('./validations/' + action) }) -function rand52CharId() { +function rand52CharId () { // 39 bytes turns into 52 base64 characters var bytes = crypto.randomBytes(39) // Need to replace + and / so just choose 0, obvs won't be truly random, whatevs return bytes.toString('base64').toUpperCase().replace(/\+|\//g, '0') } -function sendData(req, res, data, statusCode) { +function sendData (req, res, data, statusCode) { var body = JSON.stringify(data) req.removeAllListeners() res.statusCode = statusCode || 200 @@ -80,10 +83,10 @@ function sendData(req, res, data, statusCode) { res.end(body) } -function httpHandler(store, req, res) { +function httpHandler (store, req, res) { var body - req.on('error', function(err) { throw err }) - req.on('data', function(data) { + req.on('error', function (err) { throw err }) + req.on('data', function (data) { var newLength = data.length + (body ? body.length : 0) if (newLength > MAX_REQUEST_BYTES) { req.removeAllListeners() @@ -91,14 +94,14 @@ function httpHandler(store, req, res) { res.setHeader('Transfer-Encoding', 'chunked') return res.end() } - body = body ? Buffer.concat([body, data], newLength) : data + body = body ? Buffer.concat([ body, data ], newLength) : data }) - req.on('end', function() { + req.on('end', function () { body = body ? body.toString() : '' if (debug) { - console.error('[Dynalite] Incoming request:', {headers: req.headers, body: body}) + console.error('[Dynalite] Incoming request:', { headers: req.headers, body: body }) } // All responses after this point have a RequestId @@ -149,15 +152,16 @@ function httpHandler(store, req, res) { if (body) { try { data = JSON.parse(body) - } catch (e) { - return sendData(req, res, {__type: 'com.amazon.coral.service#SerializationException'}, 400) + } + catch (e) { + return sendData(req, res, { __type: 'com.amazon.coral.service#SerializationException' }, 400) } } var target = (req.headers['x-amz-target'] || '').split('.') if (target.length != 2 || !~validApis.indexOf(target[0]) || !~validOperations.indexOf(target[1])) - return sendData(req, res, {__type: 'com.amazon.coral.service#UnknownOperationException'}, 400) + return sendData(req, res, { __type: 'com.amazon.coral.service#UnknownOperationException' }, 400) var authHeader = req.headers.authorization var query = url.parse(req.url, true).query @@ -181,13 +185,13 @@ function httpHandler(store, req, res) { // TODO: Go through key-vals first // "'Credential' not a valid key=value pair (missing equal-sign) in Authorization header: 'AWS4-HMAC-SHA256 \ // Signature=b, Credential, SignedHeaders'." - params = ['Credential', 'Signature', 'SignedHeaders'] - var authParams = authHeader.split(/,| /).slice(1).filter(Boolean).reduce(function(obj, x) { + params = [ 'Credential', 'Signature', 'SignedHeaders' ] + var authParams = authHeader.split(/,| /).slice(1).filter(Boolean).reduce(function (obj, x) { var keyVal = x.trim().split('=') obj[keyVal[0]] = keyVal[1] return obj }, {}) - params.forEach(function(param) { + params.forEach(function (param) { if (!authParams[param]) // TODO: SignedHeaders *is* allowed to be an empty string at this point msg += 'Authorization header requires \'' + param + '\' parameter. ' @@ -196,9 +200,10 @@ function httpHandler(store, req, res) { msg += 'Authorization header requires existence of either a \'X-Amz-Date\' or a \'Date\' header. ' if (msg) msg += 'Authorization=' + authHeader - } else { - params = ['X-Amz-Algorithm', 'X-Amz-Credential', 'X-Amz-Signature', 'X-Amz-SignedHeaders', 'X-Amz-Date'] - params.forEach(function(param) { + } + else { + params = [ 'X-Amz-Algorithm', 'X-Amz-Credential', 'X-Amz-Signature', 'X-Amz-SignedHeaders', 'X-Amz-Date' ] + params.forEach(function (param) { if (!query[param]) msg += 'AWS query-string parameters must include \'' + param + '\'. ' }) @@ -255,14 +260,15 @@ function httpHandler(store, req, res) { // For some reason, the serialization checks seem to be a bit out of sync if (!body) - return sendData(req, res, {__type: 'com.amazon.coral.service#SerializationException'}, 400) + return sendData(req, res, { __type: 'com.amazon.coral.service#SerializationException' }, 400) var action = validations.toLowerFirst(target[1]) var actionValidation = actionValidations[action] try { data = validations.checkTypes(data, actionValidation.types) validations.checkValidations(data, actionValidation.types, actionValidation.custom, store) - } catch (err) { + } + catch (err) { if (err.statusCode) { if (verbose) console.error('[Dynalite] Validation error', err.body) return sendData(req, res, err.body, err.statusCode) @@ -270,7 +276,7 @@ function httpHandler(store, req, res) { throw err } - actions[action](store, data, function(err, data) { + actions[action](store, data, function (err, data) { if (err && err.statusCode) { if (verbose) console.error('[Dynalite] API error', err.body) return sendData(req, res, err.body, err.statusCode) diff --git a/package.json b/package.json index 921990b..3851b1d 100644 --- a/package.json +++ b/package.json @@ -12,7 +12,7 @@ "bin": "cli.js", "scripts": { "build": "for file in ./db/*.pegjs; do pegjs \"$file\"; done", - "test": "mocha --require should --reporter spec -t $([ $REMOTE ] && echo 30s || echo 4s)", + "test": "npm run lint && mocha --require should --reporter spec -t $([ $REMOTE ] && echo 30s || echo 4s)", "coverage": "npx nyc@latest mocha --require should -t 4s", "lint": "eslint . --fix" }, @@ -55,5 +55,14 @@ "mock", "serverless", "test" - ] + ], + "eslintConfig": { + "extends": "@architect/eslint-config", + "env": { + "mocha": true + }, + "rules": { + "filenames/match-regex": [ "error", "^[a-zA-Z0-9-_.]+$", true ] + } + } } diff --git a/test/batchGetItem.js b/test/batchGetItem.js index a41362e..3a7bb7e 100644 --- a/test/batchGetItem.js +++ b/test/batchGetItem.js @@ -1,77 +1,77 @@ var async = require('async'), - helpers = require('./helpers') + helpers = require('./helpers') var target = 'BatchGetItem', - request = helpers.request, - randomName = helpers.randomName, - opts = helpers.opts.bind(null, target), - assertType = helpers.assertType.bind(null, target), - assertValidation = helpers.assertValidation.bind(null, target), - assertNotFound = helpers.assertNotFound.bind(null, target), - runSlowTests = helpers.runSlowTests + request = helpers.request, + randomName = helpers.randomName, + opts = helpers.opts.bind(null, target), + assertType = helpers.assertType.bind(null, target), + assertValidation = helpers.assertValidation.bind(null, target), + assertNotFound = helpers.assertNotFound.bind(null, target), + runSlowTests = helpers.runSlowTests -describe('batchGetItem', function() { +describe('batchGetItem', function () { - describe('serializations', function() { + describe('serializations', function () { - it('should return SerializationException when RequestItems is not a map', function(done) { + it('should return SerializationException when RequestItems is not a map', function (done) { assertType('RequestItems', 'Map', done) }) - it('should return SerializationException when RequestItems.Attr is not a struct', function(done) { + it('should return SerializationException when RequestItems.Attr is not a struct', function (done) { assertType('RequestItems.Attr', 'ValueStruct', done) }) - it('should return SerializationException when RequestItems.Attr.Keys is not a list', function(done) { + it('should return SerializationException when RequestItems.Attr.Keys is not a list', function (done) { assertType('RequestItems.Attr.Keys', 'List', done) }) - it('should return SerializationException when RequestItems.Attr.Keys.0 is not a map', function(done) { + it('should return SerializationException when RequestItems.Attr.Keys.0 is not a map', function (done) { assertType('RequestItems.Attr.Keys.0', 'ParameterizedMap', done) }) - it('should return SerializationException when RequestItems.Attr.Keys.0.Attr is not an attr struct', function(done) { + it('should return SerializationException when RequestItems.Attr.Keys.0.Attr is not an attr struct', function (done) { this.timeout(60000) assertType('RequestItems.Attr.Keys.0.Attr', 'AttrStruct', done) }) - it('should return SerializationException when RequestItems.Attr.AttributesToGet is not a list', function(done) { + it('should return SerializationException when RequestItems.Attr.AttributesToGet is not a list', function (done) { assertType('RequestItems.Attr.AttributesToGet', 'List', done) }) - it('should return SerializationException when RequestItems.Attr.ConsistentRead is not a boolean', function(done) { + it('should return SerializationException when RequestItems.Attr.ConsistentRead is not a boolean', function (done) { assertType('RequestItems.Attr.ConsistentRead', 'Boolean', done) }) - it('should return SerializationException when RequestItems.Attr.ExpressionAttributeNames is not a map', function(done) { + it('should return SerializationException when RequestItems.Attr.ExpressionAttributeNames is not a map', function (done) { assertType('RequestItems.Attr.ExpressionAttributeNames', 'Map', done) }) - it('should return SerializationException when RequestItems.Attr.ExpressionAttributeNames.Attr is not a string', function(done) { + it('should return SerializationException when RequestItems.Attr.ExpressionAttributeNames.Attr is not a string', function (done) { assertType('RequestItems.Attr.ExpressionAttributeNames.Attr', 'String', done) }) - it('should return SerializationException when RequestItems.Attr.ProjectionExpression is not a string', function(done) { + it('should return SerializationException when RequestItems.Attr.ProjectionExpression is not a string', function (done) { assertType('RequestItems.Attr.ProjectionExpression', 'String', done) }) - it('should return SerializationException when ReturnConsumedCapacity is not a string', function(done) { + it('should return SerializationException when ReturnConsumedCapacity is not a string', function (done) { assertType('ReturnConsumedCapacity', 'String', done) }) }) - describe('validations', function() { + describe('validations', function () { - it('should return ValidationException for empty RequestItems', function(done) { + it('should return ValidationException for empty RequestItems', function (done) { assertValidation({}, '1 validation error detected: ' + 'Value null at \'requestItems\' failed to satisfy constraint: ' + 'Member must not be null', done) }) - it('should return ValidationException for missing RequestItems', function(done) { - assertValidation({ReturnConsumedCapacity: 'hi', ReturnItemCollectionMetrics: 'hi'}, [ + it('should return ValidationException for missing RequestItems', function (done) { + assertValidation({ ReturnConsumedCapacity: 'hi', ReturnItemCollectionMetrics: 'hi' }, [ 'Value \'hi\' at \'returnConsumedCapacity\' failed to satisfy constraint: ' + 'Member must satisfy enum value set: [INDEXES, TOTAL, NONE]', 'Value null at \'requestItems\' failed to satisfy constraint: ' + @@ -79,15 +79,15 @@ describe('batchGetItem', function() { ], done) }) - it('should return ValidationException for empty RequestItems', function(done) { - assertValidation({RequestItems: {}}, + it('should return ValidationException for empty RequestItems', function (done) { + assertValidation({ RequestItems: {} }, '1 validation error detected: ' + 'Value \'{}\' at \'requestItems\' failed to satisfy constraint: ' + 'Member must have length greater than or equal to 1', done) }) - it('should return ValidationException for short table name with no keys', function(done) { - assertValidation({RequestItems: {a: {}}, ReturnConsumedCapacity: 'hi', ReturnItemCollectionMetrics: 'hi'}, [ + it('should return ValidationException for short table name with no keys', function (done) { + assertValidation({ RequestItems: { a: {} }, ReturnConsumedCapacity: 'hi', ReturnItemCollectionMetrics: 'hi' }, [ 'Value \'hi\' at \'returnConsumedCapacity\' failed to satisfy constraint: ' + 'Member must satisfy enum value set: [INDEXES, TOTAL, NONE]', new RegExp('Value \'{.+}\' at \'requestItems\' ' + @@ -100,8 +100,8 @@ describe('batchGetItem', function() { ], done) }) - it('should return ValidationException for empty keys', function(done) { - assertValidation({RequestItems: {a: {Keys: []}}}, [ + it('should return ValidationException for empty keys', function (done) { + assertValidation({ RequestItems: { a: { Keys: [] } } }, [ new RegExp('Value \'{.+}\' at \'requestItems\' ' + 'failed to satisfy constraint: Map keys must satisfy constraint: ' + '\\[Member must have length less than or equal to 255, ' + @@ -112,8 +112,8 @@ describe('batchGetItem', function() { ], done) }) - it('should return ValidationException for incorrect attributes', function(done) { - assertValidation({RequestItems: {'aa;': {}}, ReturnConsumedCapacity: 'hi'}, [ + it('should return ValidationException for incorrect attributes', function (done) { + assertValidation({ RequestItems: { 'aa;': {} }, ReturnConsumedCapacity: 'hi' }, [ 'Value \'hi\' at \'returnConsumedCapacity\' failed to satisfy constraint: ' + 'Member must satisfy enum value set: [INDEXES, TOTAL, NONE]', new RegExp('Value \'{.+}\' at \'requestItems\' ' + @@ -126,8 +126,8 @@ describe('batchGetItem', function() { ], done) }) - it('should return ValidationException for short table name with keys', function(done) { - assertValidation({RequestItems: {a: {Keys: [{a: {S: 'a'}}]}}}, + it('should return ValidationException for short table name with keys', function (done) { + assertValidation({ RequestItems: { a: { Keys: [ { a: { S: 'a' } } ] } } }, new RegExp('1 validation error detected: ' + 'Value \'{.+}\' at \'requestItems\' ' + 'failed to satisfy constraint: Map keys must satisfy constraint: ' + @@ -136,23 +136,23 @@ describe('batchGetItem', function() { 'Member must satisfy regular expression pattern: \\[a-zA-Z0-9_.-\\]\\+\\]'), done) }) - it('should return ValidationException when fetching more than 100 keys', function(done) { + it('should return ValidationException when fetching more than 100 keys', function (done) { var keys = [], i for (i = 0; i < 101; i++) { - keys.push({a: {S: String(i)}}) + keys.push({ a: { S: String(i) } }) } - assertValidation({RequestItems: {abc: {Keys: keys}}}, + assertValidation({ RequestItems: { abc: { Keys: keys } } }, new RegExp('1 validation error detected: ' + 'Value \'\\[.+\\]\' at \'requestItems.abc.member.keys\' failed to satisfy constraint: ' + 'Member must have length less than or equal to 100'), done) }) - it('should return ValidationException if filter expression and non-expression', function(done) { + it('should return ValidationException if filter expression and non-expression', function (done) { assertValidation({ RequestItems: { abc: { - Keys: [{}], - AttributesToGet: ['a'], + Keys: [ {} ], + AttributesToGet: [ 'a' ], ExpressionAttributeNames: {}, ProjectionExpression: '', }, @@ -161,23 +161,23 @@ describe('batchGetItem', function() { 'Non-expression parameters: {AttributesToGet} Expression parameters: {ProjectionExpression}', done) }) - it('should return ValidationException if ExpressionAttributeNames but no ProjectionExpression', function(done) { + it('should return ValidationException if ExpressionAttributeNames but no ProjectionExpression', function (done) { assertValidation({ RequestItems: { abc: { - Keys: [{}], - AttributesToGet: ['a'], + Keys: [ {} ], + AttributesToGet: [ 'a' ], ExpressionAttributeNames: {}, }, }, }, 'ExpressionAttributeNames can only be specified when using expressions', done) }) - it('should return ValidationException for empty ExpressionAttributeNames', function(done) { + it('should return ValidationException for empty ExpressionAttributeNames', function (done) { assertValidation({ RequestItems: { abc: { - Keys: [{}], + Keys: [ {} ], ExpressionAttributeNames: {}, ProjectionExpression: '', }, @@ -185,104 +185,104 @@ describe('batchGetItem', function() { }, 'ExpressionAttributeNames must not be empty', done) }) - it('should return ValidationException for invalid ExpressionAttributeNames', function(done) { + it('should return ValidationException for invalid ExpressionAttributeNames', function (done) { assertValidation({ RequestItems: { abc: { - Keys: [{}], - ExpressionAttributeNames: {'a': 'a'}, + Keys: [ {} ], + ExpressionAttributeNames: { 'a': 'a' }, ProjectionExpression: '', }, }, }, 'ExpressionAttributeNames contains invalid key: Syntax error; key: "a"', done) }) - it('should return ValidationException for empty ProjectionExpression', function(done) { + it('should return ValidationException for empty ProjectionExpression', function (done) { assertValidation({ RequestItems: { abc: { - Keys: [{}], + Keys: [ {} ], ProjectionExpression: '', }, }, }, 'Invalid ProjectionExpression: The expression can not be empty;', done) }) - it('should return ValidationException when fetching more than 100 keys over multiple tables', function(done) { + it('should return ValidationException when fetching more than 100 keys over multiple tables', function (done) { var keys = [], i for (i = 0; i < 100; i++) { - keys.push({a: {S: String(i)}}) + keys.push({ a: { S: String(i) } }) } - assertValidation({RequestItems: {abc: {Keys: keys}, abd: {Keys: [{a: {S: '100'}}]}}}, + assertValidation({ RequestItems: { abc: { Keys: keys }, abd: { Keys: [ { a: { S: '100' } } ] } } }, 'Too many items requested for the BatchGetItem call', done) }) - it('should return ResourceNotFoundException when fetching exactly 100 keys and table does not exist', function(done) { + it('should return ResourceNotFoundException when fetching exactly 100 keys and table does not exist', function (done) { var keys = [], i for (i = 0; i < 100; i++) { - keys.push({a: {S: String(i)}}) + keys.push({ a: { S: String(i) } }) } - assertNotFound({RequestItems: {abc: {Keys: keys}}}, + assertNotFound({ RequestItems: { abc: { Keys: keys } } }, 'Requested resource not found', done) }) - it('should return ValidationException for unsupported datatype in Key', function(done) { + it('should return ValidationException for unsupported datatype in Key', function (done) { async.forEach([ {}, - {a: ''}, - {M: {a: {}}}, - {L: [{}]}, - {L: [{a: {}}]}, - ], function(expr, cb) { - assertValidation({RequestItems: {abc: {Keys: [{a: expr}]}}}, + { a: '' }, + { M: { a: {} } }, + { L: [ {} ] }, + { L: [ { a: {} } ] }, + ], function (expr, cb) { + assertValidation({ RequestItems: { abc: { Keys: [ { a: expr } ] } } }, 'Supplied AttributeValue is empty, must contain exactly one of the supported datatypes', cb) }, done) }) - it('should return ValidationException for invalid values in Key', function(done) { + it('should return ValidationException for invalid values in Key', function (done) { async.forEach([ - [{NULL: 'no'}, 'Null attribute value types must have the value of true'], - [{SS: []}, 'An string set may not be empty'], - [{NS: []}, 'An number set may not be empty'], - [{BS: []}, 'Binary sets should not be empty'], - [{SS: ['a', 'a']}, 'Input collection [a, a] contains duplicates.'], - [{BS: ['Yg==', 'Yg==']}, 'Input collection [Yg==, Yg==]of type BS contains duplicates.'], - ], function(expr, cb) { - assertValidation({RequestItems: {abc: {Keys: [{a: expr[0]}]}}}, + [ { NULL: 'no' }, 'Null attribute value types must have the value of true' ], + [ { SS: [] }, 'An string set may not be empty' ], + [ { NS: [] }, 'An number set may not be empty' ], + [ { BS: [] }, 'Binary sets should not be empty' ], + [ { SS: [ 'a', 'a' ] }, 'Input collection [a, a] contains duplicates.' ], + [ { BS: [ 'Yg==', 'Yg==' ] }, 'Input collection [Yg==, Yg==]of type BS contains duplicates.' ], + ], function (expr, cb) { + assertValidation({ RequestItems: { abc: { Keys: [ { a: expr[0] } ] } } }, 'One or more parameter values were invalid: ' + expr[1], cb) }, done) }) - it('should return ValidationException for empty/invalid numbers in Key', function(done) { + it('should return ValidationException for empty/invalid numbers in Key', function (done) { async.forEach([ - [{S: '', N: ''}, 'The parameter cannot be converted to a numeric value'], - [{S: 'a', N: ''}, 'The parameter cannot be converted to a numeric value'], - [{S: 'a', N: 'b'}, 'The parameter cannot be converted to a numeric value: b'], - [{NS: ['1', '']}, 'The parameter cannot be converted to a numeric value'], - [{NS: ['1', 'b']}, 'The parameter cannot be converted to a numeric value: b'], - [{NS: ['1', '1']}, 'Input collection contains duplicates'], - [{N: '123456789012345678901234567890123456789'}, 'Attempting to store more than 38 significant digits in a Number'], - [{N: '-1.23456789012345678901234567890123456789'}, 'Attempting to store more than 38 significant digits in a Number'], - [{N: '1e126'}, 'Number overflow. Attempting to store a number with magnitude larger than supported range'], - [{N: '-1e126'}, 'Number overflow. Attempting to store a number with magnitude larger than supported range'], - [{N: '1e-131'}, 'Number underflow. Attempting to store a number with magnitude smaller than supported range'], - [{N: '-1e-131'}, 'Number underflow. Attempting to store a number with magnitude smaller than supported range'], - ], function(expr, cb) { - assertValidation({RequestItems: {abc: {Keys: [{a: expr[0]}]}}}, expr[1], cb) + [ { S: '', N: '' }, 'The parameter cannot be converted to a numeric value' ], + [ { S: 'a', N: '' }, 'The parameter cannot be converted to a numeric value' ], + [ { S: 'a', N: 'b' }, 'The parameter cannot be converted to a numeric value: b' ], + [ { NS: [ '1', '' ] }, 'The parameter cannot be converted to a numeric value' ], + [ { NS: [ '1', 'b' ] }, 'The parameter cannot be converted to a numeric value: b' ], + [ { NS: [ '1', '1' ] }, 'Input collection contains duplicates' ], + [ { N: '123456789012345678901234567890123456789' }, 'Attempting to store more than 38 significant digits in a Number' ], + [ { N: '-1.23456789012345678901234567890123456789' }, 'Attempting to store more than 38 significant digits in a Number' ], + [ { N: '1e126' }, 'Number overflow. Attempting to store a number with magnitude larger than supported range' ], + [ { N: '-1e126' }, 'Number overflow. Attempting to store a number with magnitude larger than supported range' ], + [ { N: '1e-131' }, 'Number underflow. Attempting to store a number with magnitude smaller than supported range' ], + [ { N: '-1e-131' }, 'Number underflow. Attempting to store a number with magnitude smaller than supported range' ], + ], function (expr, cb) { + assertValidation({ RequestItems: { abc: { Keys: [ { a: expr[0] } ] } } }, expr[1], cb) }, done) }) - it('should return ValidationException for multiple datatypes in Key', function(done) { - assertValidation({RequestItems: {abc: {Keys: [{'a': {S: 'a', N: '1'}}]}}}, + it('should return ValidationException for multiple datatypes in Key', function (done) { + assertValidation({ RequestItems: { abc: { Keys: [ { 'a': { S: 'a', N: '1' } } ] } } }, 'Supplied AttributeValue has more than one datatypes set, must contain exactly one of the supported datatypes', done) }) - it('should return ValidationException for empty ExpressionAttributeNames', function(done) { - var key = {a: {S: helpers.randomString()}, b: {N: helpers.randomNumber()}} + it('should return ValidationException for empty ExpressionAttributeNames', function (done) { + var key = { a: { S: helpers.randomString() }, b: { N: helpers.randomNumber() } } assertValidation({ RequestItems: { abc: { - Keys: [key, {b: key.b, a: key.a}, key], + Keys: [ key, { b: key.b, a: key.a }, key ], ExpressionAttributeNames: {}, ProjectionExpression: '', }, @@ -290,110 +290,110 @@ describe('batchGetItem', function() { }, 'ExpressionAttributeNames must not be empty', done) }) - it('should return ValidationException for empty ProjectionExpression', function(done) { - var key = {a: {S: helpers.randomString()}, b: {N: helpers.randomNumber()}} + it('should return ValidationException for empty ProjectionExpression', function (done) { + var key = { a: { S: helpers.randomString() }, b: { N: helpers.randomNumber() } } assertValidation({ RequestItems: { abc: { - Keys: [key, {b: key.b, a: key.a}, key], + Keys: [ key, { b: key.b, a: key.a }, key ], ProjectionExpression: '', }, }, }, 'Invalid ProjectionExpression: The expression can not be empty;', done) }) - it('should return ValidationException for duplicated keys', function(done) { - var key = {a: {S: helpers.randomString()}, b: {N: helpers.randomNumber()}} + it('should return ValidationException for duplicated keys', function (done) { + var key = { a: { S: helpers.randomString() }, b: { N: helpers.randomNumber() } } assertValidation({ RequestItems: { abc: { - Keys: [key, {b: key.b, a: key.a}, key], + Keys: [ key, { b: key.b, a: key.a }, key ], }, }, }, 'Provided list of item keys contains duplicates', done) }) - it('should return ValidationException for duplicated mixed up keys', function(done) { - var key = {a: {S: helpers.randomString()}}, - key2 = {a: {S: helpers.randomString()}} + it('should return ValidationException for duplicated mixed up keys', function (done) { + var key = { a: { S: helpers.randomString() } }, + key2 = { a: { S: helpers.randomString() } } assertValidation({ RequestItems: { abc: { - Keys: [key, key2, key], - AttributesToGet: ['a', 'a'], + Keys: [ key, key2, key ], + AttributesToGet: [ 'a', 'a' ], }, }, }, 'One or more parameter values were invalid: Duplicate value in attribute name: a', done) }) - it('should return ValidationException duplicate values in AttributesToGet', function(done) { - assertValidation({RequestItems: {abc: {Keys: [{}], AttributesToGet: ['a', 'a']}}}, + it('should return ValidationException duplicate values in AttributesToGet', function (done) { + assertValidation({ RequestItems: { abc: { Keys: [ {} ], AttributesToGet: [ 'a', 'a' ] } } }, 'One or more parameter values were invalid: Duplicate value in attribute name: a', done) }) - it('should return ResourceNotFoundException if key is empty and table does not exist', function(done) { - var batchReq = {RequestItems: {}} - batchReq.RequestItems[randomName()] = {Keys: [{}]} + it('should return ResourceNotFoundException if key is empty and table does not exist', function (done) { + var batchReq = { RequestItems: {} } + batchReq.RequestItems[randomName()] = { Keys: [ {} ] } assertNotFound(batchReq, 'Requested resource not found', done) }) - it('should return ValidationException if key does not match schema', function(done) { + it('should return ValidationException if key does not match schema', function (done) { async.forEach([ {}, - {b: {S: 'a'}}, - {a: {S: 'a'}, b: {S: 'a'}}, - {a: {B: 'abcd'}}, - {a: {N: '1'}}, - {a: {BOOL: true}}, - {a: {NULL: true}}, - {a: {SS: ['a']}}, - {a: {NS: ['1']}}, - {a: {BS: ['aaaa']}}, - {a: {M: {}}}, - {a: {L: []}}, - ], function(expr, cb) { - var batchReq = {RequestItems: {}} - batchReq.RequestItems[helpers.testHashTable] = {Keys: [expr]} + { b: { S: 'a' } }, + { a: { S: 'a' }, b: { S: 'a' } }, + { a: { B: 'abcd' } }, + { a: { N: '1' } }, + { a: { BOOL: true } }, + { a: { NULL: true } }, + { a: { SS: [ 'a' ] } }, + { a: { NS: [ '1' ] } }, + { a: { BS: [ 'aaaa' ] } }, + { a: { M: {} } }, + { a: { L: [] } }, + ], function (expr, cb) { + var batchReq = { RequestItems: {} } + batchReq.RequestItems[helpers.testHashTable] = { Keys: [ expr ] } assertValidation(batchReq, 'The provided key element does not match the schema', cb) }, done) }) - it('should return ValidationException if range key does not match schema', function(done) { - var batchReq = {RequestItems: {}} - batchReq.RequestItems[helpers.testRangeTable] = {Keys: [{a: {S: 'a'}}]} + it('should return ValidationException if range key does not match schema', function (done) { + var batchReq = { RequestItems: {} } + batchReq.RequestItems[helpers.testRangeTable] = { Keys: [ { a: { S: 'a' } } ] } assertValidation(batchReq, 'The provided key element does not match the schema', done) }) - it('should return ValidationException if hash key is too big', function(done) { - var batchReq = {RequestItems: {}}, keyStr = (helpers.randomString() + new Array(2048).join('a')).slice(0, 2049) - batchReq.RequestItems[helpers.testHashTable] = {Keys: [{a: {S: keyStr}}]} + it('should return ValidationException if hash key is too big', function (done) { + var batchReq = { RequestItems: {} }, keyStr = (helpers.randomString() + new Array(2048).join('a')).slice(0, 2049) + batchReq.RequestItems[helpers.testHashTable] = { Keys: [ { a: { S: keyStr } } ] } assertValidation(batchReq, 'One or more parameter values were invalid: ' + 'Size of hashkey has exceeded the maximum size limit of2048 bytes', done) }) - it('should return ValidationException if range key is too big', function(done) { - var batchReq = {RequestItems: {}}, keyStr = (helpers.randomString() + new Array(1024).join('a')).slice(0, 1025) - batchReq.RequestItems[helpers.testRangeTable] = {Keys: [{a: {S: 'a'}, b: {S: keyStr}}]} + it('should return ValidationException if range key is too big', function (done) { + var batchReq = { RequestItems: {} }, keyStr = (helpers.randomString() + new Array(1024).join('a')).slice(0, 1025) + batchReq.RequestItems[helpers.testRangeTable] = { Keys: [ { a: { S: 'a' }, b: { S: keyStr } } ] } assertValidation(batchReq, 'One or more parameter values were invalid: ' + 'Aggregated size of all range keys has exceeded the size limit of 1024 bytes', done) }) - it('should return ResourceNotFoundException if table is being created', function(done) { + it('should return ResourceNotFoundException if table is being created', function (done) { var table = { TableName: randomName(), - AttributeDefinitions: [{AttributeName: 'a', AttributeType: 'S'}], - KeySchema: [{KeyType: 'HASH', AttributeName: 'a'}], - ProvisionedThroughput: {ReadCapacityUnits: 1, WriteCapacityUnits: 1}, + AttributeDefinitions: [ { AttributeName: 'a', AttributeType: 'S' } ], + KeySchema: [ { KeyType: 'HASH', AttributeName: 'a' } ], + ProvisionedThroughput: { ReadCapacityUnits: 1, WriteCapacityUnits: 1 }, } - request(helpers.opts('CreateTable', table), function(err) { + request(helpers.opts('CreateTable', table), function (err) { if (err) return done(err) - var batchReq = {RequestItems: {}} - batchReq.RequestItems[table.TableName] = {Keys: [{a: {S: 'a'}}]} + var batchReq = { RequestItems: {} } + batchReq.RequestItems[table.TableName] = { Keys: [ { a: { S: 'a' } } ] } assertNotFound(batchReq, 'Requested resource not found', done) helpers.deleteWhenActive(table.TableName) }) @@ -401,13 +401,13 @@ describe('batchGetItem', function() { }) - describe('functionality', function() { + describe('functionality', function () { - it('should return empty responses if keys do not exist', function(done) { - var batchReq = {RequestItems: {}} - batchReq.RequestItems[helpers.testHashTable] = {Keys: [{a: {S: helpers.randomString()}}]} - batchReq.RequestItems[helpers.testRangeTable] = {Keys: [{a: {S: helpers.randomString()}, b: {S: helpers.randomString()}}]} - request(opts(batchReq), function(err, res) { + it('should return empty responses if keys do not exist', function (done) { + var batchReq = { RequestItems: {} } + batchReq.RequestItems[helpers.testHashTable] = { Keys: [ { a: { S: helpers.randomString() } } ] } + batchReq.RequestItems[helpers.testRangeTable] = { Keys: [ { a: { S: helpers.randomString() }, b: { S: helpers.randomString() } } ] } + request(opts(batchReq), function (err, res) { if (err) return done(err) res.statusCode.should.equal(200) res.body.Responses[helpers.testHashTable].should.eql([]) @@ -417,27 +417,27 @@ describe('batchGetItem', function() { }) }) - it('should return only items that do exist', function(done) { - var item = {a: {S: helpers.randomString()}, b: {N: helpers.randomNumber()}}, - item2 = {a: {S: helpers.randomString()}, b: item.b}, - item3 = {a: {S: helpers.randomString()}, b: {N: helpers.randomNumber()}}, - batchReq = {RequestItems: {}} + it('should return only items that do exist', function (done) { + var item = { a: { S: helpers.randomString() }, b: { N: helpers.randomNumber() } }, + item2 = { a: { S: helpers.randomString() }, b: item.b }, + item3 = { a: { S: helpers.randomString() }, b: { N: helpers.randomNumber() } }, + batchReq = { RequestItems: {} } batchReq.RequestItems[helpers.testHashTable] = [ - {PutRequest: {Item: item}}, - {PutRequest: {Item: item2}}, - {PutRequest: {Item: item3}}, + { PutRequest: { Item: item } }, + { PutRequest: { Item: item2 } }, + { PutRequest: { Item: item3 } }, ] - request(helpers.opts('BatchWriteItem', batchReq), function(err, res) { + request(helpers.opts('BatchWriteItem', batchReq), function (err, res) { if (err) return done(err) res.statusCode.should.equal(200) - batchReq = {RequestItems: {}} - batchReq.RequestItems[helpers.testHashTable] = {Keys: [ - {a: item.a}, - {a: {S: helpers.randomString()}}, - {a: item3.a}, - {a: {S: helpers.randomString()}}, - ], ConsistentRead: true} - request(opts(batchReq), function(err, res) { + batchReq = { RequestItems: {} } + batchReq.RequestItems[helpers.testHashTable] = { Keys: [ + { a: item.a }, + { a: { S: helpers.randomString() } }, + { a: item3.a }, + { a: { S: helpers.randomString() } }, + ], ConsistentRead: true } + request(opts(batchReq), function (err, res) { if (err) return done(err) res.statusCode.should.equal(200) res.body.Responses[helpers.testHashTable].should.containEql(item) @@ -449,41 +449,41 @@ describe('batchGetItem', function() { }) }) - it('should return only requested attributes of items that do exist', function(done) { - var item = {a: {S: helpers.randomString()}, b: {N: helpers.randomNumber()}, c: {S: 'c'}}, - item2 = {a: {S: helpers.randomString()}, b: item.b}, - item3 = {a: {S: helpers.randomString()}, b: {N: helpers.randomNumber()}}, - item4 = {a: {S: helpers.randomString()}}, - batchReq = {RequestItems: {}} + it('should return only requested attributes of items that do exist', function (done) { + var item = { a: { S: helpers.randomString() }, b: { N: helpers.randomNumber() }, c: { S: 'c' } }, + item2 = { a: { S: helpers.randomString() }, b: item.b }, + item3 = { a: { S: helpers.randomString() }, b: { N: helpers.randomNumber() } }, + item4 = { a: { S: helpers.randomString() } }, + batchReq = { RequestItems: {} } batchReq.RequestItems[helpers.testHashTable] = [ - {PutRequest: {Item: item}}, - {PutRequest: {Item: item2}}, - {PutRequest: {Item: item3}}, - {PutRequest: {Item: item4}}, + { PutRequest: { Item: item } }, + { PutRequest: { Item: item2 } }, + { PutRequest: { Item: item3 } }, + { PutRequest: { Item: item4 } }, ] - request(helpers.opts('BatchWriteItem', batchReq), function(err, res) { + request(helpers.opts('BatchWriteItem', batchReq), function (err, res) { if (err) return done(err) res.statusCode.should.equal(200) async.forEach([ - {AttributesToGet: ['b', 'c']}, - {ProjectionExpression: 'b, c'}, - {ProjectionExpression: '#b, #c', ExpressionAttributeNames: {'#b': 'b', '#c': 'c'}}, - ], function(batchOpts, cb) { - batchReq = {RequestItems: {}} + { AttributesToGet: [ 'b', 'c' ] }, + { ProjectionExpression: 'b, c' }, + { ProjectionExpression: '#b, #c', ExpressionAttributeNames: { '#b': 'b', '#c': 'c' } }, + ], function (batchOpts, cb) { + batchReq = { RequestItems: {} } batchReq.RequestItems[helpers.testHashTable] = batchOpts batchOpts.Keys = [ - {a: item.a}, - {a: {S: helpers.randomString()}}, - {a: item3.a}, - {a: {S: helpers.randomString()}}, - {a: item4.a}, + { a: item.a }, + { a: { S: helpers.randomString() } }, + { a: item3.a }, + { a: { S: helpers.randomString() } }, + { a: item4.a }, ] batchOpts.ConsistentRead = true - request(opts(batchReq), function(err, res) { + request(opts(batchReq), function (err, res) { if (err) return cb(err) res.statusCode.should.equal(200) - res.body.Responses[helpers.testHashTable].should.containEql({b: item.b, c: item.c}) - res.body.Responses[helpers.testHashTable].should.containEql({b: item3.b}) + res.body.Responses[helpers.testHashTable].should.containEql({ b: item.b, c: item.c }) + res.body.Responses[helpers.testHashTable].should.containEql({ b: item3.b }) res.body.Responses[helpers.testHashTable].should.containEql({}) res.body.Responses[helpers.testHashTable].should.have.length(3) res.body.UnprocessedKeys.should.eql({}) @@ -493,124 +493,124 @@ describe('batchGetItem', function() { }) }) - it('should return ConsumedCapacity from each specified table with no consistent read and small item', function(done) { + it('should return ConsumedCapacity from each specified table with no consistent read and small item', function (done) { var a = helpers.randomString(), b = new Array(4082 - a.length).join('b'), - item = {a: {S: a}, b: {S: b}, c: {N: '12.3456'}, d: {B: 'AQI='}, e: {BS: ['AQI=', 'Ag==', 'AQ==']}}, - item2 = {a: {S: helpers.randomString()}}, - batchReq = {RequestItems: {}} - batchReq.RequestItems[helpers.testHashTable] = [{PutRequest: {Item: item}}, {PutRequest: {Item: item2}}] - request(helpers.opts('BatchWriteItem', batchReq), function(err, res) { + item = { a: { S: a }, b: { S: b }, c: { N: '12.3456' }, d: { B: 'AQI=' }, e: { BS: [ 'AQI=', 'Ag==', 'AQ==' ] } }, + item2 = { a: { S: helpers.randomString() } }, + batchReq = { RequestItems: {} } + batchReq.RequestItems[helpers.testHashTable] = [ { PutRequest: { Item: item } }, { PutRequest: { Item: item2 } } ] + request(helpers.opts('BatchWriteItem', batchReq), function (err, res) { if (err) return done(err) res.statusCode.should.equal(200) - batchReq = {RequestItems: {}, ReturnConsumedCapacity: 'TOTAL'} - batchReq.RequestItems[helpers.testHashTable] = {Keys: [{a: item.a}, {a: item2.a}, {a: {S: helpers.randomString()}}]} - batchReq.RequestItems[helpers.testHashNTable] = {Keys: [{a: {N: helpers.randomNumber()}}]} - request(opts(batchReq), function(err, res) { + batchReq = { RequestItems: {}, ReturnConsumedCapacity: 'TOTAL' } + batchReq.RequestItems[helpers.testHashTable] = { Keys: [ { a: item.a }, { a: item2.a }, { a: { S: helpers.randomString() } } ] } + batchReq.RequestItems[helpers.testHashNTable] = { Keys: [ { a: { N: helpers.randomNumber() } } ] } + request(opts(batchReq), function (err, res) { if (err) return done(err) res.statusCode.should.equal(200) - res.body.ConsumedCapacity.should.containEql({CapacityUnits: 1.5, TableName: helpers.testHashTable}) - res.body.ConsumedCapacity.should.containEql({CapacityUnits: 0.5, TableName: helpers.testHashNTable}) + res.body.ConsumedCapacity.should.containEql({ CapacityUnits: 1.5, TableName: helpers.testHashTable }) + res.body.ConsumedCapacity.should.containEql({ CapacityUnits: 0.5, TableName: helpers.testHashNTable }) res.body.Responses[helpers.testHashTable].should.have.length(2) res.body.Responses[helpers.testHashNTable].should.have.length(0) batchReq.ReturnConsumedCapacity = 'INDEXES' - request(opts(batchReq), function(err, res) { + request(opts(batchReq), function (err, res) { if (err) return done(err) res.statusCode.should.equal(200) - res.body.ConsumedCapacity.should.containEql({CapacityUnits: 1.5, Table: {CapacityUnits: 1.5}, TableName: helpers.testHashTable}) - res.body.ConsumedCapacity.should.containEql({CapacityUnits: 0.5, Table: {CapacityUnits: 0.5}, TableName: helpers.testHashNTable}) + res.body.ConsumedCapacity.should.containEql({ CapacityUnits: 1.5, Table: { CapacityUnits: 1.5 }, TableName: helpers.testHashTable }) + res.body.ConsumedCapacity.should.containEql({ CapacityUnits: 0.5, Table: { CapacityUnits: 0.5 }, TableName: helpers.testHashNTable }) done() }) }) }) }) - it('should return ConsumedCapacity from each specified table with no consistent read and larger item', function(done) { + it('should return ConsumedCapacity from each specified table with no consistent read and larger item', function (done) { var a = helpers.randomString(), b = new Array(4084 - a.length).join('b'), - item = {a: {S: a}, b: {S: b}, c: {N: '12.3456'}, d: {B: 'AQI='}, e: {BS: ['AQI=', 'Ag==']}}, - item2 = {a: {S: helpers.randomString()}}, - batchReq = {RequestItems: {}} - batchReq.RequestItems[helpers.testHashTable] = [{PutRequest: {Item: item}}, {PutRequest: {Item: item2}}] - request(helpers.opts('BatchWriteItem', batchReq), function(err, res) { + item = { a: { S: a }, b: { S: b }, c: { N: '12.3456' }, d: { B: 'AQI=' }, e: { BS: [ 'AQI=', 'Ag==' ] } }, + item2 = { a: { S: helpers.randomString() } }, + batchReq = { RequestItems: {} } + batchReq.RequestItems[helpers.testHashTable] = [ { PutRequest: { Item: item } }, { PutRequest: { Item: item2 } } ] + request(helpers.opts('BatchWriteItem', batchReq), function (err, res) { if (err) return done(err) res.statusCode.should.equal(200) - batchReq = {RequestItems: {}, ReturnConsumedCapacity: 'TOTAL'} - batchReq.RequestItems[helpers.testHashTable] = {Keys: [{a: item.a}, {a: item2.a}, {a: {S: helpers.randomString()}}]} - batchReq.RequestItems[helpers.testHashNTable] = {Keys: [{a: {N: helpers.randomNumber()}}]} - request(opts(batchReq), function(err, res) { + batchReq = { RequestItems: {}, ReturnConsumedCapacity: 'TOTAL' } + batchReq.RequestItems[helpers.testHashTable] = { Keys: [ { a: item.a }, { a: item2.a }, { a: { S: helpers.randomString() } } ] } + batchReq.RequestItems[helpers.testHashNTable] = { Keys: [ { a: { N: helpers.randomNumber() } } ] } + request(opts(batchReq), function (err, res) { if (err) return done(err) res.statusCode.should.equal(200) - res.body.ConsumedCapacity.should.containEql({CapacityUnits: 2, TableName: helpers.testHashTable}) - res.body.ConsumedCapacity.should.containEql({CapacityUnits: 0.5, TableName: helpers.testHashNTable}) + res.body.ConsumedCapacity.should.containEql({ CapacityUnits: 2, TableName: helpers.testHashTable }) + res.body.ConsumedCapacity.should.containEql({ CapacityUnits: 0.5, TableName: helpers.testHashNTable }) res.body.Responses[helpers.testHashTable].should.have.length(2) res.body.Responses[helpers.testHashNTable].should.have.length(0) batchReq.ReturnConsumedCapacity = 'INDEXES' - request(opts(batchReq), function(err, res) { + request(opts(batchReq), function (err, res) { if (err) return done(err) res.statusCode.should.equal(200) - res.body.ConsumedCapacity.should.containEql({CapacityUnits: 2, Table: {CapacityUnits: 2}, TableName: helpers.testHashTable}) - res.body.ConsumedCapacity.should.containEql({CapacityUnits: 0.5, Table: {CapacityUnits: 0.5}, TableName: helpers.testHashNTable}) + res.body.ConsumedCapacity.should.containEql({ CapacityUnits: 2, Table: { CapacityUnits: 2 }, TableName: helpers.testHashTable }) + res.body.ConsumedCapacity.should.containEql({ CapacityUnits: 0.5, Table: { CapacityUnits: 0.5 }, TableName: helpers.testHashNTable }) done() }) }) }) }) - it('should return ConsumedCapacity from each specified table with consistent read and small item', function(done) { + it('should return ConsumedCapacity from each specified table with consistent read and small item', function (done) { var a = helpers.randomString(), b = new Array(4082 - a.length).join('b'), - item = {a: {S: a}, b: {S: b}, c: {N: '12.3456'}, d: {B: 'AQI='}, e: {BS: ['AQI=', 'Ag==', 'AQ==']}}, - item2 = {a: {S: helpers.randomString()}}, - batchReq = {RequestItems: {}} - batchReq.RequestItems[helpers.testHashTable] = [{PutRequest: {Item: item}}, {PutRequest: {Item: item2}}] - request(helpers.opts('BatchWriteItem', batchReq), function(err, res) { + item = { a: { S: a }, b: { S: b }, c: { N: '12.3456' }, d: { B: 'AQI=' }, e: { BS: [ 'AQI=', 'Ag==', 'AQ==' ] } }, + item2 = { a: { S: helpers.randomString() } }, + batchReq = { RequestItems: {} } + batchReq.RequestItems[helpers.testHashTable] = [ { PutRequest: { Item: item } }, { PutRequest: { Item: item2 } } ] + request(helpers.opts('BatchWriteItem', batchReq), function (err, res) { if (err) return done(err) res.statusCode.should.equal(200) - batchReq = {RequestItems: {}, ReturnConsumedCapacity: 'TOTAL'} - batchReq.RequestItems[helpers.testHashTable] = {Keys: [{a: item.a}, {a: item2.a}, {a: {S: helpers.randomString()}}], ConsistentRead: true} - batchReq.RequestItems[helpers.testHashNTable] = {Keys: [{a: {N: helpers.randomNumber()}}], ConsistentRead: true} - request(opts(batchReq), function(err, res) { + batchReq = { RequestItems: {}, ReturnConsumedCapacity: 'TOTAL' } + batchReq.RequestItems[helpers.testHashTable] = { Keys: [ { a: item.a }, { a: item2.a }, { a: { S: helpers.randomString() } } ], ConsistentRead: true } + batchReq.RequestItems[helpers.testHashNTable] = { Keys: [ { a: { N: helpers.randomNumber() } } ], ConsistentRead: true } + request(opts(batchReq), function (err, res) { if (err) return done(err) res.statusCode.should.equal(200) - res.body.ConsumedCapacity.should.containEql({CapacityUnits: 3, TableName: helpers.testHashTable}) - res.body.ConsumedCapacity.should.containEql({CapacityUnits: 1, TableName: helpers.testHashNTable}) + res.body.ConsumedCapacity.should.containEql({ CapacityUnits: 3, TableName: helpers.testHashTable }) + res.body.ConsumedCapacity.should.containEql({ CapacityUnits: 1, TableName: helpers.testHashNTable }) res.body.Responses[helpers.testHashTable].should.have.length(2) res.body.Responses[helpers.testHashNTable].should.have.length(0) batchReq.ReturnConsumedCapacity = 'INDEXES' - request(opts(batchReq), function(err, res) { + request(opts(batchReq), function (err, res) { if (err) return done(err) res.statusCode.should.equal(200) - res.body.ConsumedCapacity.should.containEql({CapacityUnits: 3, Table: {CapacityUnits: 3}, TableName: helpers.testHashTable}) - res.body.ConsumedCapacity.should.containEql({CapacityUnits: 1, Table: {CapacityUnits: 1}, TableName: helpers.testHashNTable}) + res.body.ConsumedCapacity.should.containEql({ CapacityUnits: 3, Table: { CapacityUnits: 3 }, TableName: helpers.testHashTable }) + res.body.ConsumedCapacity.should.containEql({ CapacityUnits: 1, Table: { CapacityUnits: 1 }, TableName: helpers.testHashNTable }) done() }) }) }) }) - it('should return ConsumedCapacity from each specified table with consistent read and larger item', function(done) { + it('should return ConsumedCapacity from each specified table with consistent read and larger item', function (done) { var a = helpers.randomString(), b = new Array(4084 - a.length).join('b'), - item = {a: {S: a}, b: {S: b}, c: {N: '12.3456'}, d: {B: 'AQI='}, e: {BS: ['AQI=', 'Ag==']}}, - item2 = {a: {S: helpers.randomString()}}, - batchReq = {RequestItems: {}} - batchReq.RequestItems[helpers.testHashTable] = [{PutRequest: {Item: item}}, {PutRequest: {Item: item2}}] - request(helpers.opts('BatchWriteItem', batchReq), function(err, res) { + item = { a: { S: a }, b: { S: b }, c: { N: '12.3456' }, d: { B: 'AQI=' }, e: { BS: [ 'AQI=', 'Ag==' ] } }, + item2 = { a: { S: helpers.randomString() } }, + batchReq = { RequestItems: {} } + batchReq.RequestItems[helpers.testHashTable] = [ { PutRequest: { Item: item } }, { PutRequest: { Item: item2 } } ] + request(helpers.opts('BatchWriteItem', batchReq), function (err, res) { if (err) return done(err) res.statusCode.should.equal(200) - batchReq = {RequestItems: {}, ReturnConsumedCapacity: 'TOTAL'} - batchReq.RequestItems[helpers.testHashTable] = {Keys: [{a: item.a}, {a: item2.a}, {a: {S: helpers.randomString()}}], ConsistentRead: true} - batchReq.RequestItems[helpers.testHashNTable] = {Keys: [{a: {N: helpers.randomNumber()}}], ConsistentRead: true} - request(opts(batchReq), function(err, res) { + batchReq = { RequestItems: {}, ReturnConsumedCapacity: 'TOTAL' } + batchReq.RequestItems[helpers.testHashTable] = { Keys: [ { a: item.a }, { a: item2.a }, { a: { S: helpers.randomString() } } ], ConsistentRead: true } + batchReq.RequestItems[helpers.testHashNTable] = { Keys: [ { a: { N: helpers.randomNumber() } } ], ConsistentRead: true } + request(opts(batchReq), function (err, res) { if (err) return done(err) res.statusCode.should.equal(200) - res.body.ConsumedCapacity.should.containEql({CapacityUnits: 4, TableName: helpers.testHashTable}) - res.body.ConsumedCapacity.should.containEql({CapacityUnits: 1, TableName: helpers.testHashNTable}) + res.body.ConsumedCapacity.should.containEql({ CapacityUnits: 4, TableName: helpers.testHashTable }) + res.body.ConsumedCapacity.should.containEql({ CapacityUnits: 1, TableName: helpers.testHashNTable }) res.body.Responses[helpers.testHashTable].should.have.length(2) res.body.Responses[helpers.testHashNTable].should.have.length(0) batchReq.ReturnConsumedCapacity = 'INDEXES' - request(opts(batchReq), function(err, res) { + request(opts(batchReq), function (err, res) { if (err) return done(err) res.statusCode.should.equal(200) - res.body.ConsumedCapacity.should.containEql({CapacityUnits: 4, Table: {CapacityUnits: 4}, TableName: helpers.testHashTable}) - res.body.ConsumedCapacity.should.containEql({CapacityUnits: 1, Table: {CapacityUnits: 1}, TableName: helpers.testHashNTable}) + res.body.ConsumedCapacity.should.containEql({ CapacityUnits: 4, Table: { CapacityUnits: 4 }, TableName: helpers.testHashTable }) + res.body.ConsumedCapacity.should.containEql({ CapacityUnits: 1, Table: { CapacityUnits: 1 }, TableName: helpers.testHashNTable }) done() }) }) @@ -619,29 +619,30 @@ describe('batchGetItem', function() { // High capacity (~100 or more) needed to run this quickly if (runSlowTests) { - it('should return all items if just under limit', function(done) { + it('should return all items if just under limit', function (done) { this.timeout(200000) var i, item, items = [], b = new Array(helpers.MAX_SIZE - 6).join('b'), - batchReq = {RequestItems: {}, ReturnConsumedCapacity: 'TOTAL'} + batchReq = { RequestItems: {}, ReturnConsumedCapacity: 'TOTAL' } for (i = 0; i < 4; i++) { if (i < 3) { - item = {a: {S: ('0' + i).slice(-2)}, b: {S: b}} - } else { - item = {a: {S: ('0' + i).slice(-2)}, b: {S: b.slice(0, 229353)}, c: {N: '12.3456'}, d: {B: 'AQI='}, - e: {SS: ['a', 'bc']}, f: {NS: ['1.23', '12.3']}, g: {BS: ['AQI=', 'Ag==', 'AQ==']}} + item = { a: { S: ('0' + i).slice(-2) }, b: { S: b } } + } + else { + item = { a: { S: ('0' + i).slice(-2) }, b: { S: b.slice(0, 229353) }, c: { N: '12.3456' }, d: { B: 'AQI=' }, + e: { SS: [ 'a', 'bc' ] }, f: { NS: [ '1.23', '12.3' ] }, g: { BS: [ 'AQI=', 'Ag==', 'AQ==' ] } } } items.push(item) } - helpers.clearTable(helpers.testHashTable, 'a', function(err) { + helpers.clearTable(helpers.testHashTable, 'a', function (err) { if (err) return done(err) - helpers.batchWriteUntilDone(helpers.testHashTable, {puts: items}, function(err) { + helpers.batchWriteUntilDone(helpers.testHashTable, { puts: items }, function (err) { if (err) return done(err) - batchReq.RequestItems[helpers.testHashTable] = {Keys: items.map(function(item) { return {a: item.a} }), ConsistentRead: true} - request(opts(batchReq), function(err, res) { + batchReq.RequestItems[helpers.testHashTable] = { Keys: items.map(function (item) { return { a: item.a } }), ConsistentRead: true } + request(opts(batchReq), function (err, res) { if (err) return done(err) res.statusCode.should.equal(200) - res.body.ConsumedCapacity.should.eql([{CapacityUnits: 357, TableName: helpers.testHashTable}]) + res.body.ConsumedCapacity.should.eql([ { CapacityUnits: 357, TableName: helpers.testHashTable } ]) res.body.UnprocessedKeys.should.eql({}) res.body.Responses[helpers.testHashTable].should.have.length(4) helpers.clearTable(helpers.testHashTable, 'a', done) @@ -651,35 +652,37 @@ describe('batchGetItem', function() { }) // TODO: test fails! - it.skip('should return an unprocessed item if just over limit', function(done) { + it.skip('should return an unprocessed item if just over limit', function (done) { this.timeout(200000) var i, item, items = [], b = new Array(helpers.MAX_SIZE - 6).join('b'), - batchReq = {RequestItems: {}, ReturnConsumedCapacity: 'TOTAL'} + batchReq = { RequestItems: {}, ReturnConsumedCapacity: 'TOTAL' } for (i = 0; i < 4; i++) { if (i < 3) { - item = {a: {S: ('0' + i).slice(-2)}, b: {S: b}} - } else { - item = {a: {S: ('0' + i).slice(-2)}, b: {S: b.slice(0, 229354)}, c: {N: '12.3456'}, d: {B: 'AQI='}, - e: {SS: ['a', 'bc']}, f: {NS: ['1.23', '12.3']}, g: {BS: ['AQI=', 'Ag==', 'AQ==']}} + item = { a: { S: ('0' + i).slice(-2) }, b: { S: b } } + } + else { + item = { a: { S: ('0' + i).slice(-2) }, b: { S: b.slice(0, 229354) }, c: { N: '12.3456' }, d: { B: 'AQI=' }, + e: { SS: [ 'a', 'bc' ] }, f: { NS: [ '1.23', '12.3' ] }, g: { BS: [ 'AQI=', 'Ag==', 'AQ==' ] } } } items.push(item) } - helpers.batchWriteUntilDone(helpers.testHashTable, {puts: items}, function(err) { + helpers.batchWriteUntilDone(helpers.testHashTable, { puts: items }, function (err) { if (err) return done(err) - batchReq.RequestItems[helpers.testHashTable] = {Keys: items.map(function(item) { return {a: item.a} }), ConsistentRead: true} - request(opts(batchReq), function(err, res) { + batchReq.RequestItems[helpers.testHashTable] = { Keys: items.map(function (item) { return { a: item.a } }), ConsistentRead: true } + request(opts(batchReq), function (err, res) { if (err) return done(err) res.statusCode.should.equal(200) res.body.UnprocessedKeys[helpers.testHashTable].ConsistentRead.should.equal(true) res.body.UnprocessedKeys[helpers.testHashTable].Keys.should.have.length(1) Object.keys(res.body.UnprocessedKeys[helpers.testHashTable].Keys[0]).should.have.length(1) if (res.body.UnprocessedKeys[helpers.testHashTable].Keys[0].a.S == '03') { - res.body.ConsumedCapacity.should.eql([{CapacityUnits: 301, TableName: helpers.testHashTable}]) - } else { + res.body.ConsumedCapacity.should.eql([ { CapacityUnits: 301, TableName: helpers.testHashTable } ]) + } + else { res.body.UnprocessedKeys[helpers.testHashTable].Keys[0].a.S.should.be.above(-1) res.body.UnprocessedKeys[helpers.testHashTable].Keys[0].a.S.should.be.below(4) - res.body.ConsumedCapacity.should.eql([{CapacityUnits: 258, TableName: helpers.testHashTable}]) + res.body.ConsumedCapacity.should.eql([ { CapacityUnits: 258, TableName: helpers.testHashTable } ]) } res.body.Responses[helpers.testHashTable].should.have.length(3) helpers.clearTable(helpers.testHashTable, 'a', done) @@ -687,23 +690,24 @@ describe('batchGetItem', function() { }) }) - it('should return many unprocessed items if very over the limit', function(done) { + it('should return many unprocessed items if very over the limit', function (done) { this.timeout(200000) var i, item, items = [], b = new Array(helpers.MAX_SIZE - 3).join('b'), - batchReq = {RequestItems: {}, ReturnConsumedCapacity: 'TOTAL'} + batchReq = { RequestItems: {}, ReturnConsumedCapacity: 'TOTAL' } for (i = 0; i < 20; i++) { if (i < 3) { - item = {a: {S: ('0' + i).slice(-2)}, b: {S: b}} - } else { - item = {a: {S: ('0' + i).slice(-2)}, b: {S: b.slice(0, 20000)}} + item = { a: { S: ('0' + i).slice(-2) }, b: { S: b } } + } + else { + item = { a: { S: ('0' + i).slice(-2) }, b: { S: b.slice(0, 20000) } } } items.push(item) } - helpers.batchBulkPut(helpers.testHashTable, items, function(err) { + helpers.batchBulkPut(helpers.testHashTable, items, function (err) { if (err) return done(err) - batchReq.RequestItems[helpers.testHashTable] = {Keys: items.map(function(item) { return {a: item.a} }), ConsistentRead: true} - request(opts(batchReq), function(err, res) { + batchReq.RequestItems[helpers.testHashTable] = { Keys: items.map(function (item) { return { a: item.a } }), ConsistentRead: true } + request(opts(batchReq), function (err, res) { if (err) return done(err) res.statusCode.should.equal(200) res.body.UnprocessedKeys[helpers.testHashTable].ConsistentRead.should.equal(true) diff --git a/test/batchWriteItem.js b/test/batchWriteItem.js index 1dfcc9e..cbbf7ae 100644 --- a/test/batchWriteItem.js +++ b/test/batchWriteItem.js @@ -1,78 +1,78 @@ var async = require('async'), - helpers = require('./helpers'), - db = require('../db') + helpers = require('./helpers'), + db = require('../db') var target = 'BatchWriteItem', - request = helpers.request, - randomName = helpers.randomName, - opts = helpers.opts.bind(null, target), - assertType = helpers.assertType.bind(null, target), - assertValidation = helpers.assertValidation.bind(null, target), - assertNotFound = helpers.assertNotFound.bind(null, target) + request = helpers.request, + randomName = helpers.randomName, + opts = helpers.opts.bind(null, target), + assertType = helpers.assertType.bind(null, target), + assertValidation = helpers.assertValidation.bind(null, target), + assertNotFound = helpers.assertNotFound.bind(null, target) -describe('batchWriteItem', function() { +describe('batchWriteItem', function () { - describe('serializations', function() { + describe('serializations', function () { - it('should return SerializationException when RequestItems is not a map', function(done) { + it('should return SerializationException when RequestItems is not a map', function (done) { assertType('RequestItems', 'Map>', done) }) - it('should return SerializationException when RequestItems.Attr is not a list', function(done) { + it('should return SerializationException when RequestItems.Attr is not a list', function (done) { assertType('RequestItems.Attr', 'ParameterizedList', done) }) - it('should return SerializationException when RequestItems.Attr.0 is not a struct', function(done) { + it('should return SerializationException when RequestItems.Attr.0 is not a struct', function (done) { assertType('RequestItems.Attr.0', 'ValueStruct', done) }) - it('should return SerializationException when RequestItems.Attr.0.DeleteRequest is not a struct', function(done) { + it('should return SerializationException when RequestItems.Attr.0.DeleteRequest is not a struct', function (done) { assertType('RequestItems.Attr.0.DeleteRequest', 'FieldStruct', done) }) - it('should return SerializationException when RequestItems.Attr.0.DeleteRequest.Key is not a map', function(done) { + it('should return SerializationException when RequestItems.Attr.0.DeleteRequest.Key is not a map', function (done) { assertType('RequestItems.Attr.0.DeleteRequest.Key', 'Map', done) }) - it('should return SerializationException when RequestItems.Attr.0.DeleteRequest.Key.Attr is not an attr struct', function(done) { + it('should return SerializationException when RequestItems.Attr.0.DeleteRequest.Key.Attr is not an attr struct', function (done) { this.timeout(60000) assertType('RequestItems.Attr.0.DeleteRequest.Key.Attr', 'AttrStruct', done) }) - it('should return SerializationException when RequestItems.Attr.0.PutRequest is not a struct', function(done) { + it('should return SerializationException when RequestItems.Attr.0.PutRequest is not a struct', function (done) { assertType('RequestItems.Attr.0.PutRequest', 'FieldStruct', done) }) - it('should return SerializationException when RequestItems.Attr.0.PutRequest.Item is not a map', function(done) { + it('should return SerializationException when RequestItems.Attr.0.PutRequest.Item is not a map', function (done) { assertType('RequestItems.Attr.0.PutRequest.Item', 'Map', done) }) - it('should return SerializationException when RequestItems.Attr.0.PutRequest.Item.Attr is not an attr struct', function(done) { + it('should return SerializationException when RequestItems.Attr.0.PutRequest.Item.Attr is not an attr struct', function (done) { this.timeout(60000) assertType('RequestItems.Attr.0.PutRequest.Item.Attr', 'AttrStruct', done) }) - it('should return SerializationException when ReturnConsumedCapacity is not a string', function(done) { + it('should return SerializationException when ReturnConsumedCapacity is not a string', function (done) { assertType('ReturnConsumedCapacity', 'String', done) }) - it('should return SerializationException when ReturnItemCollectionMetrics is not a string', function(done) { + it('should return SerializationException when ReturnItemCollectionMetrics is not a string', function (done) { assertType('ReturnItemCollectionMetrics', 'String', done) }) }) - describe('validations', function() { + describe('validations', function () { - it('should return ValidationException for empty body', function(done) { + it('should return ValidationException for empty body', function (done) { assertValidation({}, '1 validation error detected: ' + 'Value null at \'requestItems\' failed to satisfy constraint: ' + 'Member must not be null', done) }) - it('should return ValidationException for missing RequestItems', function(done) { - assertValidation({ReturnConsumedCapacity: 'hi', ReturnItemCollectionMetrics: 'hi'}, [ + it('should return ValidationException for missing RequestItems', function (done) { + assertValidation({ ReturnConsumedCapacity: 'hi', ReturnItemCollectionMetrics: 'hi' }, [ 'Value \'hi\' at \'returnConsumedCapacity\' failed to satisfy constraint: ' + 'Member must satisfy enum value set: [INDEXES, TOTAL, NONE]', 'Value \'hi\' at \'returnItemCollectionMetrics\' failed to satisfy constraint: ' + @@ -82,15 +82,15 @@ describe('batchWriteItem', function() { ], done) }) - it('should return ValidationException for empty RequestItems', function(done) { - assertValidation({RequestItems: {}}, + it('should return ValidationException for empty RequestItems', function (done) { + assertValidation({ RequestItems: {} }, '1 validation error detected: ' + 'Value \'{}\' at \'requestItems\' failed to satisfy constraint: ' + 'Member must have length greater than or equal to 1', done) }) - it('should return ValidationException for empty list in RequestItems', function(done) { - assertValidation({RequestItems: {a: []}}, [ + it('should return ValidationException for empty list in RequestItems', function (done) { + assertValidation({ RequestItems: { a: [] } }, [ new RegExp('Value \'{.+}\' at \'requestItems\' failed to satisfy constraint: ' + 'Map keys must satisfy constraint: ' + '\\[Member must have length less than or equal to 255, ' + @@ -103,14 +103,14 @@ describe('batchWriteItem', function() { ], done) }) - it('should return ValidationException for empty item in RequestItems', function(done) { - assertValidation({RequestItems: {abc: [{}]}}, + it('should return ValidationException for empty item in RequestItems', function (done) { + assertValidation({ RequestItems: { abc: [ {} ] } }, 'Supplied AttributeValue has more than one datatypes set, ' + 'must contain exactly one of the supported datatypes', done) }) - it('should return ValidationException for short table name and missing requests', function(done) { - assertValidation({RequestItems: {a: []}, ReturnConsumedCapacity: 'hi', ReturnItemCollectionMetrics: 'hi'}, [ + it('should return ValidationException for short table name and missing requests', function (done) { + assertValidation({ RequestItems: { a: [] }, ReturnConsumedCapacity: 'hi', ReturnItemCollectionMetrics: 'hi' }, [ 'Value \'hi\' at \'returnConsumedCapacity\' failed to satisfy constraint: ' + 'Member must satisfy enum value set: [INDEXES, TOTAL, NONE]', 'Value \'hi\' at \'returnItemCollectionMetrics\' failed to satisfy constraint: ' + @@ -127,31 +127,31 @@ describe('batchWriteItem', function() { ], done) }) - it('should return ValidationException for incorrect attributes', function(done) { - assertValidation({RequestItems: {'aa;': [{PutRequest: {}, DeleteRequest: {}}]}, - ReturnConsumedCapacity: 'hi', ReturnItemCollectionMetrics: 'hi'}, [ - 'Value \'hi\' at \'returnConsumedCapacity\' failed to satisfy constraint: ' + + it('should return ValidationException for incorrect attributes', function (done) { + assertValidation({ RequestItems: { 'aa;': [ { PutRequest: {}, DeleteRequest: {} } ] }, + ReturnConsumedCapacity: 'hi', ReturnItemCollectionMetrics: 'hi' }, [ + 'Value \'hi\' at \'returnConsumedCapacity\' failed to satisfy constraint: ' + 'Member must satisfy enum value set: [INDEXES, TOTAL, NONE]', - 'Value \'hi\' at \'returnItemCollectionMetrics\' failed to satisfy constraint: ' + + 'Value \'hi\' at \'returnItemCollectionMetrics\' failed to satisfy constraint: ' + 'Member must satisfy enum value set: [SIZE, NONE]', - new RegExp('Value \'{.+}\' at \'requestItems\' ' + + new RegExp('Value \'{.+}\' at \'requestItems\' ' + 'failed to satisfy constraint: Map keys must satisfy constraint: ' + '\\[Member must have length less than or equal to 255, ' + 'Member must have length greater than or equal to 3, ' + 'Member must satisfy regular expression pattern: \\[a-zA-Z0-9_.-\\]\\+\\]'), - 'Value null at \'requestItems.aa;.member.1.member.deleteRequest.key\' failed to satisfy constraint: ' + + 'Value null at \'requestItems.aa;.member.1.member.deleteRequest.key\' failed to satisfy constraint: ' + 'Member must not be null', - 'Value null at \'requestItems.aa;.member.1.member.putRequest.item\' failed to satisfy constraint: ' + + 'Value null at \'requestItems.aa;.member.1.member.putRequest.item\' failed to satisfy constraint: ' + 'Member must not be null', - ], done) + ], done) }) - it('should return ValidationException when putting more than 25 items', function(done) { + it('should return ValidationException when putting more than 25 items', function (done) { var requests = [], i for (i = 0; i < 26; i++) { - requests.push(i % 2 ? {DeleteRequest: {Key: {a: {S: String(i)}}}} : {PutRequest: {Item: {a: {S: String(i)}}}}) + requests.push(i % 2 ? { DeleteRequest: { Key: { a: { S: String(i) } } } } : { PutRequest: { Item: { a: { S: String(i) } } } }) } - assertValidation({RequestItems: {abc: requests}}, + assertValidation({ RequestItems: { abc: requests } }, new RegExp('1 validation error detected: ' + 'Value \'{.+}\' at \'requestItems\' failed to satisfy constraint: ' + 'Map value must satisfy constraint: ' + @@ -159,37 +159,37 @@ describe('batchWriteItem', function() { 'Member must have length greater than or equal to 1\\]'), done) }) - it('should return ResourceNotFoundException when fetching exactly 25 items and table does not exist', function(done) { + it('should return ResourceNotFoundException when fetching exactly 25 items and table does not exist', function (done) { var requests = [], i for (i = 0; i < 25; i++) { - requests.push(i % 2 ? {DeleteRequest: {Key: {a: {S: String(i)}}}} : {PutRequest: {Item: {a: {S: String(i)}}}}) + requests.push(i % 2 ? { DeleteRequest: { Key: { a: { S: String(i) } } } } : { PutRequest: { Item: { a: { S: String(i) } } } }) } - assertNotFound({RequestItems: {abc: requests}}, + assertNotFound({ RequestItems: { abc: requests } }, 'Requested resource not found', done) }) - it('should check table exists first before checking for duplicate keys', function(done) { - var item = {a: {S: helpers.randomString()}, c: {S: 'c'}} - assertNotFound({RequestItems: {abc: [{PutRequest: {Item: item}}, {DeleteRequest: {Key: {a: item.a}}}]}}, - 'Requested resource not found', done) + it('should check table exists first before checking for duplicate keys', function (done) { + var item = { a: { S: helpers.randomString() }, c: { S: 'c' } } + assertNotFound({ RequestItems: { abc: [ { PutRequest: { Item: item } }, { DeleteRequest: { Key: { a: item.a } } } ] } }, + 'Requested resource not found', done) }) - it('should return ValidationException for puts and deletes of the same item with put first', function(done) { - var item = {a: {S: helpers.randomString()}, c: {S: 'c'}}, - batchReq = {RequestItems: {}} - batchReq.RequestItems[helpers.testHashTable] = [{PutRequest: {Item: item}}, {DeleteRequest: {Key: {a: item.a}}}] + it('should return ValidationException for puts and deletes of the same item with put first', function (done) { + var item = { a: { S: helpers.randomString() }, c: { S: 'c' } }, + batchReq = { RequestItems: {} } + batchReq.RequestItems[helpers.testHashTable] = [ { PutRequest: { Item: item } }, { DeleteRequest: { Key: { a: item.a } } } ] assertValidation(batchReq, 'Provided list of item keys contains duplicates', done) }) - it('should return ValidationException for puts and deletes of the same item with delete first', function(done) { - var item = {a: {S: helpers.randomString()}, c: {S: 'c'}}, - batchReq = {RequestItems: {}} - batchReq.RequestItems[helpers.testHashTable] = [{DeleteRequest: {Key: {a: item.a}}}, {PutRequest: {Item: item}}] + it('should return ValidationException for puts and deletes of the same item with delete first', function (done) { + var item = { a: { S: helpers.randomString() }, c: { S: 'c' } }, + batchReq = { RequestItems: {} } + batchReq.RequestItems[helpers.testHashTable] = [ { DeleteRequest: { Key: { a: item.a } } }, { PutRequest: { Item: item } } ] assertValidation(batchReq, 'Provided list of item keys contains duplicates', done) }) - it('should return ValidationException for short table name', function(done) { - assertValidation({RequestItems: {a: [{PutRequest: {Item: {a: {S: 'a'}}}}]}}, + it('should return ValidationException for short table name', function (done) { + assertValidation({ RequestItems: { a: [ { PutRequest: { Item: { a: { S: 'a' } } } } ] } }, new RegExp('1 validation error detected: ' + 'Value \'{.+}\' at \'requestItems\' ' + 'failed to satisfy constraint: ' + @@ -199,220 +199,220 @@ describe('batchWriteItem', function() { 'Member must satisfy regular expression pattern: \\[a-zA-Z0-9_.-\\]\\+\\]'), done) }) - it('should return ValidationException for unsupported datatype in Item', function(done) { + it('should return ValidationException for unsupported datatype in Item', function (done) { async.forEach([ {}, - {a: ''}, - {M: {a: {}}}, - {L: [{}]}, - {L: [{a: {}}]}, - ], function(expr, cb) { - assertValidation({RequestItems: {abc: [{PutRequest: {Item: {a: expr}}}]}}, + { a: '' }, + { M: { a: {} } }, + { L: [ {} ] }, + { L: [ { a: {} } ] }, + ], function (expr, cb) { + assertValidation({ RequestItems: { abc: [ { PutRequest: { Item: { a: expr } } } ] } }, 'Supplied AttributeValue is empty, must contain exactly one of the supported datatypes', cb) }, done) }) - it('should return ValidationException for invalid values in Item', function(done) { + it('should return ValidationException for invalid values in Item', function (done) { async.forEach([ - [{NULL: 'no'}, 'Null attribute value types must have the value of true'], - [{SS: []}, 'An string set may not be empty'], - [{NS: []}, 'An number set may not be empty'], - [{BS: []}, 'Binary sets should not be empty'], - [{SS: ['a', 'a']}, 'Input collection [a, a] contains duplicates.'], - [{BS: ['Yg==', 'Yg==']}, 'Input collection [Yg==, Yg==]of type BS contains duplicates.'], - ], function(expr, cb) { - assertValidation({RequestItems: {abc: [{PutRequest: {Item: {a: expr[0]}}}]}}, + [ { NULL: 'no' }, 'Null attribute value types must have the value of true' ], + [ { SS: [] }, 'An string set may not be empty' ], + [ { NS: [] }, 'An number set may not be empty' ], + [ { BS: [] }, 'Binary sets should not be empty' ], + [ { SS: [ 'a', 'a' ] }, 'Input collection [a, a] contains duplicates.' ], + [ { BS: [ 'Yg==', 'Yg==' ] }, 'Input collection [Yg==, Yg==]of type BS contains duplicates.' ], + ], function (expr, cb) { + assertValidation({ RequestItems: { abc: [ { PutRequest: { Item: { a: expr[0] } } } ] } }, 'One or more parameter values were invalid: ' + expr[1], cb) }, done) }) - it('should return ValidationException for empty/invalid numbers in Item', function(done) { + it('should return ValidationException for empty/invalid numbers in Item', function (done) { async.forEach([ - [{S: '', N: ''}, 'The parameter cannot be converted to a numeric value'], - [{S: 'a', N: ''}, 'The parameter cannot be converted to a numeric value'], - [{S: 'a', N: 'b'}, 'The parameter cannot be converted to a numeric value: b'], - [{NS: ['1', '']}, 'The parameter cannot be converted to a numeric value'], - [{NS: ['1', 'b']}, 'The parameter cannot be converted to a numeric value: b'], - [{NS: ['1', '1']}, 'Input collection contains duplicates'], - [{N: '123456789012345678901234567890123456789'}, 'Attempting to store more than 38 significant digits in a Number'], - [{N: '-1.23456789012345678901234567890123456789'}, 'Attempting to store more than 38 significant digits in a Number'], - [{N: '1e126'}, 'Number overflow. Attempting to store a number with magnitude larger than supported range'], - [{N: '-1e126'}, 'Number overflow. Attempting to store a number with magnitude larger than supported range'], - [{N: '1e-131'}, 'Number underflow. Attempting to store a number with magnitude smaller than supported range'], - [{N: '-1e-131'}, 'Number underflow. Attempting to store a number with magnitude smaller than supported range'], - ], function(expr, cb) { - assertValidation({RequestItems: {abc: [{PutRequest: {Item: {a: expr[0]}}}]}}, expr[1], cb) + [ { S: '', N: '' }, 'The parameter cannot be converted to a numeric value' ], + [ { S: 'a', N: '' }, 'The parameter cannot be converted to a numeric value' ], + [ { S: 'a', N: 'b' }, 'The parameter cannot be converted to a numeric value: b' ], + [ { NS: [ '1', '' ] }, 'The parameter cannot be converted to a numeric value' ], + [ { NS: [ '1', 'b' ] }, 'The parameter cannot be converted to a numeric value: b' ], + [ { NS: [ '1', '1' ] }, 'Input collection contains duplicates' ], + [ { N: '123456789012345678901234567890123456789' }, 'Attempting to store more than 38 significant digits in a Number' ], + [ { N: '-1.23456789012345678901234567890123456789' }, 'Attempting to store more than 38 significant digits in a Number' ], + [ { N: '1e126' }, 'Number overflow. Attempting to store a number with magnitude larger than supported range' ], + [ { N: '-1e126' }, 'Number overflow. Attempting to store a number with magnitude larger than supported range' ], + [ { N: '1e-131' }, 'Number underflow. Attempting to store a number with magnitude smaller than supported range' ], + [ { N: '-1e-131' }, 'Number underflow. Attempting to store a number with magnitude smaller than supported range' ], + ], function (expr, cb) { + assertValidation({ RequestItems: { abc: [ { PutRequest: { Item: { a: expr[0] } } } ] } }, expr[1], cb) }, done) }) - it('should return ValidationException for multiple datatypes in Item', function(done) { - assertValidation({RequestItems: {abc: [{PutRequest: {Item: {a: {S: 'a', N: '1'}}}}]}}, + it('should return ValidationException for multiple datatypes in Item', function (done) { + assertValidation({ RequestItems: { abc: [ { PutRequest: { Item: { a: { S: 'a', N: '1' } } } } ] } }, 'Supplied AttributeValue has more than one datatypes set, must contain exactly one of the supported datatypes', done) }) - it('should return ValidationException if item is too big with small attribute', function(done) { + it('should return ValidationException if item is too big with small attribute', function (done) { var keyStr = helpers.randomString(), b = new Array(helpers.MAX_SIZE + 1 - keyStr.length - 1).join('a') - assertValidation({RequestItems: {abc: [{PutRequest: {Item: {a: {S: keyStr}, b: {S: b}}}}]}}, + assertValidation({ RequestItems: { abc: [ { PutRequest: { Item: { a: { S: keyStr }, b: { S: b } } } } ] } }, 'Item size has exceeded the maximum allowed size', done) }) - it('should return ResourceNotFoundException if item is just small enough with small attribute', function(done) { + it('should return ResourceNotFoundException if item is just small enough with small attribute', function (done) { var keyStr = helpers.randomString(), b = new Array(helpers.MAX_SIZE + 1 - keyStr.length - 2).join('a') - assertNotFound({RequestItems: {abc: [{PutRequest: {Item: {a: {S: keyStr}, b: {S: b}}}}]}}, + assertNotFound({ RequestItems: { abc: [ { PutRequest: { Item: { a: { S: keyStr }, b: { S: b } } } } ] } }, 'Requested resource not found', done) }) - it('should return ValidationException if item is too big with larger attribute', function(done) { + it('should return ValidationException if item is too big with larger attribute', function (done) { var keyStr = helpers.randomString(), b = new Array(helpers.MAX_SIZE + 1 - keyStr.length - 27).join('a') - assertValidation({RequestItems: {abc: [{PutRequest: {Item: {a: {S: keyStr}, bbbbbbbbbbbbbbbbbbbbbbbbbbb: {S: b}}}}]}}, + assertValidation({ RequestItems: { abc: [ { PutRequest: { Item: { a: { S: keyStr }, bbbbbbbbbbbbbbbbbbbbbbbbbbb: { S: b } } } } ] } }, 'Item size has exceeded the maximum allowed size', done) }) - it('should return ResourceNotFoundException if item is just small enough with larger attribute', function(done) { + it('should return ResourceNotFoundException if item is just small enough with larger attribute', function (done) { var keyStr = helpers.randomString(), b = new Array(helpers.MAX_SIZE + 1 - keyStr.length - 28).join('a') - assertNotFound({RequestItems: {abc: [{PutRequest: {Item: {a: {S: keyStr}, bbbbbbbbbbbbbbbbbbbbbbbbbbb: {S: b}}}}]}}, + assertNotFound({ RequestItems: { abc: [ { PutRequest: { Item: { a: { S: keyStr }, bbbbbbbbbbbbbbbbbbbbbbbbbbb: { S: b } } } } ] } }, 'Requested resource not found', done) }) - it('should return ValidationException if item is too big with multi attributes', function(done) { + it('should return ValidationException if item is too big with multi attributes', function (done) { var keyStr = helpers.randomString(), b = new Array(helpers.MAX_SIZE + 1 - keyStr.length - 7).join('a') - assertValidation({RequestItems: {abc: [{PutRequest: {Item: {a: {S: keyStr}, bb: {S: b}, ccc: {S: 'cc'}}}}]}}, + assertValidation({ RequestItems: { abc: [ { PutRequest: { Item: { a: { S: keyStr }, bb: { S: b }, ccc: { S: 'cc' } } } } ] } }, 'Item size has exceeded the maximum allowed size', done) }) - it('should return ResourceNotFoundException if item is just small enough with multi attributes', function(done) { + it('should return ResourceNotFoundException if item is just small enough with multi attributes', function (done) { var keyStr = helpers.randomString(), b = new Array(helpers.MAX_SIZE + 1 - keyStr.length - 8).join('a') - assertNotFound({RequestItems: {abc: [{PutRequest: {Item: {a: {S: keyStr}, bb: {S: b}, ccc: {S: 'cc'}}}}]}}, + assertNotFound({ RequestItems: { abc: [ { PutRequest: { Item: { a: { S: keyStr }, bb: { S: b }, ccc: { S: 'cc' } } } } ] } }, 'Requested resource not found', done) }) - it('should return ValidationException if item is too big with big number attribute', function(done) { + it('should return ValidationException if item is too big with big number attribute', function (done) { var keyStr = helpers.randomString(), b = new Array(helpers.MAX_SIZE + 1 - keyStr.length - 1 - 1 - 20).join('a'), c = new Array(38 + 1).join('1') + new Array(89).join('0') - assertValidation({RequestItems: {abc: [{PutRequest: {Item: {a: {S: keyStr}, b: {S: b}, c: {N: c}}}}]}}, + assertValidation({ RequestItems: { abc: [ { PutRequest: { Item: { a: { S: keyStr }, b: { S: b }, c: { N: c } } } } ] } }, 'Item size has exceeded the maximum allowed size', done) }) - it('should return ValidationException if item is too big with smallest number attribute', function(done) { + it('should return ValidationException if item is too big with smallest number attribute', function (done) { var keyStr = helpers.randomString(), b = new Array(helpers.MAX_SIZE + 1 - keyStr.length - 1 - 1 - 2).join('a'), c = '1' + new Array(126).join('0') - assertValidation({RequestItems: {abc: [{PutRequest: {Item: {a: {S: keyStr}, b: {S: b}, c: {N: c}}}}]}}, + assertValidation({ RequestItems: { abc: [ { PutRequest: { Item: { a: { S: keyStr }, b: { S: b }, c: { N: c } } } } ] } }, 'Item size has exceeded the maximum allowed size', done) }) - it('should return ValidationException if item is too big with smaller number attribute', function(done) { + it('should return ValidationException if item is too big with smaller number attribute', function (done) { var keyStr = helpers.randomString(), b = new Array(helpers.MAX_SIZE + 1 - keyStr.length - 1 - 1 - 2).join('a'), c = '11' + new Array(125).join('0') - assertValidation({RequestItems: {abc: [{PutRequest: {Item: {a: {S: keyStr}, b: {S: b}, c: {N: c}}}}]}}, + assertValidation({ RequestItems: { abc: [ { PutRequest: { Item: { a: { S: keyStr }, b: { S: b }, c: { N: c } } } } ] } }, 'Item size has exceeded the maximum allowed size', done) }) - it('should return ValidationException if item is too big with medium number attribute', function(done) { + it('should return ValidationException if item is too big with medium number attribute', function (done) { var keyStr = helpers.randomString(), b = new Array(helpers.MAX_SIZE + 1 - keyStr.length - 1 - 1 - 4).join('a'), c = '11111' + new Array(122).join('0') - assertValidation({RequestItems: {abc: [{PutRequest: {Item: {a: {S: keyStr}, b: {S: b}, c: {N: c}}}}]}}, + assertValidation({ RequestItems: { abc: [ { PutRequest: { Item: { a: { S: keyStr }, b: { S: b }, c: { N: c } } } } ] } }, 'Item size has exceeded the maximum allowed size', done) }) - it('should return ValidationException if item is too big with medium number attribute', function(done) { + it('should return ValidationException if item is too big with medium number attribute', function (done) { var keyStr = helpers.randomString(), b = new Array(helpers.MAX_SIZE + 1 - keyStr.length - 1 - 1 - 4).join('a'), c = '111111' + new Array(121).join('0') - assertValidation({RequestItems: {abc: [{PutRequest: {Item: {a: {S: keyStr}, b: {S: b}, c: {N: c}}}}]}}, + assertValidation({ RequestItems: { abc: [ { PutRequest: { Item: { a: { S: keyStr }, b: { S: b }, c: { N: c } } } } ] } }, 'Item size has exceeded the maximum allowed size', done) }) - it('should return ValidationException if item is too big with medium number attribute', function(done) { + it('should return ValidationException if item is too big with medium number attribute', function (done) { var keyStr = helpers.randomString(), b = new Array(helpers.MAX_SIZE + 1 - keyStr.length - 1 - 1 - 5).join('a'), c = '1111111' + new Array(120).join('0') - assertValidation({RequestItems: {abc: [{PutRequest: {Item: {a: {S: keyStr}, b: {S: b}, c: {N: c}}}}]}}, + assertValidation({ RequestItems: { abc: [ { PutRequest: { Item: { a: { S: keyStr }, b: { S: b }, c: { N: c } } } } ] } }, 'Item size has exceeded the maximum allowed size', done) }) - it('should return ValidationException if item is too big with multi number attribute', function(done) { + it('should return ValidationException if item is too big with multi number attribute', function (done) { var keyStr = helpers.randomString(), b = new Array(helpers.MAX_SIZE + 1 - keyStr.length - 1 - 1 - 5 - 1 - 5).join('a'), c = '1111111' + new Array(120).join('0'), d = '1111111' + new Array(120).join('0') - assertValidation({RequestItems: {abc: [{PutRequest: {Item: {a: {S: keyStr}, b: {S: b}, c: {N: c}, d: {N: d}}}}]}}, + assertValidation({ RequestItems: { abc: [ { PutRequest: { Item: { a: { S: keyStr }, b: { S: b }, c: { N: c }, d: { N: d } } } } ] } }, 'Item size has exceeded the maximum allowed size', done) }) - it('should return ResourceNotFoundException if item is just small enough with multi number attribute', function(done) { + it('should return ResourceNotFoundException if item is just small enough with multi number attribute', function (done) { var keyStr = helpers.randomString(), b = new Array(helpers.MAX_SIZE + 1 - keyStr.length - 1 - 1 - 5 - 1 - 6).join('a'), c = '1111111' + new Array(120).join('0'), d = '1111111' + new Array(120).join('0') - assertNotFound({RequestItems: {abc: [{PutRequest: {Item: {a: {S: keyStr}, b: {S: b}, c: {N: c}, d: {N: d}}}}]}}, + assertNotFound({ RequestItems: { abc: [ { PutRequest: { Item: { a: { S: keyStr }, b: { S: b }, c: { N: c }, d: { N: d } } } } ] } }, 'Requested resource not found', done) }) - it('should return ResourceNotFoundException if key is empty and table does not exist', function(done) { - var batchReq = {RequestItems: {}} - batchReq.RequestItems[helpers.randomString()] = [{PutRequest: {Item: {}}}] + it('should return ResourceNotFoundException if key is empty and table does not exist', function (done) { + var batchReq = { RequestItems: {} } + batchReq.RequestItems[helpers.randomString()] = [ { PutRequest: { Item: {} } } ] assertNotFound(batchReq, 'Requested resource not found', done) }) - it('should return ValidationException if key does not match schema', function(done) { + it('should return ValidationException if key does not match schema', function (done) { async.forEach([ {}, - {b: {S: 'a'}}, - {a: {B: 'abcd'}}, - {a: {N: '1'}}, - {a: {BOOL: true}}, - {a: {NULL: true}}, - {a: {SS: ['a']}}, - {a: {NS: ['1']}}, - {a: {BS: ['aaaa']}}, - {a: {M: {}}}, - {a: {L: []}}, - ], function(expr, cb) { - var batchReq = {RequestItems: {}} - batchReq.RequestItems[helpers.testHashTable] = [{PutRequest: {Item: expr}}] + { b: { S: 'a' } }, + { a: { B: 'abcd' } }, + { a: { N: '1' } }, + { a: { BOOL: true } }, + { a: { NULL: true } }, + { a: { SS: [ 'a' ] } }, + { a: { NS: [ '1' ] } }, + { a: { BS: [ 'aaaa' ] } }, + { a: { M: {} } }, + { a: { L: [] } }, + ], function (expr, cb) { + var batchReq = { RequestItems: {} } + batchReq.RequestItems[helpers.testHashTable] = [ { PutRequest: { Item: expr } } ] assertValidation(batchReq, 'The provided key element does not match the schema', cb) }, done) }) - it('should return ValidationException if range key does not match schema', function(done) { - var batchReq = {RequestItems: {}} - batchReq.RequestItems[helpers.testRangeTable] = [{PutRequest: {Item: {a: {S: 'a'}}}}] + it('should return ValidationException if range key does not match schema', function (done) { + var batchReq = { RequestItems: {} } + batchReq.RequestItems[helpers.testRangeTable] = [ { PutRequest: { Item: { a: { S: 'a' } } } } ] assertValidation(batchReq, 'The provided key element does not match the schema', done) }) - it('should return ValidationException if secondary index key is incorrect type', function(done) { - var batchReq = {RequestItems: {}} - batchReq.RequestItems[helpers.testRangeTable] = [{PutRequest: {Item: {a: {S: 'a'}, b: {S: 'a'}, c: {N: '1'}}}}] + it('should return ValidationException if secondary index key is incorrect type', function (done) { + var batchReq = { RequestItems: {} } + batchReq.RequestItems[helpers.testRangeTable] = [ { PutRequest: { Item: { a: { S: 'a' }, b: { S: 'a' }, c: { N: '1' } } } } ] assertValidation(batchReq, new RegExp('^One or more parameter values were invalid: ' + 'Type mismatch for Index Key c Expected: S Actual: N IndexName: index\\d$'), done) }) - it('should return ValidationException if hash key is too big', function(done) { - var batchReq = {RequestItems: {}}, keyStr = (helpers.randomString() + new Array(2048).join('a')).slice(0, 2049) - batchReq.RequestItems[helpers.testHashTable] = [{PutRequest: {Item: {a: {S: keyStr}}}}] + it('should return ValidationException if hash key is too big', function (done) { + var batchReq = { RequestItems: {} }, keyStr = (helpers.randomString() + new Array(2048).join('a')).slice(0, 2049) + batchReq.RequestItems[helpers.testHashTable] = [ { PutRequest: { Item: { a: { S: keyStr } } } } ] assertValidation(batchReq, 'One or more parameter values were invalid: ' + 'Size of hashkey has exceeded the maximum size limit of2048 bytes', done) }) - it('should return ValidationException if range key is too big', function(done) { - var batchReq = {RequestItems: {}}, keyStr = (helpers.randomString() + new Array(1024).join('a')).slice(0, 1025) - batchReq.RequestItems[helpers.testRangeTable] = [{PutRequest: {Item: {a: {S: 'a'}, b: {S: keyStr}}}}] + it('should return ValidationException if range key is too big', function (done) { + var batchReq = { RequestItems: {} }, keyStr = (helpers.randomString() + new Array(1024).join('a')).slice(0, 1025) + batchReq.RequestItems[helpers.testRangeTable] = [ { PutRequest: { Item: { a: { S: 'a' }, b: { S: keyStr } } } } ] assertValidation(batchReq, 'One or more parameter values were invalid: ' + 'Aggregated size of all range keys has exceeded the size limit of 1024 bytes', done) }) - it('should return ResourceNotFoundException if table is being created', function(done) { + it('should return ResourceNotFoundException if table is being created', function (done) { var table = { TableName: randomName(), - AttributeDefinitions: [{AttributeName: 'a', AttributeType: 'S'}], - KeySchema: [{KeyType: 'HASH', AttributeName: 'a'}], - ProvisionedThroughput: {ReadCapacityUnits: 1, WriteCapacityUnits: 1}, + AttributeDefinitions: [ { AttributeName: 'a', AttributeType: 'S' } ], + KeySchema: [ { KeyType: 'HASH', AttributeName: 'a' } ], + ProvisionedThroughput: { ReadCapacityUnits: 1, WriteCapacityUnits: 1 }, } - request(helpers.opts('CreateTable', table), function(err, res) { + request(helpers.opts('CreateTable', table), function (err, res) { if (err) return done(err) res.statusCode.should.equal(200) - var batchReq = {RequestItems: {}} - batchReq.RequestItems[table.TableName] = [{PutRequest: {Item: {a: {S: 'a'}}}}] + var batchReq = { RequestItems: {} } + batchReq.RequestItems[table.TableName] = [ { PutRequest: { Item: { a: { S: 'a' } } } } ] assertNotFound(batchReq, 'Requested resource not found', done) helpers.deleteWhenActive(table.TableName) }) @@ -420,53 +420,53 @@ describe('batchWriteItem', function() { }) - describe('functionality', function() { + describe('functionality', function () { - it('should write a single item to each table', function(done) { - var item = {a: {S: helpers.randomString()}, c: {S: 'c'}}, - item2 = {a: {S: helpers.randomString()}, b: {S: helpers.randomString()}, c: {S: 'c'}}, - batchReq = {RequestItems: {}} - batchReq.RequestItems[helpers.testHashTable] = [{PutRequest: {Item: item}}] - batchReq.RequestItems[helpers.testRangeTable] = [{PutRequest: {Item: item2}}] - request(opts(batchReq), function(err, res) { + it('should write a single item to each table', function (done) { + var item = { a: { S: helpers.randomString() }, c: { S: 'c' } }, + item2 = { a: { S: helpers.randomString() }, b: { S: helpers.randomString() }, c: { S: 'c' } }, + batchReq = { RequestItems: {} } + batchReq.RequestItems[helpers.testHashTable] = [ { PutRequest: { Item: item } } ] + batchReq.RequestItems[helpers.testRangeTable] = [ { PutRequest: { Item: item2 } } ] + request(opts(batchReq), function (err, res) { if (err) return done(err) res.statusCode.should.equal(200) - res.body.should.eql({UnprocessedItems: {}}) - request(helpers.opts('GetItem', {TableName: helpers.testHashTable, Key: {a: item.a}, ConsistentRead: true}), function(err, res) { + res.body.should.eql({ UnprocessedItems: {} }) + request(helpers.opts('GetItem', { TableName: helpers.testHashTable, Key: { a: item.a }, ConsistentRead: true }), function (err, res) { if (err) return done(err) res.statusCode.should.equal(200) - res.body.should.eql({Item: item}) - request(helpers.opts('GetItem', {TableName: helpers.testRangeTable, Key: {a: item2.a, b: item2.b}, ConsistentRead: true}), function(err, res) { + res.body.should.eql({ Item: item }) + request(helpers.opts('GetItem', { TableName: helpers.testRangeTable, Key: { a: item2.a, b: item2.b }, ConsistentRead: true }), function (err, res) { if (err) return done(err) res.statusCode.should.equal(200) - res.body.should.eql({Item: item2}) + res.body.should.eql({ Item: item2 }) done() }) }) }) }) - it('should delete an item from each table', function(done) { - var item = {a: {S: helpers.randomString()}, c: {S: 'c'}}, - item2 = {a: {S: helpers.randomString()}, b: {S: helpers.randomString()}, c: {S: 'c'}}, - batchReq = {RequestItems: {}} - batchReq.RequestItems[helpers.testHashTable] = [{DeleteRequest: {Key: {a: item.a}}}] - batchReq.RequestItems[helpers.testRangeTable] = [{DeleteRequest: {Key: {a: item2.a, b: item2.b}}}] - request(helpers.opts('PutItem', {TableName: helpers.testHashTable, Item: item}), function(err, res) { + it('should delete an item from each table', function (done) { + var item = { a: { S: helpers.randomString() }, c: { S: 'c' } }, + item2 = { a: { S: helpers.randomString() }, b: { S: helpers.randomString() }, c: { S: 'c' } }, + batchReq = { RequestItems: {} } + batchReq.RequestItems[helpers.testHashTable] = [ { DeleteRequest: { Key: { a: item.a } } } ] + batchReq.RequestItems[helpers.testRangeTable] = [ { DeleteRequest: { Key: { a: item2.a, b: item2.b } } } ] + request(helpers.opts('PutItem', { TableName: helpers.testHashTable, Item: item }), function (err, res) { if (err) return done(err) res.statusCode.should.equal(200) - request(helpers.opts('PutItem', {TableName: helpers.testRangeTable, Item: item2}), function(err, res) { + request(helpers.opts('PutItem', { TableName: helpers.testRangeTable, Item: item2 }), function (err, res) { if (err) return done(err) res.statusCode.should.equal(200) - request(opts(batchReq), function(err, res) { + request(opts(batchReq), function (err, res) { if (err) return done(err) res.statusCode.should.equal(200) - res.body.should.eql({UnprocessedItems: {}}) - request(helpers.opts('GetItem', {TableName: helpers.testHashTable, Key: {a: item.a}, ConsistentRead: true}), function(err, res) { + res.body.should.eql({ UnprocessedItems: {} }) + request(helpers.opts('GetItem', { TableName: helpers.testHashTable, Key: { a: item.a }, ConsistentRead: true }), function (err, res) { if (err) return done(err) res.statusCode.should.equal(200) res.body.should.eql({}) - request(helpers.opts('GetItem', {TableName: helpers.testRangeTable, Key: {a: item2.a, b: item2.b}, ConsistentRead: true}), function(err, res) { + request(helpers.opts('GetItem', { TableName: helpers.testRangeTable, Key: { a: item2.a, b: item2.b }, ConsistentRead: true }), function (err, res) { if (err) return done(err) res.statusCode.should.equal(200) res.body.should.eql({}) @@ -478,26 +478,26 @@ describe('batchWriteItem', function() { }) }) - it('should deal with puts and deletes together', function(done) { - var item = {a: {S: helpers.randomString()}, c: {S: 'c'}}, - item2 = {a: {S: helpers.randomString()}, c: {S: 'c'}}, - batchReq = {RequestItems: {}} - request(helpers.opts('PutItem', {TableName: helpers.testHashTable, Item: item}), function(err, res) { + it('should deal with puts and deletes together', function (done) { + var item = { a: { S: helpers.randomString() }, c: { S: 'c' } }, + item2 = { a: { S: helpers.randomString() }, c: { S: 'c' } }, + batchReq = { RequestItems: {} } + request(helpers.opts('PutItem', { TableName: helpers.testHashTable, Item: item }), function (err, res) { if (err) return done(err) res.statusCode.should.equal(200) - batchReq.RequestItems[helpers.testHashTable] = [{DeleteRequest: {Key: {a: item.a}}}, {PutRequest: {Item: item2}}] - request(opts(batchReq), function(err, res) { + batchReq.RequestItems[helpers.testHashTable] = [ { DeleteRequest: { Key: { a: item.a } } }, { PutRequest: { Item: item2 } } ] + request(opts(batchReq), function (err, res) { if (err) return done(err) - res.body.should.eql({UnprocessedItems: {}}) - batchReq.RequestItems[helpers.testHashTable] = [{PutRequest: {Item: item}}, {DeleteRequest: {Key: {a: item2.a}}}] - request(opts(batchReq), function(err, res) { + res.body.should.eql({ UnprocessedItems: {} }) + batchReq.RequestItems[helpers.testHashTable] = [ { PutRequest: { Item: item } }, { DeleteRequest: { Key: { a: item2.a } } } ] + request(opts(batchReq), function (err, res) { if (err) return done(err) - res.body.should.eql({UnprocessedItems: {}}) - request(helpers.opts('GetItem', {TableName: helpers.testHashTable, Key: {a: item.a}, ConsistentRead: true}), function(err, res) { + res.body.should.eql({ UnprocessedItems: {} }) + request(helpers.opts('GetItem', { TableName: helpers.testHashTable, Key: { a: item.a }, ConsistentRead: true }), function (err, res) { if (err) return done(err) res.statusCode.should.equal(200) - res.body.should.eql({Item: item}) - request(helpers.opts('GetItem', {TableName: helpers.testHashTable, Key: {a: item2.a}, ConsistentRead: true}), function(err, res) { + res.body.should.eql({ Item: item }) + request(helpers.opts('GetItem', { TableName: helpers.testHashTable, Key: { a: item2.a }, ConsistentRead: true }), function (err, res) { if (err) return done(err) res.statusCode.should.equal(200) res.body.should.eql({}) @@ -509,38 +509,38 @@ describe('batchWriteItem', function() { }) }) - it('should return ConsumedCapacity from each specified table when putting and deleting small item', function(done) { + it('should return ConsumedCapacity from each specified table when putting and deleting small item', function (done) { var a = helpers.randomString(), b = new Array(1010 - a.length).join('b'), - item = {a: {S: a}, b: {S: b}, c: {N: '12.3456'}, d: {B: 'AQI='}, e: {BS: ['AQI=', 'Ag==', 'AQ==']}}, - key2 = helpers.randomString(), key3 = helpers.randomNumber(), - batchReq = {RequestItems: {}, ReturnConsumedCapacity: 'TOTAL'} - batchReq.RequestItems[helpers.testHashTable] = [{PutRequest: {Item: item}}, {PutRequest: {Item: {a: {S: key2}}}}] - batchReq.RequestItems[helpers.testHashNTable] = [{PutRequest: {Item: {a: {N: key3}}}}] - request(opts(batchReq), function(err, res) { + item = { a: { S: a }, b: { S: b }, c: { N: '12.3456' }, d: { B: 'AQI=' }, e: { BS: [ 'AQI=', 'Ag==', 'AQ==' ] } }, + key2 = helpers.randomString(), key3 = helpers.randomNumber(), + batchReq = { RequestItems: {}, ReturnConsumedCapacity: 'TOTAL' } + batchReq.RequestItems[helpers.testHashTable] = [ { PutRequest: { Item: item } }, { PutRequest: { Item: { a: { S: key2 } } } } ] + batchReq.RequestItems[helpers.testHashNTable] = [ { PutRequest: { Item: { a: { N: key3 } } } } ] + request(opts(batchReq), function (err, res) { if (err) return done(err) res.statusCode.should.equal(200) - res.body.ConsumedCapacity.should.containEql({CapacityUnits: 2, TableName: helpers.testHashTable}) - res.body.ConsumedCapacity.should.containEql({CapacityUnits: 1, TableName: helpers.testHashNTable}) + res.body.ConsumedCapacity.should.containEql({ CapacityUnits: 2, TableName: helpers.testHashTable }) + res.body.ConsumedCapacity.should.containEql({ CapacityUnits: 1, TableName: helpers.testHashNTable }) batchReq.ReturnConsumedCapacity = 'INDEXES' - request(opts(batchReq), function(err, res) { + request(opts(batchReq), function (err, res) { if (err) return done(err) res.statusCode.should.equal(200) - res.body.ConsumedCapacity.should.containEql({CapacityUnits: 2, Table: {CapacityUnits: 2}, TableName: helpers.testHashTable}) - res.body.ConsumedCapacity.should.containEql({CapacityUnits: 1, Table: {CapacityUnits: 1}, TableName: helpers.testHashNTable}) + res.body.ConsumedCapacity.should.containEql({ CapacityUnits: 2, Table: { CapacityUnits: 2 }, TableName: helpers.testHashTable }) + res.body.ConsumedCapacity.should.containEql({ CapacityUnits: 1, Table: { CapacityUnits: 1 }, TableName: helpers.testHashNTable }) batchReq.ReturnConsumedCapacity = 'TOTAL' - batchReq.RequestItems[helpers.testHashTable] = [{DeleteRequest: {Key: {a: item.a}}}, {DeleteRequest: {Key: {a: {S: key2}}}}] - batchReq.RequestItems[helpers.testHashNTable] = [{DeleteRequest: {Key: {a: {N: key3}}}}] - request(opts(batchReq), function(err, res) { + batchReq.RequestItems[helpers.testHashTable] = [ { DeleteRequest: { Key: { a: item.a } } }, { DeleteRequest: { Key: { a: { S: key2 } } } } ] + batchReq.RequestItems[helpers.testHashNTable] = [ { DeleteRequest: { Key: { a: { N: key3 } } } } ] + request(opts(batchReq), function (err, res) { if (err) return done(err) res.statusCode.should.equal(200) - res.body.ConsumedCapacity.should.containEql({CapacityUnits: 2, TableName: helpers.testHashTable}) - res.body.ConsumedCapacity.should.containEql({CapacityUnits: 1, TableName: helpers.testHashNTable}) + res.body.ConsumedCapacity.should.containEql({ CapacityUnits: 2, TableName: helpers.testHashTable }) + res.body.ConsumedCapacity.should.containEql({ CapacityUnits: 1, TableName: helpers.testHashNTable }) batchReq.ReturnConsumedCapacity = 'INDEXES' - request(opts(batchReq), function(err, res) { + request(opts(batchReq), function (err, res) { if (err) return done(err) res.statusCode.should.equal(200) - res.body.ConsumedCapacity.should.containEql({CapacityUnits: 2, Table: {CapacityUnits: 2}, TableName: helpers.testHashTable}) - res.body.ConsumedCapacity.should.containEql({CapacityUnits: 1, Table: {CapacityUnits: 1}, TableName: helpers.testHashNTable}) + res.body.ConsumedCapacity.should.containEql({ CapacityUnits: 2, Table: { CapacityUnits: 2 }, TableName: helpers.testHashTable }) + res.body.ConsumedCapacity.should.containEql({ CapacityUnits: 1, Table: { CapacityUnits: 1 }, TableName: helpers.testHashNTable }) done() }) }) @@ -548,38 +548,38 @@ describe('batchWriteItem', function() { }) }) - it('should return ConsumedCapacity from each specified table when putting and deleting larger item', function(done) { + it('should return ConsumedCapacity from each specified table when putting and deleting larger item', function (done) { var a = helpers.randomString(), b = new Array(1012 - a.length).join('b'), - item = {a: {S: a}, b: {S: b}, c: {N: '12.3456'}, d: {B: 'AQI='}, e: {BS: ['AQI=', 'Ag==']}}, - key2 = helpers.randomString(), key3 = helpers.randomNumber(), - batchReq = {RequestItems: {}, ReturnConsumedCapacity: 'TOTAL'} - batchReq.RequestItems[helpers.testHashTable] = [{PutRequest: {Item: item}}, {PutRequest: {Item: {a: {S: key2}}}}] - batchReq.RequestItems[helpers.testHashNTable] = [{PutRequest: {Item: {a: {N: key3}}}}] - request(opts(batchReq), function(err, res) { + item = { a: { S: a }, b: { S: b }, c: { N: '12.3456' }, d: { B: 'AQI=' }, e: { BS: [ 'AQI=', 'Ag==' ] } }, + key2 = helpers.randomString(), key3 = helpers.randomNumber(), + batchReq = { RequestItems: {}, ReturnConsumedCapacity: 'TOTAL' } + batchReq.RequestItems[helpers.testHashTable] = [ { PutRequest: { Item: item } }, { PutRequest: { Item: { a: { S: key2 } } } } ] + batchReq.RequestItems[helpers.testHashNTable] = [ { PutRequest: { Item: { a: { N: key3 } } } } ] + request(opts(batchReq), function (err, res) { if (err) return done(err) res.statusCode.should.equal(200) - res.body.ConsumedCapacity.should.containEql({CapacityUnits: 3, TableName: helpers.testHashTable}) - res.body.ConsumedCapacity.should.containEql({CapacityUnits: 1, TableName: helpers.testHashNTable}) + res.body.ConsumedCapacity.should.containEql({ CapacityUnits: 3, TableName: helpers.testHashTable }) + res.body.ConsumedCapacity.should.containEql({ CapacityUnits: 1, TableName: helpers.testHashNTable }) batchReq.ReturnConsumedCapacity = 'INDEXES' - request(opts(batchReq), function(err, res) { + request(opts(batchReq), function (err, res) { if (err) return done(err) res.statusCode.should.equal(200) - res.body.ConsumedCapacity.should.containEql({CapacityUnits: 3, Table: {CapacityUnits: 3}, TableName: helpers.testHashTable}) - res.body.ConsumedCapacity.should.containEql({CapacityUnits: 1, Table: {CapacityUnits: 1}, TableName: helpers.testHashNTable}) + res.body.ConsumedCapacity.should.containEql({ CapacityUnits: 3, Table: { CapacityUnits: 3 }, TableName: helpers.testHashTable }) + res.body.ConsumedCapacity.should.containEql({ CapacityUnits: 1, Table: { CapacityUnits: 1 }, TableName: helpers.testHashNTable }) batchReq.ReturnConsumedCapacity = 'TOTAL' - batchReq.RequestItems[helpers.testHashTable] = [{DeleteRequest: {Key: {a: item.a}}}, {DeleteRequest: {Key: {a: {S: key2}}}}] - batchReq.RequestItems[helpers.testHashNTable] = [{DeleteRequest: {Key: {a: {N: key3}}}}] - request(opts(batchReq), function(err, res) { + batchReq.RequestItems[helpers.testHashTable] = [ { DeleteRequest: { Key: { a: item.a } } }, { DeleteRequest: { Key: { a: { S: key2 } } } } ] + batchReq.RequestItems[helpers.testHashNTable] = [ { DeleteRequest: { Key: { a: { N: key3 } } } } ] + request(opts(batchReq), function (err, res) { if (err) return done(err) res.statusCode.should.equal(200) - res.body.ConsumedCapacity.should.containEql({CapacityUnits: 3, TableName: helpers.testHashTable}) - res.body.ConsumedCapacity.should.containEql({CapacityUnits: 1, TableName: helpers.testHashNTable}) + res.body.ConsumedCapacity.should.containEql({ CapacityUnits: 3, TableName: helpers.testHashTable }) + res.body.ConsumedCapacity.should.containEql({ CapacityUnits: 1, TableName: helpers.testHashNTable }) batchReq.ReturnConsumedCapacity = 'INDEXES' - request(opts(batchReq), function(err, res) { + request(opts(batchReq), function (err, res) { if (err) return done(err) res.statusCode.should.equal(200) - res.body.ConsumedCapacity.should.containEql({CapacityUnits: 2, Table: {CapacityUnits: 2}, TableName: helpers.testHashTable}) - res.body.ConsumedCapacity.should.containEql({CapacityUnits: 1, Table: {CapacityUnits: 1}, TableName: helpers.testHashNTable}) + res.body.ConsumedCapacity.should.containEql({ CapacityUnits: 2, Table: { CapacityUnits: 2 }, TableName: helpers.testHashTable }) + res.body.ConsumedCapacity.should.containEql({ CapacityUnits: 1, Table: { CapacityUnits: 1 }, TableName: helpers.testHashNTable }) done() }) }) @@ -592,38 +592,38 @@ describe('batchWriteItem', function() { // Max size = 1638400 = 25 * 65536 = 1600 capacity units // Will process all if capacity >= 751. Below this value, the algorithm is something like: // min(capacity * 300, min(capacity, 336) + 677) + random(mean = 80, stddev = 32) - it.skip('should return UnprocessedItems if over limit', function(done) { + it.skip('should return UnprocessedItems if over limit', function (done) { this.timeout(1e8) var CAPACITY = 3 async.times(10, createAndWrite, done) - function createAndWrite(i, cb) { + function createAndWrite (i, cb) { var name = helpers.randomName(), table = { TableName: name, - AttributeDefinitions: [{AttributeName: 'a', AttributeType: 'S'}], - KeySchema: [{KeyType: 'HASH', AttributeName: 'a'}], - ProvisionedThroughput: {ReadCapacityUnits: CAPACITY, WriteCapacityUnits: CAPACITY}, + AttributeDefinitions: [ { AttributeName: 'a', AttributeType: 'S' } ], + KeySchema: [ { KeyType: 'HASH', AttributeName: 'a' } ], + ProvisionedThroughput: { ReadCapacityUnits: CAPACITY, WriteCapacityUnits: CAPACITY }, } - helpers.createAndWait(table, function(err) { + helpers.createAndWait(table, function (err) { if (err) return cb(err) - async.timesSeries(50, function(n, cb) { batchWrite(name, n, cb) }, cb) + async.timesSeries(50, function (n, cb) { batchWrite(name, n, cb) }, cb) }) } - function batchWrite(name, n, cb) { - var i, item, items = [], totalSize = 0, batchReq = {RequestItems: {}, ReturnConsumedCapacity: 'TOTAL'} + function batchWrite (name, n, cb) { + var i, item, items = [], totalSize = 0, batchReq = { RequestItems: {}, ReturnConsumedCapacity: 'TOTAL' } for (i = 0; i < 25; i++) { - item = {a: {S: ('0' + i).slice(-2)}, - b: {S: new Array(Math.floor((64 - (16 * Math.random())) * 1024) - 3).join('b')}} + item = { a: { S: ('0' + i).slice(-2) }, + b: { S: new Array(Math.floor((64 - (16 * Math.random())) * 1024) - 3).join('b') } } totalSize += db.itemSize(item) - items.push({PutRequest: {Item: item}}) + items.push({ PutRequest: { Item: item } }) } batchReq.RequestItems[name] = items - request(opts(batchReq), function(err, res) { + request(opts(batchReq), function (err, res) { // if (err) return cb(err) if (err) { // console.log('Caught err: ' + err) @@ -632,13 +632,14 @@ describe('batchWriteItem', function() { if (/ProvisionedThroughputExceededException$/.test(res.body.__type)) { // console.log('ProvisionedThroughputExceededException$') return cb() - } else if (res.body.__type) { + } + else if (res.body.__type) { // return cb(new Error(JSON.stringify(res.body))) return cb() } res.statusCode.should.equal(200) // eslint-disable-next-line no-console - console.log([CAPACITY, res.body.ConsumedCapacity[0].CapacityUnits, totalSize].join()) + console.log([ CAPACITY, res.body.ConsumedCapacity[0].CapacityUnits, totalSize ].join()) setTimeout(cb, res.body.ConsumedCapacity[0].CapacityUnits * 1000 / CAPACITY) }) } diff --git a/test/bench.js b/test/bench.js index 93e15f8..65a5ce7 100644 --- a/test/bench.js +++ b/test/bench.js @@ -1,16 +1,16 @@ var helpers = require('./helpers') -describe.skip('benchmarks', function() { +describe.skip('benchmarks', function () { - it('should batch write', function(done) { + it('should batch write', function (done) { this.timeout(1e6) var numItems = 1e6, numSegments = 4, start = Date.now(), i, items = new Array(numItems) for (i = 0; i < numItems; i++) - items[i] = {a: {S: String(i)}} + items[i] = { a: { S: String(i) } } - helpers.batchBulkPut(helpers.testHashTable, items, numSegments, function(err) { + helpers.batchBulkPut(helpers.testHashTable, items, numSegments, function (err) { if (err) return done(err) // eslint-disable-next-line no-console @@ -20,15 +20,15 @@ describe.skip('benchmarks', function() { }) }) - it('should scan', function(done) { + it('should scan', function (done) { this.timeout(1e6) scan() - function scan(key) { + function scan (key) { var start = Date.now() - helpers.request(helpers.opts('Scan', {TableName: helpers.testHashTable, Limit: 1000, ExclusiveStartKey: key}), function(err, res) { + helpers.request(helpers.opts('Scan', { TableName: helpers.testHashTable, Limit: 1000, ExclusiveStartKey: key }), function (err, res) { if (err) return done(err) res.statusCode.should.equal(200) diff --git a/test/connection.js b/test/connection.js index f47b4cd..77de3d0 100644 --- a/test/connection.js +++ b/test/connection.js @@ -1,16 +1,16 @@ var https = require('https'), - once = require('once'), - dynalite = require('..'), - helpers = require('./helpers') + once = require('once'), + dynalite = require('..'), + helpers = require('./helpers') var request = helpers.request -describe('dynalite connections', function() { +describe('dynalite connections', function () { - describe('basic', function() { + describe('basic', function () { - function assert404(done) { - return function(err, res) { + function assert404 (done) { + return function (err, res) { // Sometimes DynamoDB returns weird/bad HTTP responses if (err && err.code == 'HPE_INVALID_CONSTANT') return done() if (err) return done(err) @@ -19,7 +19,8 @@ describe('dynalite connections', function() { res.body.should.equal('\n') res.headers['x-amz-crc32'].should.equal('3552371480') res.headers['content-length'].should.equal('29') - } catch (e) { + } + catch (e) { // Sometimes it's an HTML page instead of the above res.body.should.equal( '', done) }) - it('should return SerializationException when ProvisionedThroughput.WriteCapacityUnits is not a long', function(done) { + it('should return SerializationException when ProvisionedThroughput.WriteCapacityUnits is not a long', function (done) { assertType('ProvisionedThroughput.WriteCapacityUnits', 'Long', done) }) - it('should return SerializationException when ProvisionedThroughput.ReadCapacityUnits is not a long', function(done) { + it('should return SerializationException when ProvisionedThroughput.ReadCapacityUnits is not a long', function (done) { assertType('ProvisionedThroughput.ReadCapacityUnits', 'Long', done) }) - it('should return SerializationException when KeySchema.0 is not a struct', function(done) { + it('should return SerializationException when KeySchema.0 is not a struct', function (done) { assertType('KeySchema.0', 'ValueStruct', done) }) - it('should return SerializationException when KeySchema.0.KeyType is not a string', function(done) { + it('should return SerializationException when KeySchema.0.KeyType is not a string', function (done) { assertType('KeySchema.0.KeyType', 'String', done) }) - it('should return SerializationException when KeySchema.0.AttributeName is not a string', function(done) { + it('should return SerializationException when KeySchema.0.AttributeName is not a string', function (done) { assertType('KeySchema.0.AttributeName', 'String', done) }) - it('should return SerializationException when AttributeDefinitions.0 is not a struct', function(done) { + it('should return SerializationException when AttributeDefinitions.0 is not a struct', function (done) { assertType('AttributeDefinitions.0', 'ValueStruct', done) }) - it('should return SerializationException when AttributeDefinitions.0.AttributeName is not a string', function(done) { + it('should return SerializationException when AttributeDefinitions.0.AttributeName is not a string', function (done) { assertType('AttributeDefinitions.0.AttributeName', 'String', done) }) - it('should return SerializationException when AttributeDefinitions.0.AttributeType is not a string', function(done) { + it('should return SerializationException when AttributeDefinitions.0.AttributeType is not a string', function (done) { assertType('AttributeDefinitions.0.AttributeType', 'String', done) }) - it('should return SerializationException when LocalSecondaryIndexes.0 is not a struct', function(done) { + it('should return SerializationException when LocalSecondaryIndexes.0 is not a struct', function (done) { assertType('LocalSecondaryIndexes.0', 'ValueStruct', done) }) - it('should return SerializationException when LocalSecondaryIndexes.0.IndexName is not a string', function(done) { + it('should return SerializationException when LocalSecondaryIndexes.0.IndexName is not a string', function (done) { assertType('LocalSecondaryIndexes.0.IndexName', 'String', done) }) - it('should return SerializationException when LocalSecondaryIndexes.0.KeySchema is not a list', function(done) { + it('should return SerializationException when LocalSecondaryIndexes.0.KeySchema is not a list', function (done) { assertType('LocalSecondaryIndexes.0.KeySchema', 'List', done) }) - it('should return SerializationException when LocalSecondaryIndexes.0.Projection is not a struct', function(done) { + it('should return SerializationException when LocalSecondaryIndexes.0.Projection is not a struct', function (done) { assertType('LocalSecondaryIndexes.0.Projection', 'FieldStruct', done) }) - it('should return SerializationException when LocalSecondaryIndexes.0.KeySchema.0 is not a struct', function(done) { + it('should return SerializationException when LocalSecondaryIndexes.0.KeySchema.0 is not a struct', function (done) { assertType('LocalSecondaryIndexes.0.KeySchema.0', 'ValueStruct', done) }) - it('should return SerializationException when LocalSecondaryIndexes.0.KeySchema.0.AttributeName is not a string', function(done) { + it('should return SerializationException when LocalSecondaryIndexes.0.KeySchema.0.AttributeName is not a string', function (done) { assertType('LocalSecondaryIndexes.0.KeySchema.0.AttributeName', 'String', done) }) - it('should return SerializationException when LocalSecondaryIndexes.0.KeySchema.0.KeyType is not a string', function(done) { + it('should return SerializationException when LocalSecondaryIndexes.0.KeySchema.0.KeyType is not a string', function (done) { assertType('LocalSecondaryIndexes.0.KeySchema.0.KeyType', 'String', done) }) - it('should return SerializationException when LocalSecondaryIndexes.0.Projection.NonKeyAttributes is not a list', function(done) { + it('should return SerializationException when LocalSecondaryIndexes.0.Projection.NonKeyAttributes is not a list', function (done) { assertType('LocalSecondaryIndexes.0.Projection.NonKeyAttributes', 'List', done) }) - it('should return SerializationException when LocalSecondaryIndexes.0.Projection.ProjectionType is not a string', function(done) { + it('should return SerializationException when LocalSecondaryIndexes.0.Projection.ProjectionType is not a string', function (done) { assertType('LocalSecondaryIndexes.0.Projection.ProjectionType', 'String', done) }) - it('should return SerializationException when LocalSecondaryIndexes.0.Projection.NonKeyAttributes.0 is not a string', function(done) { + it('should return SerializationException when LocalSecondaryIndexes.0.Projection.NonKeyAttributes.0 is not a string', function (done) { assertType('LocalSecondaryIndexes.0.Projection.NonKeyAttributes.0', 'String', done) }) - it('should return SerializationException when GlobalSecondaryIndexes.0 is not a struct', function(done) { + it('should return SerializationException when GlobalSecondaryIndexes.0 is not a struct', function (done) { assertType('GlobalSecondaryIndexes.0', 'ValueStruct', done) }) - it('should return SerializationException when GlobalSecondaryIndexes.0.IndexName is not a string', function(done) { + it('should return SerializationException when GlobalSecondaryIndexes.0.IndexName is not a string', function (done) { assertType('GlobalSecondaryIndexes.0.IndexName', 'String', done) }) - it('should return SerializationException when GlobalSecondaryIndexes.0.KeySchema is not a list', function(done) { + it('should return SerializationException when GlobalSecondaryIndexes.0.KeySchema is not a list', function (done) { assertType('GlobalSecondaryIndexes.0.KeySchema', 'List', done) }) - it('should return SerializationException when GlobalSecondaryIndexes.0.Projection is not a struct', function(done) { + it('should return SerializationException when GlobalSecondaryIndexes.0.Projection is not a struct', function (done) { assertType('GlobalSecondaryIndexes.0.Projection', 'FieldStruct', done) }) - it('should return SerializationException when GlobalSecondaryIndexes.0.KeySchema.0 is not a struct', function(done) { + it('should return SerializationException when GlobalSecondaryIndexes.0.KeySchema.0 is not a struct', function (done) { assertType('GlobalSecondaryIndexes.0.KeySchema.0', 'ValueStruct', done) }) - it('should return SerializationException when GlobalSecondaryIndexes.0.KeySchema.0.AttributeName is not a string', function(done) { + it('should return SerializationException when GlobalSecondaryIndexes.0.KeySchema.0.AttributeName is not a string', function (done) { assertType('GlobalSecondaryIndexes.0.KeySchema.0.AttributeName', 'String', done) }) - it('should return SerializationException when GlobalSecondaryIndexes.0.KeySchema.0.KeyType is not a string', function(done) { + it('should return SerializationException when GlobalSecondaryIndexes.0.KeySchema.0.KeyType is not a string', function (done) { assertType('GlobalSecondaryIndexes.0.KeySchema.0.KeyType', 'String', done) }) - it('should return SerializationException when GlobalSecondaryIndexes.0.Projection.NonKeyAttributes is not a list', function(done) { + it('should return SerializationException when GlobalSecondaryIndexes.0.Projection.NonKeyAttributes is not a list', function (done) { assertType('GlobalSecondaryIndexes.0.Projection.NonKeyAttributes', 'List', done) }) - it('should return SerializationException when GlobalSecondaryIndexes.0.Projection.ProjectionType is not a string', function(done) { + it('should return SerializationException when GlobalSecondaryIndexes.0.Projection.ProjectionType is not a string', function (done) { assertType('GlobalSecondaryIndexes.0.Projection.ProjectionType', 'String', done) }) - it('should return SerializationException when GlobalSecondaryIndexes.0.Projection.NonKeyAttributes.0 is not a string', function(done) { + it('should return SerializationException when GlobalSecondaryIndexes.0.Projection.NonKeyAttributes.0 is not a string', function (done) { assertType('GlobalSecondaryIndexes.0.Projection.NonKeyAttributes.0', 'String', done) }) - it('should return SerializationException when GlobalSecondaryIndexes.0.ProvisionedThroughput is not a struct', function(done) { + it('should return SerializationException when GlobalSecondaryIndexes.0.ProvisionedThroughput is not a struct', function (done) { assertType('GlobalSecondaryIndexes.0.ProvisionedThroughput', 'FieldStruct', done) }) - it('should return SerializationException when GlobalSecondaryIndexes.0.ProvisionedThroughput.WriteCapacityUnits is not a long', function(done) { + it('should return SerializationException when GlobalSecondaryIndexes.0.ProvisionedThroughput.WriteCapacityUnits is not a long', function (done) { assertType('GlobalSecondaryIndexes.0.ProvisionedThroughput.WriteCapacityUnits', 'Long', done) }) - it('should return SerializationException when GlobalSecondaryIndexes.0.ProvisionedThroughput.ReadCapacityUnits is not a long', function(done) { + it('should return SerializationException when GlobalSecondaryIndexes.0.ProvisionedThroughput.ReadCapacityUnits is not a long', function (done) { assertType('GlobalSecondaryIndexes.0.ProvisionedThroughput.ReadCapacityUnits', 'Long', done) }) - it('should return SerializationException when BillingMode is not a string', function(done) { + it('should return SerializationException when BillingMode is not a string', function (done) { assertType('BillingMode', 'String', done) }) }) - describe('validations', function() { + describe('validations', function () { - it('should return ValidationException for no TableName', function(done) { + it('should return ValidationException for no TableName', function (done) { assertValidation({}, 'The parameter \'TableName\' is required but was not present in the request', done) }) - it('should return ValidationException for empty TableName', function(done) { - assertValidation({TableName: ''}, + it('should return ValidationException for empty TableName', function (done) { + assertValidation({ TableName: '' }, 'TableName must be at least 3 characters long and at most 255 characters long', done) }) - it('should return ValidationException for short TableName', function(done) { - assertValidation({TableName: 'a;'}, + it('should return ValidationException for short TableName', function (done) { + assertValidation({ TableName: 'a;' }, 'TableName must be at least 3 characters long and at most 255 characters long', done) }) - it('should return ValidationException for long TableName', function(done) { - assertValidation({TableName: new Array(256 + 1).join('a')}, + it('should return ValidationException for long TableName', function (done) { + assertValidation({ TableName: new Array(256 + 1).join('a') }, 'TableName must be at least 3 characters long and at most 255 characters long', done) }) - it('should return ValidationException for null attributes', function(done) { - assertValidation({TableName: 'abc;'}, [ + it('should return ValidationException for null attributes', function (done) { + assertValidation({ TableName: 'abc;' }, [ 'Value null at \'attributeDefinitions\' failed to satisfy constraint: ' + 'Member must not be null', 'Value \'abc;\' at \'tableName\' failed to satisfy constraint: ' + @@ -199,15 +199,15 @@ describe('createTable', function() { ], done) }) - it('should return ValidationException for empty AttributeDefinitions', function(done) { - assertValidation({TableName: 'abc', AttributeDefinitions: []}, [ + it('should return ValidationException for empty AttributeDefinitions', function (done) { + assertValidation({ TableName: 'abc', AttributeDefinitions: [] }, [ 'Value null at \'keySchema\' failed to satisfy constraint: ' + 'Member must not be null', ], done) }) - it('should return ValidationException for empty ProvisionedThroughput', function(done) { - assertValidation({TableName: 'abc', AttributeDefinitions: [], ProvisionedThroughput: {}, BillingMode: 'PAY_PER_REQUEST'}, [ + it('should return ValidationException for empty ProvisionedThroughput', function (done) { + assertValidation({ TableName: 'abc', AttributeDefinitions: [], ProvisionedThroughput: {}, BillingMode: 'PAY_PER_REQUEST' }, [ 'Value null at \'provisionedThroughput.writeCapacityUnits\' failed to satisfy constraint: ' + 'Member must not be null', 'Value null at \'provisionedThroughput.readCapacityUnits\' failed to satisfy constraint: ' + @@ -217,939 +217,939 @@ describe('createTable', function() { ], done) }) - it('should return ValidationException for low ProvisionedThroughput.WriteCapacityUnits', function(done) { - assertValidation({TableName: 'abc', AttributeDefinitions: [], KeySchema: [], - ProvisionedThroughput: {ReadCapacityUnits: -1, WriteCapacityUnits: -1}, BillingMode: 'A'}, [ - 'Value \'A\' at \'billingMode\' failed to satisfy constraint: ' + + it('should return ValidationException for low ProvisionedThroughput.WriteCapacityUnits', function (done) { + assertValidation({ TableName: 'abc', AttributeDefinitions: [], KeySchema: [], + ProvisionedThroughput: { ReadCapacityUnits: -1, WriteCapacityUnits: -1 }, BillingMode: 'A' }, [ + 'Value \'A\' at \'billingMode\' failed to satisfy constraint: ' + 'Member must satisfy enum value set: [PROVISIONED, PAY_PER_REQUEST]', - 'Value \'-1\' at \'provisionedThroughput.writeCapacityUnits\' failed to satisfy constraint: ' + + 'Value \'-1\' at \'provisionedThroughput.writeCapacityUnits\' failed to satisfy constraint: ' + 'Member must have value greater than or equal to 1', - 'Value \'-1\' at \'provisionedThroughput.readCapacityUnits\' failed to satisfy constraint: ' + + 'Value \'-1\' at \'provisionedThroughput.readCapacityUnits\' failed to satisfy constraint: ' + 'Member must have value greater than or equal to 1', - 'Value \'[]\' at \'keySchema\' failed to satisfy constraint: ' + + 'Value \'[]\' at \'keySchema\' failed to satisfy constraint: ' + 'Member must have length greater than or equal to 1', - ], done) + ], done) }) - it('should return ValidationException for key element names', function(done) { - assertValidation({TableName: 'abc', AttributeDefinitions: [], - KeySchema: [{KeyType: 'HASH'}, {AttributeName: 'a'}, {KeyType: 'Woop', AttributeName: 'a'}], - ProvisionedThroughput: {ReadCapacityUnits: 1000000000001, WriteCapacityUnits: 1000000000001}}, [ - new RegExp('Value \'\\[.+\\]\' at \'keySchema\' failed to satisfy constraint: ' + + it('should return ValidationException for key element names', function (done) { + assertValidation({ TableName: 'abc', AttributeDefinitions: [], + KeySchema: [ { KeyType: 'HASH' }, { AttributeName: 'a' }, { KeyType: 'Woop', AttributeName: 'a' } ], + ProvisionedThroughput: { ReadCapacityUnits: 1000000000001, WriteCapacityUnits: 1000000000001 } }, [ + new RegExp('Value \'\\[.+\\]\' at \'keySchema\' failed to satisfy constraint: ' + 'Member must have length less than or equal to 2'), - 'Value null at \'keySchema.1.member.attributeName\' failed to satisfy constraint: ' + + 'Value null at \'keySchema.1.member.attributeName\' failed to satisfy constraint: ' + 'Member must not be null', - 'Value null at \'keySchema.2.member.keyType\' failed to satisfy constraint: ' + + 'Value null at \'keySchema.2.member.keyType\' failed to satisfy constraint: ' + 'Member must not be null', - 'Value \'Woop\' at \'keySchema.3.member.keyType\' failed to satisfy constraint: ' + + 'Value \'Woop\' at \'keySchema.3.member.keyType\' failed to satisfy constraint: ' + 'Member must satisfy enum value set: [HASH, RANGE]', - ], done) + ], done) }) - it('should return ValidationException for high ProvisionedThroughput.ReadCapacityUnits and neg', function(done) { - assertValidation({TableName: 'abc', AttributeDefinitions: [], KeySchema: [{KeyType: 'HASH', AttributeName: 'a'}], - ProvisionedThroughput: {ReadCapacityUnits: 1000000000001, WriteCapacityUnits: -1}}, [ - 'Value \'-1\' at \'provisionedThroughput.writeCapacityUnits\' failed to satisfy constraint: ' + + it('should return ValidationException for high ProvisionedThroughput.ReadCapacityUnits and neg', function (done) { + assertValidation({ TableName: 'abc', AttributeDefinitions: [], KeySchema: [ { KeyType: 'HASH', AttributeName: 'a' } ], + ProvisionedThroughput: { ReadCapacityUnits: 1000000000001, WriteCapacityUnits: -1 } }, [ + 'Value \'-1\' at \'provisionedThroughput.writeCapacityUnits\' failed to satisfy constraint: ' + 'Member must have value greater than or equal to 1', - ], done) + ], done) }) - it('should return ValidationException for missing ProvisionedThroughput', function(done) { - assertValidation({TableName: 'abc', AttributeDefinitions: [], KeySchema: [{KeyType: 'HASH', AttributeName: 'a'}]}, + it('should return ValidationException for missing ProvisionedThroughput', function (done) { + assertValidation({ TableName: 'abc', AttributeDefinitions: [], KeySchema: [ { KeyType: 'HASH', AttributeName: 'a' } ] }, 'One or more parameter values were invalid: ReadCapacityUnits and WriteCapacityUnits must both be specified when BillingMode is PROVISIONED', done) }) - it('should return ValidationException if ProvisionedThroughput set when BillingMode is PAY_PER_REQUEST', function(done) { - assertValidation({TableName: 'abc', AttributeDefinitions: [], - KeySchema: [{KeyType: 'HASH', AttributeName: 'a'}, {KeyType: 'HASH', AttributeName: 'a'}], - ProvisionedThroughput: {ReadCapacityUnits: 1, WriteCapacityUnits: 1}, BillingMode: 'PAY_PER_REQUEST'}, - 'One or more parameter values were invalid: ' + + it('should return ValidationException if ProvisionedThroughput set when BillingMode is PAY_PER_REQUEST', function (done) { + assertValidation({ TableName: 'abc', AttributeDefinitions: [], + KeySchema: [ { KeyType: 'HASH', AttributeName: 'a' }, { KeyType: 'HASH', AttributeName: 'a' } ], + ProvisionedThroughput: { ReadCapacityUnits: 1, WriteCapacityUnits: 1 }, BillingMode: 'PAY_PER_REQUEST' }, + 'One or more parameter values were invalid: ' + 'Neither ReadCapacityUnits nor WriteCapacityUnits can be specified when BillingMode is PAY_PER_REQUEST', done) }) - it('should return ValidationException for high ProvisionedThroughput.ReadCapacityUnits', function(done) { - assertValidation({TableName: 'abc', AttributeDefinitions: [], KeySchema: [{KeyType: 'HASH', AttributeName: 'a'}], - ProvisionedThroughput: {ReadCapacityUnits: 1000000000001, WriteCapacityUnits: 1000000000001}}, - 'Given value 1000000000001 for ReadCapacityUnits is out of bounds', done) + it('should return ValidationException for high ProvisionedThroughput.ReadCapacityUnits', function (done) { + assertValidation({ TableName: 'abc', AttributeDefinitions: [], KeySchema: [ { KeyType: 'HASH', AttributeName: 'a' } ], + ProvisionedThroughput: { ReadCapacityUnits: 1000000000001, WriteCapacityUnits: 1000000000001 } }, + 'Given value 1000000000001 for ReadCapacityUnits is out of bounds', done) }) - it('should return ValidationException for high ProvisionedThroughput.ReadCapacityUnits second', function(done) { - assertValidation({TableName: 'abc', AttributeDefinitions: [], KeySchema: [{KeyType: 'HASH', AttributeName: 'a'}], - ProvisionedThroughput: {WriteCapacityUnits: 1000000000001, ReadCapacityUnits: 1000000000001}}, - 'Given value 1000000000001 for ReadCapacityUnits is out of bounds', done) + it('should return ValidationException for high ProvisionedThroughput.ReadCapacityUnits second', function (done) { + assertValidation({ TableName: 'abc', AttributeDefinitions: [], KeySchema: [ { KeyType: 'HASH', AttributeName: 'a' } ], + ProvisionedThroughput: { WriteCapacityUnits: 1000000000001, ReadCapacityUnits: 1000000000001 } }, + 'Given value 1000000000001 for ReadCapacityUnits is out of bounds', done) }) - it('should return ValidationException for high ProvisionedThroughput.WriteCapacityUnits', function(done) { - assertValidation({TableName: 'abc', AttributeDefinitions: [], KeySchema: [{KeyType: 'HASH', AttributeName: 'a'}], - ProvisionedThroughput: {ReadCapacityUnits: 1000000000000, WriteCapacityUnits: 1000000000001}}, - 'Given value 1000000000001 for WriteCapacityUnits is out of bounds', done) + it('should return ValidationException for high ProvisionedThroughput.WriteCapacityUnits', function (done) { + assertValidation({ TableName: 'abc', AttributeDefinitions: [], KeySchema: [ { KeyType: 'HASH', AttributeName: 'a' } ], + ProvisionedThroughput: { ReadCapacityUnits: 1000000000000, WriteCapacityUnits: 1000000000001 } }, + 'Given value 1000000000001 for WriteCapacityUnits is out of bounds', done) }) - it('should return ValidationException for missing key attribute definitions', function(done) { - assertValidation({TableName: 'abc', AttributeDefinitions: [], - KeySchema: [{KeyType: 'HASH', AttributeName: 'a'}, {KeyType: 'HASH', AttributeName: 'a'}], - ProvisionedThroughput: {ReadCapacityUnits: 1, WriteCapacityUnits: 1}}, - 'Invalid KeySchema: Some index key attribute have no definition', done) + it('should return ValidationException for missing key attribute definitions', function (done) { + assertValidation({ TableName: 'abc', AttributeDefinitions: [], + KeySchema: [ { KeyType: 'HASH', AttributeName: 'a' }, { KeyType: 'HASH', AttributeName: 'a' } ], + ProvisionedThroughput: { ReadCapacityUnits: 1, WriteCapacityUnits: 1 } }, + 'Invalid KeySchema: Some index key attribute have no definition', done) }) - it('should return ValidationException for missing key attribute definitions if BillingMode is PAY_PER_REQUEST', function(done) { - assertValidation({TableName: 'abc', AttributeDefinitions: [], - KeySchema: [{KeyType: 'HASH', AttributeName: 'a'}], BillingMode: 'PAY_PER_REQUEST'}, - 'Invalid KeySchema: Some index key attribute have no definition', done) + it('should return ValidationException for missing key attribute definitions if BillingMode is PAY_PER_REQUEST', function (done) { + assertValidation({ TableName: 'abc', AttributeDefinitions: [], + KeySchema: [ { KeyType: 'HASH', AttributeName: 'a' } ], BillingMode: 'PAY_PER_REQUEST' }, + 'Invalid KeySchema: Some index key attribute have no definition', done) }) - it('should return ValidationException for attribute definitions member nulls', function(done) { - assertValidation({TableName: 'abc', AttributeDefinitions: [{}], - KeySchema: [{KeyType: 'HASH', AttributeName: 'a'}, {KeyType: 'HASH', AttributeName: 'a'}], - ProvisionedThroughput: {ReadCapacityUnits: 1, WriteCapacityUnits: 1}}, [ - 'Value null at \'attributeDefinitions.1.member.attributeName\' failed to satisfy constraint: ' + + it('should return ValidationException for attribute definitions member nulls', function (done) { + assertValidation({ TableName: 'abc', AttributeDefinitions: [ {} ], + KeySchema: [ { KeyType: 'HASH', AttributeName: 'a' }, { KeyType: 'HASH', AttributeName: 'a' } ], + ProvisionedThroughput: { ReadCapacityUnits: 1, WriteCapacityUnits: 1 } }, [ + 'Value null at \'attributeDefinitions.1.member.attributeName\' failed to satisfy constraint: ' + 'Member must not be null', - 'Value null at \'attributeDefinitions.1.member.attributeType\' failed to satisfy constraint: ' + + 'Value null at \'attributeDefinitions.1.member.attributeType\' failed to satisfy constraint: ' + 'Member must not be null', - ], done) + ], done) }) - it('should return ValidationException for SS in attr definition', function(done) { - assertValidation({TableName: 'abc', AttributeDefinitions: [{AttributeName: 'b', AttributeType: 'SS'}], - KeySchema: [{KeyType: 'HASH', AttributeName: 'a'}, {KeyType: 'HASH', AttributeName: 'a'}], - ProvisionedThroughput: {ReadCapacityUnits: 1, WriteCapacityUnits: 1}}, - '1 validation error detected: ' + + it('should return ValidationException for SS in attr definition', function (done) { + assertValidation({ TableName: 'abc', AttributeDefinitions: [ { AttributeName: 'b', AttributeType: 'SS' } ], + KeySchema: [ { KeyType: 'HASH', AttributeName: 'a' }, { KeyType: 'HASH', AttributeName: 'a' } ], + ProvisionedThroughput: { ReadCapacityUnits: 1, WriteCapacityUnits: 1 } }, + '1 validation error detected: ' + 'Value \'SS\' at \'attributeDefinitions.1.member.attributeType\' failed to satisfy constraint: ' + 'Member must satisfy enum value set: [B, N, S]', done) }) - it('should return ValidationException for random attr definition', function(done) { - assertValidation({TableName: 'abc', AttributeDefinitions: [{AttributeName: 'b', AttributeType: 'a'}], - KeySchema: [{KeyType: 'HASH', AttributeName: 'a'}, {KeyType: 'HASH', AttributeName: 'a'}], - ProvisionedThroughput: {ReadCapacityUnits: 1, WriteCapacityUnits: 1}}, - '1 validation error detected: ' + + it('should return ValidationException for random attr definition', function (done) { + assertValidation({ TableName: 'abc', AttributeDefinitions: [ { AttributeName: 'b', AttributeType: 'a' } ], + KeySchema: [ { KeyType: 'HASH', AttributeName: 'a' }, { KeyType: 'HASH', AttributeName: 'a' } ], + ProvisionedThroughput: { ReadCapacityUnits: 1, WriteCapacityUnits: 1 } }, + '1 validation error detected: ' + 'Value \'a\' at \'attributeDefinitions.1.member.attributeType\' failed to satisfy constraint: ' + 'Member must satisfy enum value set: [B, N, S]', done) }) - it('should return ValidationException for missing key attr definition when double', function(done) { - assertValidation({TableName: 'abc', AttributeDefinitions: [{AttributeName: 'b', AttributeType: 'S'}], - KeySchema: [{KeyType: 'HASH', AttributeName: 'a'}, {KeyType: 'HASH', AttributeName: 'a'}], - ProvisionedThroughput: {ReadCapacityUnits: 1, WriteCapacityUnits: 1}}, - 'Invalid KeySchema: Some index key attribute have no definition', done) + it('should return ValidationException for missing key attr definition when double', function (done) { + assertValidation({ TableName: 'abc', AttributeDefinitions: [ { AttributeName: 'b', AttributeType: 'S' } ], + KeySchema: [ { KeyType: 'HASH', AttributeName: 'a' }, { KeyType: 'HASH', AttributeName: 'a' } ], + ProvisionedThroughput: { ReadCapacityUnits: 1, WriteCapacityUnits: 1 } }, + 'Invalid KeySchema: Some index key attribute have no definition', done) }) - it('should return ValidationException for missing key attr definition', function(done) { - assertValidation({TableName: 'abc', AttributeDefinitions: [{AttributeName: 'b', AttributeType: 'S'}], - KeySchema: [{KeyType: 'HASH', AttributeName: 'a'}], - ProvisionedThroughput: {ReadCapacityUnits: 1, WriteCapacityUnits: 1}}, - 'One or more parameter values were invalid: Some index key attributes are not defined in ' + + it('should return ValidationException for missing key attr definition', function (done) { + assertValidation({ TableName: 'abc', AttributeDefinitions: [ { AttributeName: 'b', AttributeType: 'S' } ], + KeySchema: [ { KeyType: 'HASH', AttributeName: 'a' } ], + ProvisionedThroughput: { ReadCapacityUnits: 1, WriteCapacityUnits: 1 } }, + 'One or more parameter values were invalid: Some index key attributes are not defined in ' + 'AttributeDefinitions. Keys: [a], AttributeDefinitions: [b]', done) }) - it('should return ValidationException for missing key attr definition when double and valid', function(done) { - assertValidation({TableName: 'abc', AttributeDefinitions: [{AttributeName: 'b', AttributeType: 'S'}], - KeySchema: [{KeyType: 'HASH', AttributeName: 'a'}, {KeyType: 'RANGE', AttributeName: 'b'}], - ProvisionedThroughput: {ReadCapacityUnits: 1, WriteCapacityUnits: 1}}, - 'Invalid KeySchema: Some index key attribute have no definition', done) + it('should return ValidationException for missing key attr definition when double and valid', function (done) { + assertValidation({ TableName: 'abc', AttributeDefinitions: [ { AttributeName: 'b', AttributeType: 'S' } ], + KeySchema: [ { KeyType: 'HASH', AttributeName: 'a' }, { KeyType: 'RANGE', AttributeName: 'b' } ], + ProvisionedThroughput: { ReadCapacityUnits: 1, WriteCapacityUnits: 1 } }, + 'Invalid KeySchema: Some index key attribute have no definition', done) }) - it('should return ValidationException for missing key attr definition when double and same', function(done) { - assertValidation({TableName: 'abc', AttributeDefinitions: [{AttributeName: 'a', AttributeType: 'S'}], - KeySchema: [{KeyType: 'HASH', AttributeName: 'a'}, {KeyType: 'HASH', AttributeName: 'a'}], - ProvisionedThroughput: {ReadCapacityUnits: 1, WriteCapacityUnits: 1}}, - 'Invalid KeySchema: Some index key attribute have no definition', done) + it('should return ValidationException for missing key attr definition when double and same', function (done) { + assertValidation({ TableName: 'abc', AttributeDefinitions: [ { AttributeName: 'a', AttributeType: 'S' } ], + KeySchema: [ { KeyType: 'HASH', AttributeName: 'a' }, { KeyType: 'HASH', AttributeName: 'a' } ], + ProvisionedThroughput: { ReadCapacityUnits: 1, WriteCapacityUnits: 1 } }, + 'Invalid KeySchema: Some index key attribute have no definition', done) }) - it('should return ValidationException for hash key and range key having same name', function(done) { - assertValidation({TableName: 'abc', - AttributeDefinitions: [{AttributeName: 'a', AttributeType: 'S'}, {AttributeName: 'b', AttributeType: 'S'}], - KeySchema: [{KeyType: 'HASH', AttributeName: 'a'}, {KeyType: 'HASH', AttributeName: 'a'}], - ProvisionedThroughput: {ReadCapacityUnits: 1, WriteCapacityUnits: 1}}, - 'Both the Hash Key and the Range Key element in the KeySchema have the same name', done) + it('should return ValidationException for hash key and range key having same name', function (done) { + assertValidation({ TableName: 'abc', + AttributeDefinitions: [ { AttributeName: 'a', AttributeType: 'S' }, { AttributeName: 'b', AttributeType: 'S' } ], + KeySchema: [ { KeyType: 'HASH', AttributeName: 'a' }, { KeyType: 'HASH', AttributeName: 'a' } ], + ProvisionedThroughput: { ReadCapacityUnits: 1, WriteCapacityUnits: 1 } }, + 'Both the Hash Key and the Range Key element in the KeySchema have the same name', done) }) - it('should return ValidationException for second key not being range', function(done) { - assertValidation({TableName: 'abc', - AttributeDefinitions: [{AttributeName: 'a', AttributeType: 'S'}, {AttributeName: 'b', AttributeType: 'S'}], - KeySchema: [{KeyType: 'HASH', AttributeName: 'a'}, {KeyType: 'HASH', AttributeName: 'b'}], - ProvisionedThroughput: {ReadCapacityUnits: 1, WriteCapacityUnits: 1}}, - 'Invalid KeySchema: The second KeySchemaElement is not a RANGE key type', done) + it('should return ValidationException for second key not being range', function (done) { + assertValidation({ TableName: 'abc', + AttributeDefinitions: [ { AttributeName: 'a', AttributeType: 'S' }, { AttributeName: 'b', AttributeType: 'S' } ], + KeySchema: [ { KeyType: 'HASH', AttributeName: 'a' }, { KeyType: 'HASH', AttributeName: 'b' } ], + ProvisionedThroughput: { ReadCapacityUnits: 1, WriteCapacityUnits: 1 } }, + 'Invalid KeySchema: The second KeySchemaElement is not a RANGE key type', done) }) - it('should return ValidationException for second key being hash', function(done) { - assertValidation({TableName: 'abc', - AttributeDefinitions: [{AttributeName: 'a', AttributeType: 'S'}, {AttributeName: 'b', AttributeType: 'S'}], - KeySchema: [{KeyType: 'RANGE', AttributeName: 'a'}, {KeyType: 'HASH', AttributeName: 'b'}], - ProvisionedThroughput: {ReadCapacityUnits: 1, WriteCapacityUnits: 1}}, - 'Invalid KeySchema: The first KeySchemaElement is not a HASH key type', done) + it('should return ValidationException for second key being hash', function (done) { + assertValidation({ TableName: 'abc', + AttributeDefinitions: [ { AttributeName: 'a', AttributeType: 'S' }, { AttributeName: 'b', AttributeType: 'S' } ], + KeySchema: [ { KeyType: 'RANGE', AttributeName: 'a' }, { KeyType: 'HASH', AttributeName: 'b' } ], + ProvisionedThroughput: { ReadCapacityUnits: 1, WriteCapacityUnits: 1 } }, + 'Invalid KeySchema: The first KeySchemaElement is not a HASH key type', done) }) - it('should return ValidationException for both being range key', function(done) { - assertValidation({TableName: 'abc', - AttributeDefinitions: [{AttributeName: 'a', AttributeType: 'S'}, {AttributeName: 'b', AttributeType: 'S'}], - KeySchema: [{KeyType: 'RANGE', AttributeName: 'a'}, {KeyType: 'RANGE', AttributeName: 'b'}], - ProvisionedThroughput: {ReadCapacityUnits: 1, WriteCapacityUnits: 1}}, - 'Invalid KeySchema: The first KeySchemaElement is not a HASH key type', done) + it('should return ValidationException for both being range key', function (done) { + assertValidation({ TableName: 'abc', + AttributeDefinitions: [ { AttributeName: 'a', AttributeType: 'S' }, { AttributeName: 'b', AttributeType: 'S' } ], + KeySchema: [ { KeyType: 'RANGE', AttributeName: 'a' }, { KeyType: 'RANGE', AttributeName: 'b' } ], + ProvisionedThroughput: { ReadCapacityUnits: 1, WriteCapacityUnits: 1 } }, + 'Invalid KeySchema: The first KeySchemaElement is not a HASH key type', done) }) - it('should return ValidationException for extra attribute in definitions when range', function(done) { - assertValidation({TableName: 'abc', - AttributeDefinitions: [{AttributeName: 'a', AttributeType: 'S'}, {AttributeName: 'c', AttributeType: 'S'}, {AttributeName: 'b', AttributeType: 'S'}], - KeySchema: [{KeyType: 'HASH', AttributeName: 'a'}, {KeyType: 'RANGE', AttributeName: 'b'}], - ProvisionedThroughput: {ReadCapacityUnits: 1, WriteCapacityUnits: 1}}, - 'One or more parameter values were invalid: Number of attributes in KeySchema does not ' + + it('should return ValidationException for extra attribute in definitions when range', function (done) { + assertValidation({ TableName: 'abc', + AttributeDefinitions: [ { AttributeName: 'a', AttributeType: 'S' }, { AttributeName: 'c', AttributeType: 'S' }, { AttributeName: 'b', AttributeType: 'S' } ], + KeySchema: [ { KeyType: 'HASH', AttributeName: 'a' }, { KeyType: 'RANGE', AttributeName: 'b' } ], + ProvisionedThroughput: { ReadCapacityUnits: 1, WriteCapacityUnits: 1 } }, + 'One or more parameter values were invalid: Number of attributes in KeySchema does not ' + 'exactly match number of attributes defined in AttributeDefinitions', done) }) - it('should return ValidationException for extra attribute in definitions when hash', function(done) { - assertValidation({TableName: 'abc', - AttributeDefinitions: [{AttributeName: 'a', AttributeType: 'S'}, {AttributeName: 'b', AttributeType: 'S'}], - KeySchema: [{KeyType: 'HASH', AttributeName: 'a'}], - ProvisionedThroughput: {ReadCapacityUnits: 1, WriteCapacityUnits: 1}}, - 'One or more parameter values were invalid: Number of attributes in KeySchema does not ' + + it('should return ValidationException for extra attribute in definitions when hash', function (done) { + assertValidation({ TableName: 'abc', + AttributeDefinitions: [ { AttributeName: 'a', AttributeType: 'S' }, { AttributeName: 'b', AttributeType: 'S' } ], + KeySchema: [ { KeyType: 'HASH', AttributeName: 'a' } ], + ProvisionedThroughput: { ReadCapacityUnits: 1, WriteCapacityUnits: 1 } }, + 'One or more parameter values were invalid: Number of attributes in KeySchema does not ' + 'exactly match number of attributes defined in AttributeDefinitions', done) }) - it('should return ValidationException for empty LocalSecondaryIndexes list', function(done) { - assertValidation({TableName: 'abc', - AttributeDefinitions: [{AttributeName: 'a', AttributeType: 'S'}, {AttributeName: 'b', AttributeType: 'S'}], - KeySchema: [{KeyType: 'HASH', AttributeName: 'a'}], + it('should return ValidationException for empty LocalSecondaryIndexes list', function (done) { + assertValidation({ TableName: 'abc', + AttributeDefinitions: [ { AttributeName: 'a', AttributeType: 'S' }, { AttributeName: 'b', AttributeType: 'S' } ], + KeySchema: [ { KeyType: 'HASH', AttributeName: 'a' } ], LocalSecondaryIndexes: [], - ProvisionedThroughput: {ReadCapacityUnits: 1, WriteCapacityUnits: 1}}, - 'One or more parameter values were invalid: List of LocalSecondaryIndexes is empty', done) + ProvisionedThroughput: { ReadCapacityUnits: 1, WriteCapacityUnits: 1 } }, + 'One or more parameter values were invalid: List of LocalSecondaryIndexes is empty', done) }) - it('should return ValidationException for more than five empty LocalSecondaryIndexes', function(done) { - assertValidation({TableName: 'abc', - AttributeDefinitions: [{AttributeName: 'a', AttributeType: 'S'}, {AttributeName: 'b', AttributeType: 'S'}], - KeySchema: [{KeyType: 'HASH', AttributeName: 'a'}, {KeyType: 'RANGE', AttributeName: 'b'}], - LocalSecondaryIndexes: [{}, {}, {}, {}, {}, {}, {}, {}, {}], - ProvisionedThroughput: {ReadCapacityUnits: 1, WriteCapacityUnits: 1}}, [ - 'Value null at \'localSecondaryIndexes.1.member.indexName\' failed to satisfy constraint: ' + + it('should return ValidationException for more than five empty LocalSecondaryIndexes', function (done) { + assertValidation({ TableName: 'abc', + AttributeDefinitions: [ { AttributeName: 'a', AttributeType: 'S' }, { AttributeName: 'b', AttributeType: 'S' } ], + KeySchema: [ { KeyType: 'HASH', AttributeName: 'a' }, { KeyType: 'RANGE', AttributeName: 'b' } ], + LocalSecondaryIndexes: [ {}, {}, {}, {}, {}, {}, {}, {}, {} ], + ProvisionedThroughput: { ReadCapacityUnits: 1, WriteCapacityUnits: 1 } }, [ + 'Value null at \'localSecondaryIndexes.1.member.indexName\' failed to satisfy constraint: ' + 'Member must not be null', - 'Value null at \'localSecondaryIndexes.1.member.keySchema\' failed to satisfy constraint: ' + + 'Value null at \'localSecondaryIndexes.1.member.keySchema\' failed to satisfy constraint: ' + 'Member must not be null', - 'Value null at \'localSecondaryIndexes.1.member.projection\' failed to satisfy constraint: ' + + 'Value null at \'localSecondaryIndexes.1.member.projection\' failed to satisfy constraint: ' + 'Member must not be null', - 'Value null at \'localSecondaryIndexes.2.member.indexName\' failed to satisfy constraint: ' + + 'Value null at \'localSecondaryIndexes.2.member.indexName\' failed to satisfy constraint: ' + 'Member must not be null', - 'Value null at \'localSecondaryIndexes.2.member.keySchema\' failed to satisfy constraint: ' + + 'Value null at \'localSecondaryIndexes.2.member.keySchema\' failed to satisfy constraint: ' + 'Member must not be null', - 'Value null at \'localSecondaryIndexes.2.member.projection\' failed to satisfy constraint: ' + + 'Value null at \'localSecondaryIndexes.2.member.projection\' failed to satisfy constraint: ' + 'Member must not be null', - 'Value null at \'localSecondaryIndexes.3.member.indexName\' failed to satisfy constraint: ' + + 'Value null at \'localSecondaryIndexes.3.member.indexName\' failed to satisfy constraint: ' + 'Member must not be null', - 'Value null at \'localSecondaryIndexes.3.member.keySchema\' failed to satisfy constraint: ' + + 'Value null at \'localSecondaryIndexes.3.member.keySchema\' failed to satisfy constraint: ' + 'Member must not be null', - 'Value null at \'localSecondaryIndexes.3.member.projection\' failed to satisfy constraint: ' + + 'Value null at \'localSecondaryIndexes.3.member.projection\' failed to satisfy constraint: ' + 'Member must not be null', - 'Value null at \'localSecondaryIndexes.4.member.indexName\' failed to satisfy constraint: ' + + 'Value null at \'localSecondaryIndexes.4.member.indexName\' failed to satisfy constraint: ' + 'Member must not be null', - ], done) + ], done) }) - it('should return ValidationException for bad LocalSecondaryIndex names', function(done) { + it('should return ValidationException for bad LocalSecondaryIndex names', function (done) { var name = new Array(256 + 1).join('a') - assertValidation({TableName: 'abc', - AttributeDefinitions: [{AttributeName: 'a', AttributeType: 'S'}, {AttributeName: 'b', AttributeType: 'S'}], - KeySchema: [{KeyType: 'HASH', AttributeName: 'a'}], - LocalSecondaryIndexes: [{ + assertValidation({ TableName: 'abc', + AttributeDefinitions: [ { AttributeName: 'a', AttributeType: 'S' }, { AttributeName: 'b', AttributeType: 'S' } ], + KeySchema: [ { KeyType: 'HASH', AttributeName: 'a' } ], + LocalSecondaryIndexes: [ { IndexName: 'h;', KeySchema: [], Projection: {}, }, { - IndexName: name, KeySchema: [{AttributeName: 'a', KeyType: 'HASH'}], Projection: {}, - }], - ProvisionedThroughput: {ReadCapacityUnits: 1, WriteCapacityUnits: 1}}, [ - 'Value \'h;\' at \'localSecondaryIndexes.1.member.indexName\' failed to satisfy constraint: ' + + IndexName: name, KeySchema: [ { AttributeName: 'a', KeyType: 'HASH' } ], Projection: {}, + } ], + ProvisionedThroughput: { ReadCapacityUnits: 1, WriteCapacityUnits: 1 } }, [ + 'Value \'h;\' at \'localSecondaryIndexes.1.member.indexName\' failed to satisfy constraint: ' + 'Member must satisfy regular expression pattern: [a-zA-Z0-9_.-]+', - 'Value \'h;\' at \'localSecondaryIndexes.1.member.indexName\' failed to satisfy constraint: ' + + 'Value \'h;\' at \'localSecondaryIndexes.1.member.indexName\' failed to satisfy constraint: ' + 'Member must have length greater than or equal to 3', - 'Value \'[]\' at \'localSecondaryIndexes.1.member.keySchema\' failed to satisfy constraint: ' + + 'Value \'[]\' at \'localSecondaryIndexes.1.member.keySchema\' failed to satisfy constraint: ' + 'Member must have length greater than or equal to 1', - 'Value \'' + name + '\' at \'localSecondaryIndexes.2.member.indexName\' failed to satisfy constraint: ' + + 'Value \'' + name + '\' at \'localSecondaryIndexes.2.member.indexName\' failed to satisfy constraint: ' + 'Member must have length less than or equal to 255', - ], done) + ], done) }) - it('should return ValidationException for no range key with LocalSecondaryIndex', function(done) { - assertValidation({TableName: 'abc', - AttributeDefinitions: [{AttributeName: 'a', AttributeType: 'S'}, {AttributeName: 'b', AttributeType: 'S'}], - KeySchema: [{KeyType: 'HASH', AttributeName: 'a'}], - LocalSecondaryIndexes: [{IndexName: 'abc', KeySchema: [{AttributeName: 'c', KeyType: 'RANGE'}], Projection: {}}], - ProvisionedThroughput: {ReadCapacityUnits: 1, WriteCapacityUnits: 1}}, - 'One or more parameter values were invalid: Table KeySchema does not have a range key, ' + + it('should return ValidationException for no range key with LocalSecondaryIndex', function (done) { + assertValidation({ TableName: 'abc', + AttributeDefinitions: [ { AttributeName: 'a', AttributeType: 'S' }, { AttributeName: 'b', AttributeType: 'S' } ], + KeySchema: [ { KeyType: 'HASH', AttributeName: 'a' } ], + LocalSecondaryIndexes: [ { IndexName: 'abc', KeySchema: [ { AttributeName: 'c', KeyType: 'RANGE' } ], Projection: {} } ], + ProvisionedThroughput: { ReadCapacityUnits: 1, WriteCapacityUnits: 1 } }, + 'One or more parameter values were invalid: Table KeySchema does not have a range key, ' + 'which is required when specifying a LocalSecondaryIndex', done) }) - it('should return ValidationException for missing attribute definitions in LocalSecondaryIndex', function(done) { - assertValidation({TableName: 'abc', - AttributeDefinitions: [{AttributeName: 'a', AttributeType: 'S'}, {AttributeName: 'b', AttributeType: 'S'}], - KeySchema: [{KeyType: 'HASH', AttributeName: 'a'}, {KeyType: 'RANGE', AttributeName: 'b'}], - LocalSecondaryIndexes: [{ + it('should return ValidationException for missing attribute definitions in LocalSecondaryIndex', function (done) { + assertValidation({ TableName: 'abc', + AttributeDefinitions: [ { AttributeName: 'a', AttributeType: 'S' }, { AttributeName: 'b', AttributeType: 'S' } ], + KeySchema: [ { KeyType: 'HASH', AttributeName: 'a' }, { KeyType: 'RANGE', AttributeName: 'b' } ], + LocalSecondaryIndexes: [ { IndexName: 'abc', - KeySchema: [{AttributeName: 'c', KeyType: 'RANGE'}, {AttributeName: 'd', KeyType: 'RANGE'}], + KeySchema: [ { AttributeName: 'c', KeyType: 'RANGE' }, { AttributeName: 'd', KeyType: 'RANGE' } ], Projection: {}, }, { IndexName: 'abc', - KeySchema: [{AttributeName: 'e', KeyType: 'RANGE'}], + KeySchema: [ { AttributeName: 'e', KeyType: 'RANGE' } ], Projection: {}, - }], - ProvisionedThroughput: {ReadCapacityUnits: 1, WriteCapacityUnits: 1}}, - new RegExp('One or more parameter values were invalid: ' + + } ], + ProvisionedThroughput: { ReadCapacityUnits: 1, WriteCapacityUnits: 1 } }, + new RegExp('One or more parameter values were invalid: ' + 'Some index key attributes are not defined in AttributeDefinitions. ' + 'Keys: \\[(c, d|d, c)\\], AttributeDefinitions: \\[(a, b|b, a)\\]'), done) }) - it('should return ValidationException for first key in LocalSecondaryIndex not being hash', function(done) { - assertValidation({TableName: 'abc', - AttributeDefinitions: [{AttributeName: 'a', AttributeType: 'S'}, {AttributeName: 'b', AttributeType: 'S'}], - KeySchema: [{KeyType: 'HASH', AttributeName: 'a'}, {KeyType: 'RANGE', AttributeName: 'b'}], - LocalSecondaryIndexes: [{IndexName: 'abc', KeySchema: [{AttributeName: 'a', KeyType: 'RANGE'}], Projection: {}}], - ProvisionedThroughput: {ReadCapacityUnits: 1, WriteCapacityUnits: 1}}, - 'Invalid KeySchema: The first KeySchemaElement is not a HASH key type', done) - }) - - it('should return ValidationException for same names of keys in LocalSecondaryIndex', function(done) { - assertValidation({TableName: 'abc', - AttributeDefinitions: [{AttributeName: 'a', AttributeType: 'S'}, {AttributeName: 'b', AttributeType: 'S'}], - KeySchema: [{KeyType: 'HASH', AttributeName: 'a'}, {KeyType: 'RANGE', AttributeName: 'b'}], - LocalSecondaryIndexes: [{IndexName: 'abc', KeySchema: [{AttributeName: 'a', KeyType: 'HASH'}, {AttributeName: 'a', KeyType: 'HASH'}], Projection: {}}], - ProvisionedThroughput: {ReadCapacityUnits: 1, WriteCapacityUnits: 1}}, - 'Both the Hash Key and the Range Key element in the KeySchema have the same name', done) - }) - - it('should return ValidationException for second key of LocalSecondaryIndex not being range', function(done) { - assertValidation({TableName: 'abc', - AttributeDefinitions: [{AttributeName: 'a', AttributeType: 'S'}, {AttributeName: 'b', AttributeType: 'S'}], - KeySchema: [{KeyType: 'HASH', AttributeName: 'a'}, {KeyType: 'RANGE', AttributeName: 'b'}], - LocalSecondaryIndexes: [{IndexName: 'abc', KeySchema: [{AttributeName: 'a', KeyType: 'HASH'}, {AttributeName: 'b', KeyType: 'HASH'}], Projection: {}}], - ProvisionedThroughput: {ReadCapacityUnits: 1, WriteCapacityUnits: 1}}, - 'Invalid KeySchema: The second KeySchemaElement is not a RANGE key type', done) - }) - - it('should return ValidationException for no range key in LocalSecondaryIndex', function(done) { - assertValidation({TableName: 'abc', - AttributeDefinitions: [{AttributeName: 'a', AttributeType: 'S'}, {AttributeName: 'b', AttributeType: 'S'}], - KeySchema: [{KeyType: 'HASH', AttributeName: 'a'}, {KeyType: 'RANGE', AttributeName: 'b'}], - LocalSecondaryIndexes: [{IndexName: 'abc', KeySchema: [{AttributeName: 'b', KeyType: 'HASH'}], Projection: {}}], - ProvisionedThroughput: {ReadCapacityUnits: 1, WriteCapacityUnits: 1}}, - 'One or more parameter values were invalid: Index KeySchema does not have a range key for index: abc', done) - }) - - it('should return ValidationException for different hash key between LocalSecondaryIndex and table', function(done) { - assertValidation({TableName: 'abc', - AttributeDefinitions: [{AttributeName: 'a', AttributeType: 'S'}, {AttributeName: 'b', AttributeType: 'S'}], - KeySchema: [{KeyType: 'HASH', AttributeName: 'a'}, {KeyType: 'RANGE', AttributeName: 'b'}], - LocalSecondaryIndexes: [{IndexName: 'abc', KeySchema: [{AttributeName: 'b', KeyType: 'HASH'}, {AttributeName: 'a', KeyType: 'RANGE'}], Projection: {}}], - ProvisionedThroughput: {ReadCapacityUnits: 1, WriteCapacityUnits: 1}}, - 'One or more parameter values were invalid: ' + + it('should return ValidationException for first key in LocalSecondaryIndex not being hash', function (done) { + assertValidation({ TableName: 'abc', + AttributeDefinitions: [ { AttributeName: 'a', AttributeType: 'S' }, { AttributeName: 'b', AttributeType: 'S' } ], + KeySchema: [ { KeyType: 'HASH', AttributeName: 'a' }, { KeyType: 'RANGE', AttributeName: 'b' } ], + LocalSecondaryIndexes: [ { IndexName: 'abc', KeySchema: [ { AttributeName: 'a', KeyType: 'RANGE' } ], Projection: {} } ], + ProvisionedThroughput: { ReadCapacityUnits: 1, WriteCapacityUnits: 1 } }, + 'Invalid KeySchema: The first KeySchemaElement is not a HASH key type', done) + }) + + it('should return ValidationException for same names of keys in LocalSecondaryIndex', function (done) { + assertValidation({ TableName: 'abc', + AttributeDefinitions: [ { AttributeName: 'a', AttributeType: 'S' }, { AttributeName: 'b', AttributeType: 'S' } ], + KeySchema: [ { KeyType: 'HASH', AttributeName: 'a' }, { KeyType: 'RANGE', AttributeName: 'b' } ], + LocalSecondaryIndexes: [ { IndexName: 'abc', KeySchema: [ { AttributeName: 'a', KeyType: 'HASH' }, { AttributeName: 'a', KeyType: 'HASH' } ], Projection: {} } ], + ProvisionedThroughput: { ReadCapacityUnits: 1, WriteCapacityUnits: 1 } }, + 'Both the Hash Key and the Range Key element in the KeySchema have the same name', done) + }) + + it('should return ValidationException for second key of LocalSecondaryIndex not being range', function (done) { + assertValidation({ TableName: 'abc', + AttributeDefinitions: [ { AttributeName: 'a', AttributeType: 'S' }, { AttributeName: 'b', AttributeType: 'S' } ], + KeySchema: [ { KeyType: 'HASH', AttributeName: 'a' }, { KeyType: 'RANGE', AttributeName: 'b' } ], + LocalSecondaryIndexes: [ { IndexName: 'abc', KeySchema: [ { AttributeName: 'a', KeyType: 'HASH' }, { AttributeName: 'b', KeyType: 'HASH' } ], Projection: {} } ], + ProvisionedThroughput: { ReadCapacityUnits: 1, WriteCapacityUnits: 1 } }, + 'Invalid KeySchema: The second KeySchemaElement is not a RANGE key type', done) + }) + + it('should return ValidationException for no range key in LocalSecondaryIndex', function (done) { + assertValidation({ TableName: 'abc', + AttributeDefinitions: [ { AttributeName: 'a', AttributeType: 'S' }, { AttributeName: 'b', AttributeType: 'S' } ], + KeySchema: [ { KeyType: 'HASH', AttributeName: 'a' }, { KeyType: 'RANGE', AttributeName: 'b' } ], + LocalSecondaryIndexes: [ { IndexName: 'abc', KeySchema: [ { AttributeName: 'b', KeyType: 'HASH' } ], Projection: {} } ], + ProvisionedThroughput: { ReadCapacityUnits: 1, WriteCapacityUnits: 1 } }, + 'One or more parameter values were invalid: Index KeySchema does not have a range key for index: abc', done) + }) + + it('should return ValidationException for different hash key between LocalSecondaryIndex and table', function (done) { + assertValidation({ TableName: 'abc', + AttributeDefinitions: [ { AttributeName: 'a', AttributeType: 'S' }, { AttributeName: 'b', AttributeType: 'S' } ], + KeySchema: [ { KeyType: 'HASH', AttributeName: 'a' }, { KeyType: 'RANGE', AttributeName: 'b' } ], + LocalSecondaryIndexes: [ { IndexName: 'abc', KeySchema: [ { AttributeName: 'b', KeyType: 'HASH' }, { AttributeName: 'a', KeyType: 'RANGE' } ], Projection: {} } ], + ProvisionedThroughput: { ReadCapacityUnits: 1, WriteCapacityUnits: 1 } }, + 'One or more parameter values were invalid: ' + 'Index KeySchema does not have the same leading hash key as table KeySchema for index: ' + 'abc. index hash key: b, table hash key: a', done) }) - it('should return ValidationException for same named keys in LocalSecondaryIndex when one hash and one range', function(done) { - assertValidation({TableName: 'abc', - AttributeDefinitions: [{AttributeName: 'a', AttributeType: 'S'}, {AttributeName: 'b', AttributeType: 'S'}], - KeySchema: [{KeyType: 'HASH', AttributeName: 'a'}, {KeyType: 'RANGE', AttributeName: 'b'}], - LocalSecondaryIndexes: [{IndexName: 'abc', KeySchema: [{AttributeName: 'a', KeyType: 'HASH'}, {AttributeName: 'a', KeyType: 'RANGE'}], Projection: {}}], - ProvisionedThroughput: {ReadCapacityUnits: 1, WriteCapacityUnits: 1}}, - 'Both the Hash Key and the Range Key element in the KeySchema have the same name', done) + it('should return ValidationException for same named keys in LocalSecondaryIndex when one hash and one range', function (done) { + assertValidation({ TableName: 'abc', + AttributeDefinitions: [ { AttributeName: 'a', AttributeType: 'S' }, { AttributeName: 'b', AttributeType: 'S' } ], + KeySchema: [ { KeyType: 'HASH', AttributeName: 'a' }, { KeyType: 'RANGE', AttributeName: 'b' } ], + LocalSecondaryIndexes: [ { IndexName: 'abc', KeySchema: [ { AttributeName: 'a', KeyType: 'HASH' }, { AttributeName: 'a', KeyType: 'RANGE' } ], Projection: {} } ], + ProvisionedThroughput: { ReadCapacityUnits: 1, WriteCapacityUnits: 1 } }, + 'Both the Hash Key and the Range Key element in the KeySchema have the same name', done) }) - it('should return ValidationException for missing attribute definitions when hash is same in LocalSecondaryIndex', function(done) { - assertValidation({TableName: 'abc', - AttributeDefinitions: [{AttributeName: 'a', AttributeType: 'S'}, {AttributeName: 'b', AttributeType: 'S'}], - KeySchema: [{KeyType: 'HASH', AttributeName: 'a'}, {KeyType: 'RANGE', AttributeName: 'b'}], - LocalSecondaryIndexes: [{ + it('should return ValidationException for missing attribute definitions when hash is same in LocalSecondaryIndex', function (done) { + assertValidation({ TableName: 'abc', + AttributeDefinitions: [ { AttributeName: 'a', AttributeType: 'S' }, { AttributeName: 'b', AttributeType: 'S' } ], + KeySchema: [ { KeyType: 'HASH', AttributeName: 'a' }, { KeyType: 'RANGE', AttributeName: 'b' } ], + LocalSecondaryIndexes: [ { IndexName: 'abc', - KeySchema: [{AttributeName: 'a', KeyType: 'HASH'}, {AttributeName: 'c', KeyType: 'RANGE'}], + KeySchema: [ { AttributeName: 'a', KeyType: 'HASH' }, { AttributeName: 'c', KeyType: 'RANGE' } ], Projection: {}, - }], - ProvisionedThroughput: {ReadCapacityUnits: 1, WriteCapacityUnits: 1}}, - new RegExp('One or more parameter values were invalid: ' + + } ], + ProvisionedThroughput: { ReadCapacityUnits: 1, WriteCapacityUnits: 1 } }, + new RegExp('One or more parameter values were invalid: ' + 'Some index key attributes are not defined in AttributeDefinitions. ' + 'Keys: \\[(a, c|c, a)\\], AttributeDefinitions: \\[(a, b|b, a)\\]'), done) }) - it('should return ValidationException for empty Projection in LocalSecondaryIndex', function(done) { - assertValidation({TableName: 'abc', - AttributeDefinitions: [{AttributeName: 'a', AttributeType: 'S'}, {AttributeName: 'b', AttributeType: 'S'}], - KeySchema: [{KeyType: 'HASH', AttributeName: 'a'}, {KeyType: 'RANGE', AttributeName: 'b'}], - LocalSecondaryIndexes: [{IndexName: 'abc', KeySchema: [{AttributeName: 'a', KeyType: 'HASH'}, {AttributeName: 'b', KeyType: 'RANGE'}], Projection: {}}], - ProvisionedThroughput: {ReadCapacityUnits: 1, WriteCapacityUnits: 1}}, - 'One or more parameter values were invalid: Unknown ProjectionType: null', done) + it('should return ValidationException for empty Projection in LocalSecondaryIndex', function (done) { + assertValidation({ TableName: 'abc', + AttributeDefinitions: [ { AttributeName: 'a', AttributeType: 'S' }, { AttributeName: 'b', AttributeType: 'S' } ], + KeySchema: [ { KeyType: 'HASH', AttributeName: 'a' }, { KeyType: 'RANGE', AttributeName: 'b' } ], + LocalSecondaryIndexes: [ { IndexName: 'abc', KeySchema: [ { AttributeName: 'a', KeyType: 'HASH' }, { AttributeName: 'b', KeyType: 'RANGE' } ], Projection: {} } ], + ProvisionedThroughput: { ReadCapacityUnits: 1, WriteCapacityUnits: 1 } }, + 'One or more parameter values were invalid: Unknown ProjectionType: null', done) }) - it('should return ValidationException for invalid properties in LocalSecondaryIndex', function(done) { - assertValidation({TableName: 'abc', - AttributeDefinitions: [{AttributeName: 'a', AttributeType: 'S'}, {AttributeName: 'b', AttributeType: 'S'}], - KeySchema: [{KeyType: 'HASH', AttributeName: 'a'}, {KeyType: 'RANGE', AttributeName: 'b'}], - LocalSecondaryIndexes: [{ + it('should return ValidationException for invalid properties in LocalSecondaryIndex', function (done) { + assertValidation({ TableName: 'abc', + AttributeDefinitions: [ { AttributeName: 'a', AttributeType: 'S' }, { AttributeName: 'b', AttributeType: 'S' } ], + KeySchema: [ { KeyType: 'HASH', AttributeName: 'a' }, { KeyType: 'RANGE', AttributeName: 'b' } ], + LocalSecondaryIndexes: [ { IndexName: 'abc', - KeySchema: [{AttributeName: 'a', KeyType: 'HASH'}, {AttributeName: 'b', KeyType: 'RANGE'}], - Projection: {NonKeyAttributes: [], ProjectionType: 'abc'}, - }], - ProvisionedThroughput: {ReadCapacityUnits: 1, WriteCapacityUnits: 1}}, [ - 'Value \'abc\' at \'localSecondaryIndexes.1.member.projection.projectionType\' failed to satisfy constraint: ' + + KeySchema: [ { AttributeName: 'a', KeyType: 'HASH' }, { AttributeName: 'b', KeyType: 'RANGE' } ], + Projection: { NonKeyAttributes: [], ProjectionType: 'abc' }, + } ], + ProvisionedThroughput: { ReadCapacityUnits: 1, WriteCapacityUnits: 1 } }, [ + 'Value \'abc\' at \'localSecondaryIndexes.1.member.projection.projectionType\' failed to satisfy constraint: ' + 'Member must satisfy enum value set: [ALL, INCLUDE, KEYS_ONLY]', - 'Value \'[]\' at \'localSecondaryIndexes.1.member.projection.nonKeyAttributes\' failed to satisfy constraint: ' + + 'Value \'[]\' at \'localSecondaryIndexes.1.member.projection.nonKeyAttributes\' failed to satisfy constraint: ' + 'Member must have length greater than or equal to 1', - ], done) + ], done) }) - it('should return ValidationException for missing ProjectionType in LocalSecondaryIndex', function(done) { - assertValidation({TableName: 'abc', - AttributeDefinitions: [{AttributeName: 'a', AttributeType: 'S'}, {AttributeName: 'b', AttributeType: 'S'}], - KeySchema: [{KeyType: 'HASH', AttributeName: 'a'}, {KeyType: 'RANGE', AttributeName: 'b'}], - LocalSecondaryIndexes: [{ + it('should return ValidationException for missing ProjectionType in LocalSecondaryIndex', function (done) { + assertValidation({ TableName: 'abc', + AttributeDefinitions: [ { AttributeName: 'a', AttributeType: 'S' }, { AttributeName: 'b', AttributeType: 'S' } ], + KeySchema: [ { KeyType: 'HASH', AttributeName: 'a' }, { KeyType: 'RANGE', AttributeName: 'b' } ], + LocalSecondaryIndexes: [ { IndexName: 'abc', - KeySchema: [{AttributeName: 'a', KeyType: 'HASH'}, {AttributeName: 'b', KeyType: 'RANGE'}], - Projection: {NonKeyAttributes: ['a']}, - }], - ProvisionedThroughput: {ReadCapacityUnits: 1, WriteCapacityUnits: 1}}, - 'One or more parameter values were invalid: Unknown ProjectionType: null', done) - }) - - it('should return ValidationException for NonKeyAttributes with ProjectionType ALL in LocalSecondaryIndex', function(done) { - assertValidation({TableName: 'abc', - AttributeDefinitions: [{AttributeName: 'a', AttributeType: 'S'}, {AttributeName: 'b', AttributeType: 'S'}], - KeySchema: [{KeyType: 'HASH', AttributeName: 'a'}, {KeyType: 'RANGE', AttributeName: 'b'}], - LocalSecondaryIndexes: [{ + KeySchema: [ { AttributeName: 'a', KeyType: 'HASH' }, { AttributeName: 'b', KeyType: 'RANGE' } ], + Projection: { NonKeyAttributes: [ 'a' ] }, + } ], + ProvisionedThroughput: { ReadCapacityUnits: 1, WriteCapacityUnits: 1 } }, + 'One or more parameter values were invalid: Unknown ProjectionType: null', done) + }) + + it('should return ValidationException for NonKeyAttributes with ProjectionType ALL in LocalSecondaryIndex', function (done) { + assertValidation({ TableName: 'abc', + AttributeDefinitions: [ { AttributeName: 'a', AttributeType: 'S' }, { AttributeName: 'b', AttributeType: 'S' } ], + KeySchema: [ { KeyType: 'HASH', AttributeName: 'a' }, { KeyType: 'RANGE', AttributeName: 'b' } ], + LocalSecondaryIndexes: [ { IndexName: 'abc', - KeySchema: [{AttributeName: 'a', KeyType: 'HASH'}, {AttributeName: 'b', KeyType: 'RANGE'}], - Projection: {ProjectionType: 'ALL', NonKeyAttributes: ['a']}, - }], - ProvisionedThroughput: {ReadCapacityUnits: 1, WriteCapacityUnits: 1}}, - 'One or more parameter values were invalid: ' + + KeySchema: [ { AttributeName: 'a', KeyType: 'HASH' }, { AttributeName: 'b', KeyType: 'RANGE' } ], + Projection: { ProjectionType: 'ALL', NonKeyAttributes: [ 'a' ] }, + } ], + ProvisionedThroughput: { ReadCapacityUnits: 1, WriteCapacityUnits: 1 } }, + 'One or more parameter values were invalid: ' + 'ProjectionType is ALL, but NonKeyAttributes is specified', done) }) - it('should return ValidationException for NonKeyAttributes with ProjectionType KEYS_ONLY in LocalSecondaryIndex', function(done) { - assertValidation({TableName: 'abc', - AttributeDefinitions: [{AttributeName: 'a', AttributeType: 'S'}, {AttributeName: 'b', AttributeType: 'S'}], - KeySchema: [{KeyType: 'HASH', AttributeName: 'a'}, {KeyType: 'RANGE', AttributeName: 'b'}], - LocalSecondaryIndexes: [{ + it('should return ValidationException for NonKeyAttributes with ProjectionType KEYS_ONLY in LocalSecondaryIndex', function (done) { + assertValidation({ TableName: 'abc', + AttributeDefinitions: [ { AttributeName: 'a', AttributeType: 'S' }, { AttributeName: 'b', AttributeType: 'S' } ], + KeySchema: [ { KeyType: 'HASH', AttributeName: 'a' }, { KeyType: 'RANGE', AttributeName: 'b' } ], + LocalSecondaryIndexes: [ { IndexName: 'abc', - KeySchema: [{AttributeName: 'a', KeyType: 'HASH'}, {AttributeName: 'b', KeyType: 'RANGE'}], - Projection: {ProjectionType: 'KEYS_ONLY', NonKeyAttributes: ['a']}, - }], - ProvisionedThroughput: {ReadCapacityUnits: 1, WriteCapacityUnits: 1}}, - 'One or more parameter values were invalid: ' + + KeySchema: [ { AttributeName: 'a', KeyType: 'HASH' }, { AttributeName: 'b', KeyType: 'RANGE' } ], + Projection: { ProjectionType: 'KEYS_ONLY', NonKeyAttributes: [ 'a' ] }, + } ], + ProvisionedThroughput: { ReadCapacityUnits: 1, WriteCapacityUnits: 1 } }, + 'One or more parameter values were invalid: ' + 'ProjectionType is KEYS_ONLY, but NonKeyAttributes is specified', done) }) - it('should return ValidationException for duplicate index names in LocalSecondaryIndexes', function(done) { - assertValidation({TableName: 'abc', - AttributeDefinitions: [{AttributeName: 'a', AttributeType: 'S'}, {AttributeName: 'b', AttributeType: 'S'}], - KeySchema: [{KeyType: 'HASH', AttributeName: 'a'}, {KeyType: 'RANGE', AttributeName: 'b'}], - LocalSecondaryIndexes: [{ + it('should return ValidationException for duplicate index names in LocalSecondaryIndexes', function (done) { + assertValidation({ TableName: 'abc', + AttributeDefinitions: [ { AttributeName: 'a', AttributeType: 'S' }, { AttributeName: 'b', AttributeType: 'S' } ], + KeySchema: [ { KeyType: 'HASH', AttributeName: 'a' }, { KeyType: 'RANGE', AttributeName: 'b' } ], + LocalSecondaryIndexes: [ { IndexName: 'abc', - KeySchema: [{AttributeName: 'a', KeyType: 'HASH'}, {AttributeName: 'b', KeyType: 'RANGE'}], - Projection: {ProjectionType: 'ALL'}, + KeySchema: [ { AttributeName: 'a', KeyType: 'HASH' }, { AttributeName: 'b', KeyType: 'RANGE' } ], + Projection: { ProjectionType: 'ALL' }, }, { IndexName: 'abc', - KeySchema: [{AttributeName: 'a', KeyType: 'HASH'}, {AttributeName: 'b', KeyType: 'RANGE'}], - Projection: {ProjectionType: 'ALL'}, - }], - ProvisionedThroughput: {ReadCapacityUnits: 1, WriteCapacityUnits: 1}}, - 'One or more parameter values were invalid: Duplicate index name: abc', done) - }) - - it('should return ValidationException for extraneous values in LocalSecondaryIndexes', function(done) { - assertValidation({TableName: 'abc', - AttributeDefinitions: [{AttributeName: 'a', AttributeType: 'S'}, {AttributeName: 'b', AttributeType: 'S'}], - KeySchema: [{KeyType: 'HASH', AttributeName: 'a'}, {KeyType: 'RANGE', AttributeName: 'b'}], - LocalSecondaryIndexes: [{ + KeySchema: [ { AttributeName: 'a', KeyType: 'HASH' }, { AttributeName: 'b', KeyType: 'RANGE' } ], + Projection: { ProjectionType: 'ALL' }, + } ], + ProvisionedThroughput: { ReadCapacityUnits: 1, WriteCapacityUnits: 1 } }, + 'One or more parameter values were invalid: Duplicate index name: abc', done) + }) + + it('should return ValidationException for extraneous values in LocalSecondaryIndexes', function (done) { + assertValidation({ TableName: 'abc', + AttributeDefinitions: [ { AttributeName: 'a', AttributeType: 'S' }, { AttributeName: 'b', AttributeType: 'S' } ], + KeySchema: [ { KeyType: 'HASH', AttributeName: 'a' }, { KeyType: 'RANGE', AttributeName: 'b' } ], + LocalSecondaryIndexes: [ { IndexName: 'abc', - KeySchema: [{AttributeName: 'a', KeyType: 'HASH'}, {AttributeName: 'b', KeyType: 'RANGE'}], - Projection: {ProjectionType: 'ALL'}, + KeySchema: [ { AttributeName: 'a', KeyType: 'HASH' }, { AttributeName: 'b', KeyType: 'RANGE' } ], + Projection: { ProjectionType: 'ALL' }, }, { IndexName: 'abd', - KeySchema: [{AttributeName: 'a', KeyType: 'HASH'}, {AttributeName: 'b', KeyType: 'RANGE'}], - Projection: {ProjectionType: 'ALL'}, + KeySchema: [ { AttributeName: 'a', KeyType: 'HASH' }, { AttributeName: 'b', KeyType: 'RANGE' } ], + Projection: { ProjectionType: 'ALL' }, }, { IndexName: 'abe', - KeySchema: [{AttributeName: 'a', KeyType: 'HASH'}, {AttributeName: 'b', KeyType: 'RANGE'}], - Projection: {ProjectionType: 'ALL'}, + KeySchema: [ { AttributeName: 'a', KeyType: 'HASH' }, { AttributeName: 'b', KeyType: 'RANGE' } ], + Projection: { ProjectionType: 'ALL' }, }, { IndexName: 'abf', - KeySchema: [{AttributeName: 'a', KeyType: 'HASH'}, {AttributeName: 'b', KeyType: 'RANGE'}], - Projection: {ProjectionType: 'ALL'}, + KeySchema: [ { AttributeName: 'a', KeyType: 'HASH' }, { AttributeName: 'b', KeyType: 'RANGE' } ], + Projection: { ProjectionType: 'ALL' }, }, { IndexName: 'abg', - KeySchema: [{AttributeName: 'a', KeyType: 'HASH'}, {AttributeName: 'b', KeyType: 'RANGE'}], - Projection: {ProjectionType: 'ALL'}, + KeySchema: [ { AttributeName: 'a', KeyType: 'HASH' }, { AttributeName: 'b', KeyType: 'RANGE' } ], + Projection: { ProjectionType: 'ALL' }, }, { IndexName: 'abh', - KeySchema: [{AttributeName: 'a', KeyType: 'HASH'}, {AttributeName: 'b', KeyType: 'RANGE'}], - Projection: {ProjectionType: 'ALL'}, - }, {}], - ProvisionedThroughput: {ReadCapacityUnits: 1, WriteCapacityUnits: 1}}, [ - 'Value null at \'localSecondaryIndexes.7.member.projection\' failed to satisfy constraint: ' + + KeySchema: [ { AttributeName: 'a', KeyType: 'HASH' }, { AttributeName: 'b', KeyType: 'RANGE' } ], + Projection: { ProjectionType: 'ALL' }, + }, {} ], + ProvisionedThroughput: { ReadCapacityUnits: 1, WriteCapacityUnits: 1 } }, [ + 'Value null at \'localSecondaryIndexes.7.member.projection\' failed to satisfy constraint: ' + 'Member must not be null', - 'Value null at \'localSecondaryIndexes.7.member.indexName\' failed to satisfy constraint: ' + + 'Value null at \'localSecondaryIndexes.7.member.indexName\' failed to satisfy constraint: ' + 'Member must not be null', - 'Value null at \'localSecondaryIndexes.7.member.keySchema\' failed to satisfy constraint: ' + + 'Value null at \'localSecondaryIndexes.7.member.keySchema\' failed to satisfy constraint: ' + 'Member must not be null', - ], done) + ], done) }) - it('should return ValidationException for more than five valid LocalSecondaryIndexes', function(done) { - assertValidation({TableName: 'abc', - AttributeDefinitions: [{AttributeName: 'a', AttributeType: 'S'}, {AttributeName: 'b', AttributeType: 'S'}], - KeySchema: [{KeyType: 'HASH', AttributeName: 'a'}, {KeyType: 'RANGE', AttributeName: 'b'}], - LocalSecondaryIndexes: [{ + it('should return ValidationException for more than five valid LocalSecondaryIndexes', function (done) { + assertValidation({ TableName: 'abc', + AttributeDefinitions: [ { AttributeName: 'a', AttributeType: 'S' }, { AttributeName: 'b', AttributeType: 'S' } ], + KeySchema: [ { KeyType: 'HASH', AttributeName: 'a' }, { KeyType: 'RANGE', AttributeName: 'b' } ], + LocalSecondaryIndexes: [ { IndexName: 'abc', - KeySchema: [{AttributeName: 'a', KeyType: 'HASH'}, {AttributeName: 'b', KeyType: 'RANGE'}], - Projection: {ProjectionType: 'ALL'}, + KeySchema: [ { AttributeName: 'a', KeyType: 'HASH' }, { AttributeName: 'b', KeyType: 'RANGE' } ], + Projection: { ProjectionType: 'ALL' }, }, { IndexName: 'abd', - KeySchema: [{AttributeName: 'a', KeyType: 'HASH'}, {AttributeName: 'b', KeyType: 'RANGE'}], - Projection: {ProjectionType: 'ALL'}, + KeySchema: [ { AttributeName: 'a', KeyType: 'HASH' }, { AttributeName: 'b', KeyType: 'RANGE' } ], + Projection: { ProjectionType: 'ALL' }, }, { IndexName: 'abe', - KeySchema: [{AttributeName: 'a', KeyType: 'HASH'}, {AttributeName: 'b', KeyType: 'RANGE'}], - Projection: {ProjectionType: 'ALL'}, + KeySchema: [ { AttributeName: 'a', KeyType: 'HASH' }, { AttributeName: 'b', KeyType: 'RANGE' } ], + Projection: { ProjectionType: 'ALL' }, }, { IndexName: 'abf', - KeySchema: [{AttributeName: 'a', KeyType: 'HASH'}, {AttributeName: 'b', KeyType: 'RANGE'}], - Projection: {ProjectionType: 'ALL'}, + KeySchema: [ { AttributeName: 'a', KeyType: 'HASH' }, { AttributeName: 'b', KeyType: 'RANGE' } ], + Projection: { ProjectionType: 'ALL' }, }, { IndexName: 'abg', - KeySchema: [{AttributeName: 'a', KeyType: 'HASH'}, {AttributeName: 'b', KeyType: 'RANGE'}], - Projection: {ProjectionType: 'ALL'}, + KeySchema: [ { AttributeName: 'a', KeyType: 'HASH' }, { AttributeName: 'b', KeyType: 'RANGE' } ], + Projection: { ProjectionType: 'ALL' }, }, { IndexName: 'abh', - KeySchema: [{AttributeName: 'a', KeyType: 'HASH'}, {AttributeName: 'b', KeyType: 'RANGE'}], - Projection: {ProjectionType: 'ALL'}, - }], - ProvisionedThroughput: {ReadCapacityUnits: 1, WriteCapacityUnits: 1}}, - 'One or more parameter values were invalid: Number of LocalSecondaryIndexes exceeds per-table limit of 5', done) + KeySchema: [ { AttributeName: 'a', KeyType: 'HASH' }, { AttributeName: 'b', KeyType: 'RANGE' } ], + Projection: { ProjectionType: 'ALL' }, + } ], + ProvisionedThroughput: { ReadCapacityUnits: 1, WriteCapacityUnits: 1 } }, + 'One or more parameter values were invalid: Number of LocalSecondaryIndexes exceeds per-table limit of 5', done) }) - it('should return ValidationException for empty GlobalSecondaryIndexes list', function(done) { - assertValidation({TableName: 'abc', - AttributeDefinitions: [{AttributeName: 'a', AttributeType: 'S'}, {AttributeName: 'b', AttributeType: 'S'}], - KeySchema: [{KeyType: 'HASH', AttributeName: 'a'}], + it('should return ValidationException for empty GlobalSecondaryIndexes list', function (done) { + assertValidation({ TableName: 'abc', + AttributeDefinitions: [ { AttributeName: 'a', AttributeType: 'S' }, { AttributeName: 'b', AttributeType: 'S' } ], + KeySchema: [ { KeyType: 'HASH', AttributeName: 'a' } ], GlobalSecondaryIndexes: [], - ProvisionedThroughput: {ReadCapacityUnits: 1, WriteCapacityUnits: 1}}, - 'One or more parameter values were invalid: List of GlobalSecondaryIndexes is empty', done) + ProvisionedThroughput: { ReadCapacityUnits: 1, WriteCapacityUnits: 1 } }, + 'One or more parameter values were invalid: List of GlobalSecondaryIndexes is empty', done) }) - it('should return ValidationException for more than five empty GlobalSecondaryIndexes', function(done) { - assertValidation({TableName: 'abc', - AttributeDefinitions: [{AttributeName: 'a', AttributeType: 'S'}, {AttributeName: 'b', AttributeType: 'S'}], - KeySchema: [{KeyType: 'HASH', AttributeName: 'a'}, {KeyType: 'RANGE', AttributeName: 'b'}], - GlobalSecondaryIndexes: [{}, {}, {}, {}, {}, {}, {}, {}, {}], - ProvisionedThroughput: {ReadCapacityUnits: 1, WriteCapacityUnits: 1}}, [ - 'Value null at \'globalSecondaryIndexes.1.member.keySchema\' failed to satisfy constraint: ' + + it('should return ValidationException for more than five empty GlobalSecondaryIndexes', function (done) { + assertValidation({ TableName: 'abc', + AttributeDefinitions: [ { AttributeName: 'a', AttributeType: 'S' }, { AttributeName: 'b', AttributeType: 'S' } ], + KeySchema: [ { KeyType: 'HASH', AttributeName: 'a' }, { KeyType: 'RANGE', AttributeName: 'b' } ], + GlobalSecondaryIndexes: [ {}, {}, {}, {}, {}, {}, {}, {}, {} ], + ProvisionedThroughput: { ReadCapacityUnits: 1, WriteCapacityUnits: 1 } }, [ + 'Value null at \'globalSecondaryIndexes.1.member.keySchema\' failed to satisfy constraint: ' + 'Member must not be null', - 'Value null at \'globalSecondaryIndexes.1.member.projection\' failed to satisfy constraint: ' + + 'Value null at \'globalSecondaryIndexes.1.member.projection\' failed to satisfy constraint: ' + 'Member must not be null', - 'Value null at \'globalSecondaryIndexes.1.member.indexName\' failed to satisfy constraint: ' + + 'Value null at \'globalSecondaryIndexes.1.member.indexName\' failed to satisfy constraint: ' + 'Member must not be null', - 'Value null at \'globalSecondaryIndexes.2.member.keySchema\' failed to satisfy constraint: ' + + 'Value null at \'globalSecondaryIndexes.2.member.keySchema\' failed to satisfy constraint: ' + 'Member must not be null', - 'Value null at \'globalSecondaryIndexes.2.member.projection\' failed to satisfy constraint: ' + + 'Value null at \'globalSecondaryIndexes.2.member.projection\' failed to satisfy constraint: ' + 'Member must not be null', - 'Value null at \'globalSecondaryIndexes.2.member.indexName\' failed to satisfy constraint: ' + + 'Value null at \'globalSecondaryIndexes.2.member.indexName\' failed to satisfy constraint: ' + 'Member must not be null', - 'Value null at \'globalSecondaryIndexes.3.member.keySchema\' failed to satisfy constraint: ' + + 'Value null at \'globalSecondaryIndexes.3.member.keySchema\' failed to satisfy constraint: ' + 'Member must not be null', - 'Value null at \'globalSecondaryIndexes.3.member.projection\' failed to satisfy constraint: ' + + 'Value null at \'globalSecondaryIndexes.3.member.projection\' failed to satisfy constraint: ' + 'Member must not be null', - 'Value null at \'globalSecondaryIndexes.3.member.indexName\' failed to satisfy constraint: ' + + 'Value null at \'globalSecondaryIndexes.3.member.indexName\' failed to satisfy constraint: ' + 'Member must not be null', - 'Value null at \'globalSecondaryIndexes.4.member.indexName\' failed to satisfy constraint: ' + + 'Value null at \'globalSecondaryIndexes.4.member.indexName\' failed to satisfy constraint: ' + 'Member must not be null', - ], done) + ], done) }) - it('should return ValidationException for bad GlobalSecondaryIndex names', function(done) { + it('should return ValidationException for bad GlobalSecondaryIndex names', function (done) { var name = new Array(256 + 1).join('a') - assertValidation({TableName: 'abc', - AttributeDefinitions: [{AttributeName: 'a', AttributeType: 'S'}, {AttributeName: 'b', AttributeType: 'S'}], - KeySchema: [{KeyType: 'HASH', AttributeName: 'a'}], - GlobalSecondaryIndexes: [{ - IndexName: 'h;', KeySchema: [], Projection: {}, ProvisionedThroughput: {ReadCapacityUnits: 0, WriteCapacityUnits: 0}, + assertValidation({ TableName: 'abc', + AttributeDefinitions: [ { AttributeName: 'a', AttributeType: 'S' }, { AttributeName: 'b', AttributeType: 'S' } ], + KeySchema: [ { KeyType: 'HASH', AttributeName: 'a' } ], + GlobalSecondaryIndexes: [ { + IndexName: 'h;', KeySchema: [], Projection: {}, ProvisionedThroughput: { ReadCapacityUnits: 0, WriteCapacityUnits: 0 }, }, { - IndexName: name, KeySchema: [{AttributeName: 'a', KeyType: 'HASH'}], Projection: {}, ProvisionedThroughput: {}, - }], - ProvisionedThroughput: {ReadCapacityUnits: 1, WriteCapacityUnits: 1}}, [ - 'Value \'h;\' at \'globalSecondaryIndexes.1.member.indexName\' failed to satisfy constraint: ' + + IndexName: name, KeySchema: [ { AttributeName: 'a', KeyType: 'HASH' } ], Projection: {}, ProvisionedThroughput: {}, + } ], + ProvisionedThroughput: { ReadCapacityUnits: 1, WriteCapacityUnits: 1 } }, [ + 'Value \'h;\' at \'globalSecondaryIndexes.1.member.indexName\' failed to satisfy constraint: ' + 'Member must satisfy regular expression pattern: [a-zA-Z0-9_.-]+', - 'Value \'h;\' at \'globalSecondaryIndexes.1.member.indexName\' failed to satisfy constraint: ' + + 'Value \'h;\' at \'globalSecondaryIndexes.1.member.indexName\' failed to satisfy constraint: ' + 'Member must have length greater than or equal to 3', - 'Value \'0\' at \'globalSecondaryIndexes.1.member.provisionedThroughput.writeCapacityUnits\' failed to satisfy constraint: ' + + 'Value \'0\' at \'globalSecondaryIndexes.1.member.provisionedThroughput.writeCapacityUnits\' failed to satisfy constraint: ' + 'Member must have value greater than or equal to 1', - 'Value \'0\' at \'globalSecondaryIndexes.1.member.provisionedThroughput.readCapacityUnits\' failed to satisfy constraint: ' + + 'Value \'0\' at \'globalSecondaryIndexes.1.member.provisionedThroughput.readCapacityUnits\' failed to satisfy constraint: ' + 'Member must have value greater than or equal to 1', - 'Value \'[]\' at \'globalSecondaryIndexes.1.member.keySchema\' failed to satisfy constraint: ' + + 'Value \'[]\' at \'globalSecondaryIndexes.1.member.keySchema\' failed to satisfy constraint: ' + 'Member must have length greater than or equal to 1', - 'Value \'' + name + '\' at \'globalSecondaryIndexes.2.member.indexName\' failed to satisfy constraint: ' + + 'Value \'' + name + '\' at \'globalSecondaryIndexes.2.member.indexName\' failed to satisfy constraint: ' + 'Member must have length less than or equal to 255', - 'Value null at \'globalSecondaryIndexes.2.member.provisionedThroughput.writeCapacityUnits\' failed to satisfy constraint: ' + + 'Value null at \'globalSecondaryIndexes.2.member.provisionedThroughput.writeCapacityUnits\' failed to satisfy constraint: ' + 'Member must not be null', - 'Value null at \'globalSecondaryIndexes.2.member.provisionedThroughput.readCapacityUnits\' failed to satisfy constraint: ' + + 'Value null at \'globalSecondaryIndexes.2.member.provisionedThroughput.readCapacityUnits\' failed to satisfy constraint: ' + 'Member must not be null', - ], done) + ], done) }) - it('should return ValidationException for missing attribute definition with only range key with GlobalSecondaryIndex', function(done) { - assertValidation({TableName: 'abc', - AttributeDefinitions: [{AttributeName: 'a', AttributeType: 'S'}, {AttributeName: 'b', AttributeType: 'S'}], - KeySchema: [{KeyType: 'HASH', AttributeName: 'a'}], - GlobalSecondaryIndexes: [{IndexName: 'abc', KeySchema: [{AttributeName: 'c', KeyType: 'RANGE'}], Projection: {}, ProvisionedThroughput: {ReadCapacityUnits: 1, WriteCapacityUnits: 1}}], - ProvisionedThroughput: {ReadCapacityUnits: 1, WriteCapacityUnits: 1}}, - new RegExp('One or more parameter values were invalid: ' + + it('should return ValidationException for missing attribute definition with only range key with GlobalSecondaryIndex', function (done) { + assertValidation({ TableName: 'abc', + AttributeDefinitions: [ { AttributeName: 'a', AttributeType: 'S' }, { AttributeName: 'b', AttributeType: 'S' } ], + KeySchema: [ { KeyType: 'HASH', AttributeName: 'a' } ], + GlobalSecondaryIndexes: [ { IndexName: 'abc', KeySchema: [ { AttributeName: 'c', KeyType: 'RANGE' } ], Projection: {}, ProvisionedThroughput: { ReadCapacityUnits: 1, WriteCapacityUnits: 1 } } ], + ProvisionedThroughput: { ReadCapacityUnits: 1, WriteCapacityUnits: 1 } }, + new RegExp('One or more parameter values were invalid: ' + 'Some index key attributes are not defined in AttributeDefinitions. ' + 'Keys: \\[c\\], AttributeDefinitions: \\[(a, b|b, a)\\]'), done) }) - it('should return ValidationException for missing attribute definitions in GlobalSecondaryIndex', function(done) { - assertValidation({TableName: 'abc', - AttributeDefinitions: [{AttributeName: 'a', AttributeType: 'S'}, {AttributeName: 'b', AttributeType: 'S'}], - KeySchema: [{KeyType: 'HASH', AttributeName: 'a'}, {KeyType: 'RANGE', AttributeName: 'b'}], - GlobalSecondaryIndexes: [{ + it('should return ValidationException for missing attribute definitions in GlobalSecondaryIndex', function (done) { + assertValidation({ TableName: 'abc', + AttributeDefinitions: [ { AttributeName: 'a', AttributeType: 'S' }, { AttributeName: 'b', AttributeType: 'S' } ], + KeySchema: [ { KeyType: 'HASH', AttributeName: 'a' }, { KeyType: 'RANGE', AttributeName: 'b' } ], + GlobalSecondaryIndexes: [ { IndexName: 'abc', - KeySchema: [{AttributeName: 'c', KeyType: 'RANGE'}, {AttributeName: 'd', KeyType: 'RANGE'}], - ProvisionedThroughput: {ReadCapacityUnits: 1, WriteCapacityUnits: 1}, + KeySchema: [ { AttributeName: 'c', KeyType: 'RANGE' }, { AttributeName: 'd', KeyType: 'RANGE' } ], + ProvisionedThroughput: { ReadCapacityUnits: 1, WriteCapacityUnits: 1 }, Projection: {}, }, { IndexName: 'abc', - KeySchema: [{AttributeName: 'e', KeyType: 'RANGE'}], - ProvisionedThroughput: {ReadCapacityUnits: 1, WriteCapacityUnits: 1}, + KeySchema: [ { AttributeName: 'e', KeyType: 'RANGE' } ], + ProvisionedThroughput: { ReadCapacityUnits: 1, WriteCapacityUnits: 1 }, Projection: {}, - }], - ProvisionedThroughput: {ReadCapacityUnits: 1, WriteCapacityUnits: 1}}, - new RegExp('One or more parameter values were invalid: ' + + } ], + ProvisionedThroughput: { ReadCapacityUnits: 1, WriteCapacityUnits: 1 } }, + new RegExp('One or more parameter values were invalid: ' + 'Some index key attributes are not defined in AttributeDefinitions. ' + 'Keys: \\[(c, d|d, c)\\], AttributeDefinitions: \\[(a, b|b, a)\\]'), done) }) - it('should return ValidationException for first key in GlobalSecondaryIndex not being hash', function(done) { - assertValidation({TableName: 'abc', - AttributeDefinitions: [{AttributeName: 'a', AttributeType: 'S'}, {AttributeName: 'b', AttributeType: 'S'}], - KeySchema: [{KeyType: 'HASH', AttributeName: 'a'}, {KeyType: 'RANGE', AttributeName: 'b'}], - GlobalSecondaryIndexes: [{ + it('should return ValidationException for first key in GlobalSecondaryIndex not being hash', function (done) { + assertValidation({ TableName: 'abc', + AttributeDefinitions: [ { AttributeName: 'a', AttributeType: 'S' }, { AttributeName: 'b', AttributeType: 'S' } ], + KeySchema: [ { KeyType: 'HASH', AttributeName: 'a' }, { KeyType: 'RANGE', AttributeName: 'b' } ], + GlobalSecondaryIndexes: [ { IndexName: 'abc', - KeySchema: [{AttributeName: 'a', KeyType: 'RANGE'}], - ProvisionedThroughput: {ReadCapacityUnits: 1, WriteCapacityUnits: 1}, + KeySchema: [ { AttributeName: 'a', KeyType: 'RANGE' } ], + ProvisionedThroughput: { ReadCapacityUnits: 1, WriteCapacityUnits: 1 }, Projection: {}, - }], - ProvisionedThroughput: {ReadCapacityUnits: 1, WriteCapacityUnits: 1}}, - 'Invalid KeySchema: The first KeySchemaElement is not a HASH key type', done) + } ], + ProvisionedThroughput: { ReadCapacityUnits: 1, WriteCapacityUnits: 1 } }, + 'Invalid KeySchema: The first KeySchemaElement is not a HASH key type', done) }) - it('should return ValidationException for same names of keys in GlobalSecondaryIndex', function(done) { - assertValidation({TableName: 'abc', - AttributeDefinitions: [{AttributeName: 'a', AttributeType: 'S'}, {AttributeName: 'b', AttributeType: 'S'}], - KeySchema: [{KeyType: 'HASH', AttributeName: 'a'}, {KeyType: 'RANGE', AttributeName: 'b'}], - GlobalSecondaryIndexes: [{ + it('should return ValidationException for same names of keys in GlobalSecondaryIndex', function (done) { + assertValidation({ TableName: 'abc', + AttributeDefinitions: [ { AttributeName: 'a', AttributeType: 'S' }, { AttributeName: 'b', AttributeType: 'S' } ], + KeySchema: [ { KeyType: 'HASH', AttributeName: 'a' }, { KeyType: 'RANGE', AttributeName: 'b' } ], + GlobalSecondaryIndexes: [ { IndexName: 'abc', - KeySchema: [{AttributeName: 'a', KeyType: 'HASH'}, {AttributeName: 'a', KeyType: 'HASH'}], - ProvisionedThroughput: {ReadCapacityUnits: 1, WriteCapacityUnits: 1}, + KeySchema: [ { AttributeName: 'a', KeyType: 'HASH' }, { AttributeName: 'a', KeyType: 'HASH' } ], + ProvisionedThroughput: { ReadCapacityUnits: 1, WriteCapacityUnits: 1 }, Projection: {}, - }], - ProvisionedThroughput: {ReadCapacityUnits: 1, WriteCapacityUnits: 1}}, - 'Both the Hash Key and the Range Key element in the KeySchema have the same name', done) + } ], + ProvisionedThroughput: { ReadCapacityUnits: 1, WriteCapacityUnits: 1 } }, + 'Both the Hash Key and the Range Key element in the KeySchema have the same name', done) }) - it('should return ValidationException for second key of GlobalSecondaryIndex not being range', function(done) { - assertValidation({TableName: 'abc', - AttributeDefinitions: [{AttributeName: 'a', AttributeType: 'S'}, {AttributeName: 'b', AttributeType: 'S'}], - KeySchema: [{KeyType: 'HASH', AttributeName: 'a'}, {KeyType: 'RANGE', AttributeName: 'b'}], - GlobalSecondaryIndexes: [{ + it('should return ValidationException for second key of GlobalSecondaryIndex not being range', function (done) { + assertValidation({ TableName: 'abc', + AttributeDefinitions: [ { AttributeName: 'a', AttributeType: 'S' }, { AttributeName: 'b', AttributeType: 'S' } ], + KeySchema: [ { KeyType: 'HASH', AttributeName: 'a' }, { KeyType: 'RANGE', AttributeName: 'b' } ], + GlobalSecondaryIndexes: [ { IndexName: 'abc', - KeySchema: [{AttributeName: 'a', KeyType: 'HASH'}, {AttributeName: 'b', KeyType: 'HASH'}], - ProvisionedThroughput: {ReadCapacityUnits: 1, WriteCapacityUnits: 1}, + KeySchema: [ { AttributeName: 'a', KeyType: 'HASH' }, { AttributeName: 'b', KeyType: 'HASH' } ], + ProvisionedThroughput: { ReadCapacityUnits: 1, WriteCapacityUnits: 1 }, Projection: {}, - }], - ProvisionedThroughput: {ReadCapacityUnits: 1, WriteCapacityUnits: 1}}, - 'Invalid KeySchema: The second KeySchemaElement is not a RANGE key type', done) + } ], + ProvisionedThroughput: { ReadCapacityUnits: 1, WriteCapacityUnits: 1 } }, + 'Invalid KeySchema: The second KeySchemaElement is not a RANGE key type', done) }) - it('should return ValidationException about Projection if no range key in GlobalSecondaryIndex', function(done) { - assertValidation({TableName: 'abc', - AttributeDefinitions: [{AttributeName: 'a', AttributeType: 'S'}, {AttributeName: 'b', AttributeType: 'S'}], - KeySchema: [{KeyType: 'HASH', AttributeName: 'a'}, {KeyType: 'RANGE', AttributeName: 'b'}], - GlobalSecondaryIndexes: [{ + it('should return ValidationException about Projection if no range key in GlobalSecondaryIndex', function (done) { + assertValidation({ TableName: 'abc', + AttributeDefinitions: [ { AttributeName: 'a', AttributeType: 'S' }, { AttributeName: 'b', AttributeType: 'S' } ], + KeySchema: [ { KeyType: 'HASH', AttributeName: 'a' }, { KeyType: 'RANGE', AttributeName: 'b' } ], + GlobalSecondaryIndexes: [ { IndexName: 'abc', - KeySchema: [{AttributeName: 'b', KeyType: 'HASH'}], - ProvisionedThroughput: {ReadCapacityUnits: 1, WriteCapacityUnits: 1}, + KeySchema: [ { AttributeName: 'b', KeyType: 'HASH' } ], + ProvisionedThroughput: { ReadCapacityUnits: 1, WriteCapacityUnits: 1 }, Projection: {}, - }], - ProvisionedThroughput: {ReadCapacityUnits: 1, WriteCapacityUnits: 1}}, - 'One or more parameter values were invalid: Unknown ProjectionType: null', done) + } ], + ProvisionedThroughput: { ReadCapacityUnits: 1, WriteCapacityUnits: 1 } }, + 'One or more parameter values were invalid: Unknown ProjectionType: null', done) }) - it('should return ValidationException about Projection for different hash key between GlobalSecondaryIndex and table', function(done) { - assertValidation({TableName: 'abc', - AttributeDefinitions: [{AttributeName: 'a', AttributeType: 'S'}, {AttributeName: 'b', AttributeType: 'S'}], - KeySchema: [{KeyType: 'HASH', AttributeName: 'a'}, {KeyType: 'RANGE', AttributeName: 'b'}], - GlobalSecondaryIndexes: [{ + it('should return ValidationException about Projection for different hash key between GlobalSecondaryIndex and table', function (done) { + assertValidation({ TableName: 'abc', + AttributeDefinitions: [ { AttributeName: 'a', AttributeType: 'S' }, { AttributeName: 'b', AttributeType: 'S' } ], + KeySchema: [ { KeyType: 'HASH', AttributeName: 'a' }, { KeyType: 'RANGE', AttributeName: 'b' } ], + GlobalSecondaryIndexes: [ { IndexName: 'abc', - KeySchema: [{AttributeName: 'b', KeyType: 'HASH'}, {AttributeName: 'a', KeyType: 'RANGE'}], - ProvisionedThroughput: {ReadCapacityUnits: 1, WriteCapacityUnits: 1}, + KeySchema: [ { AttributeName: 'b', KeyType: 'HASH' }, { AttributeName: 'a', KeyType: 'RANGE' } ], + ProvisionedThroughput: { ReadCapacityUnits: 1, WriteCapacityUnits: 1 }, Projection: {}, - }], - ProvisionedThroughput: {ReadCapacityUnits: 1, WriteCapacityUnits: 1}}, - 'One or more parameter values were invalid: Unknown ProjectionType: null', done) + } ], + ProvisionedThroughput: { ReadCapacityUnits: 1, WriteCapacityUnits: 1 } }, + 'One or more parameter values were invalid: Unknown ProjectionType: null', done) }) - it('should return ValidationException for same named keys in GlobalSecondaryIndex when one hash and one range', function(done) { - assertValidation({TableName: 'abc', - AttributeDefinitions: [{AttributeName: 'a', AttributeType: 'S'}, {AttributeName: 'b', AttributeType: 'S'}], - KeySchema: [{KeyType: 'HASH', AttributeName: 'a'}, {KeyType: 'RANGE', AttributeName: 'b'}], - GlobalSecondaryIndexes: [{ + it('should return ValidationException for same named keys in GlobalSecondaryIndex when one hash and one range', function (done) { + assertValidation({ TableName: 'abc', + AttributeDefinitions: [ { AttributeName: 'a', AttributeType: 'S' }, { AttributeName: 'b', AttributeType: 'S' } ], + KeySchema: [ { KeyType: 'HASH', AttributeName: 'a' }, { KeyType: 'RANGE', AttributeName: 'b' } ], + GlobalSecondaryIndexes: [ { IndexName: 'abc', - KeySchema: [{AttributeName: 'a', KeyType: 'HASH'}, {AttributeName: 'a', KeyType: 'RANGE'}], - ProvisionedThroughput: {ReadCapacityUnits: 1, WriteCapacityUnits: 1}, + KeySchema: [ { AttributeName: 'a', KeyType: 'HASH' }, { AttributeName: 'a', KeyType: 'RANGE' } ], + ProvisionedThroughput: { ReadCapacityUnits: 1, WriteCapacityUnits: 1 }, Projection: {}, - }], - ProvisionedThroughput: {ReadCapacityUnits: 1, WriteCapacityUnits: 1}}, - 'Both the Hash Key and the Range Key element in the KeySchema have the same name', done) + } ], + ProvisionedThroughput: { ReadCapacityUnits: 1, WriteCapacityUnits: 1 } }, + 'Both the Hash Key and the Range Key element in the KeySchema have the same name', done) }) - it('should return ValidationException for missing attribute definitions when hash is same in GlobalSecondaryIndex', function(done) { - assertValidation({TableName: 'abc', - AttributeDefinitions: [{AttributeName: 'a', AttributeType: 'S'}, {AttributeName: 'b', AttributeType: 'S'}], - KeySchema: [{KeyType: 'HASH', AttributeName: 'a'}, {KeyType: 'RANGE', AttributeName: 'b'}], - GlobalSecondaryIndexes: [{ + it('should return ValidationException for missing attribute definitions when hash is same in GlobalSecondaryIndex', function (done) { + assertValidation({ TableName: 'abc', + AttributeDefinitions: [ { AttributeName: 'a', AttributeType: 'S' }, { AttributeName: 'b', AttributeType: 'S' } ], + KeySchema: [ { KeyType: 'HASH', AttributeName: 'a' }, { KeyType: 'RANGE', AttributeName: 'b' } ], + GlobalSecondaryIndexes: [ { IndexName: 'abc', - KeySchema: [{AttributeName: 'a', KeyType: 'HASH'}, {AttributeName: 'c', KeyType: 'RANGE'}], - ProvisionedThroughput: {ReadCapacityUnits: 1, WriteCapacityUnits: 1}, + KeySchema: [ { AttributeName: 'a', KeyType: 'HASH' }, { AttributeName: 'c', KeyType: 'RANGE' } ], + ProvisionedThroughput: { ReadCapacityUnits: 1, WriteCapacityUnits: 1 }, Projection: {}, - }], - ProvisionedThroughput: {ReadCapacityUnits: 1, WriteCapacityUnits: 1}}, - new RegExp('One or more parameter values were invalid: ' + + } ], + ProvisionedThroughput: { ReadCapacityUnits: 1, WriteCapacityUnits: 1 } }, + new RegExp('One or more parameter values were invalid: ' + 'Some index key attributes are not defined in AttributeDefinitions. ' + 'Keys: \\[(a, c|c, a)\\], AttributeDefinitions: \\[(a, b|b, a)\\]'), done) }) - it('should return ValidationException for empty Projection in GlobalSecondaryIndex', function(done) { - assertValidation({TableName: 'abc', - AttributeDefinitions: [{AttributeName: 'a', AttributeType: 'S'}, {AttributeName: 'b', AttributeType: 'S'}], - KeySchema: [{KeyType: 'HASH', AttributeName: 'a'}, {KeyType: 'RANGE', AttributeName: 'b'}], - GlobalSecondaryIndexes: [{ + it('should return ValidationException for empty Projection in GlobalSecondaryIndex', function (done) { + assertValidation({ TableName: 'abc', + AttributeDefinitions: [ { AttributeName: 'a', AttributeType: 'S' }, { AttributeName: 'b', AttributeType: 'S' } ], + KeySchema: [ { KeyType: 'HASH', AttributeName: 'a' }, { KeyType: 'RANGE', AttributeName: 'b' } ], + GlobalSecondaryIndexes: [ { IndexName: 'abc', - KeySchema: [{AttributeName: 'a', KeyType: 'HASH'}, {AttributeName: 'b', KeyType: 'RANGE'}], - ProvisionedThroughput: {ReadCapacityUnits: 1, WriteCapacityUnits: 1}, + KeySchema: [ { AttributeName: 'a', KeyType: 'HASH' }, { AttributeName: 'b', KeyType: 'RANGE' } ], + ProvisionedThroughput: { ReadCapacityUnits: 1, WriteCapacityUnits: 1 }, Projection: {}, - }], - ProvisionedThroughput: {ReadCapacityUnits: 1, WriteCapacityUnits: 1}}, - 'One or more parameter values were invalid: Unknown ProjectionType: null', done) + } ], + ProvisionedThroughput: { ReadCapacityUnits: 1, WriteCapacityUnits: 1 } }, + 'One or more parameter values were invalid: Unknown ProjectionType: null', done) }) - it('should return ValidationException for invalid properties in GlobalSecondaryIndex', function(done) { - assertValidation({TableName: 'abc', - AttributeDefinitions: [{AttributeName: 'a', AttributeType: 'S'}, {AttributeName: 'b', AttributeType: 'S'}], - KeySchema: [{KeyType: 'HASH', AttributeName: 'a'}, {KeyType: 'RANGE', AttributeName: 'b'}], - GlobalSecondaryIndexes: [{ + it('should return ValidationException for invalid properties in GlobalSecondaryIndex', function (done) { + assertValidation({ TableName: 'abc', + AttributeDefinitions: [ { AttributeName: 'a', AttributeType: 'S' }, { AttributeName: 'b', AttributeType: 'S' } ], + KeySchema: [ { KeyType: 'HASH', AttributeName: 'a' }, { KeyType: 'RANGE', AttributeName: 'b' } ], + GlobalSecondaryIndexes: [ { IndexName: 'abc', - KeySchema: [{AttributeName: 'a', KeyType: 'HASH'}, {AttributeName: 'b', KeyType: 'RANGE'}], - ProvisionedThroughput: {ReadCapacityUnits: 1, WriteCapacityUnits: 1}, - Projection: {NonKeyAttributes: [], ProjectionType: 'abc'}, - }], - ProvisionedThroughput: {ReadCapacityUnits: 1, WriteCapacityUnits: 1}}, [ - 'Value \'abc\' at \'globalSecondaryIndexes.1.member.projection.projectionType\' failed to satisfy constraint: ' + + KeySchema: [ { AttributeName: 'a', KeyType: 'HASH' }, { AttributeName: 'b', KeyType: 'RANGE' } ], + ProvisionedThroughput: { ReadCapacityUnits: 1, WriteCapacityUnits: 1 }, + Projection: { NonKeyAttributes: [], ProjectionType: 'abc' }, + } ], + ProvisionedThroughput: { ReadCapacityUnits: 1, WriteCapacityUnits: 1 } }, [ + 'Value \'abc\' at \'globalSecondaryIndexes.1.member.projection.projectionType\' failed to satisfy constraint: ' + 'Member must satisfy enum value set: [ALL, INCLUDE, KEYS_ONLY]', - 'Value \'[]\' at \'globalSecondaryIndexes.1.member.projection.nonKeyAttributes\' failed to satisfy constraint: ' + + 'Value \'[]\' at \'globalSecondaryIndexes.1.member.projection.nonKeyAttributes\' failed to satisfy constraint: ' + 'Member must have length greater than or equal to 1', - ], done) + ], done) }) - it('should return ValidationException for missing ProjectionType in GlobalSecondaryIndex', function(done) { - assertValidation({TableName: 'abc', - AttributeDefinitions: [{AttributeName: 'a', AttributeType: 'S'}, {AttributeName: 'b', AttributeType: 'S'}], - KeySchema: [{KeyType: 'HASH', AttributeName: 'a'}, {KeyType: 'RANGE', AttributeName: 'b'}], - GlobalSecondaryIndexes: [{ + it('should return ValidationException for missing ProjectionType in GlobalSecondaryIndex', function (done) { + assertValidation({ TableName: 'abc', + AttributeDefinitions: [ { AttributeName: 'a', AttributeType: 'S' }, { AttributeName: 'b', AttributeType: 'S' } ], + KeySchema: [ { KeyType: 'HASH', AttributeName: 'a' }, { KeyType: 'RANGE', AttributeName: 'b' } ], + GlobalSecondaryIndexes: [ { IndexName: 'abc', - KeySchema: [{AttributeName: 'a', KeyType: 'HASH'}, {AttributeName: 'b', KeyType: 'RANGE'}], - ProvisionedThroughput: {ReadCapacityUnits: 1, WriteCapacityUnits: 1}, - Projection: {NonKeyAttributes: ['a']}, - }], - ProvisionedThroughput: {ReadCapacityUnits: 1, WriteCapacityUnits: 1}}, - 'One or more parameter values were invalid: Unknown ProjectionType: null', done) - }) - - it('should return ValidationException for NonKeyAttributes with ProjectionType ALL in GlobalSecondaryIndex', function(done) { - assertValidation({TableName: 'abc', - AttributeDefinitions: [{AttributeName: 'a', AttributeType: 'S'}, {AttributeName: 'b', AttributeType: 'S'}], - KeySchema: [{KeyType: 'HASH', AttributeName: 'a'}, {KeyType: 'RANGE', AttributeName: 'b'}], - GlobalSecondaryIndexes: [{ + KeySchema: [ { AttributeName: 'a', KeyType: 'HASH' }, { AttributeName: 'b', KeyType: 'RANGE' } ], + ProvisionedThroughput: { ReadCapacityUnits: 1, WriteCapacityUnits: 1 }, + Projection: { NonKeyAttributes: [ 'a' ] }, + } ], + ProvisionedThroughput: { ReadCapacityUnits: 1, WriteCapacityUnits: 1 } }, + 'One or more parameter values were invalid: Unknown ProjectionType: null', done) + }) + + it('should return ValidationException for NonKeyAttributes with ProjectionType ALL in GlobalSecondaryIndex', function (done) { + assertValidation({ TableName: 'abc', + AttributeDefinitions: [ { AttributeName: 'a', AttributeType: 'S' }, { AttributeName: 'b', AttributeType: 'S' } ], + KeySchema: [ { KeyType: 'HASH', AttributeName: 'a' }, { KeyType: 'RANGE', AttributeName: 'b' } ], + GlobalSecondaryIndexes: [ { IndexName: 'abc', - KeySchema: [{AttributeName: 'a', KeyType: 'HASH'}, {AttributeName: 'b', KeyType: 'RANGE'}], - ProvisionedThroughput: {ReadCapacityUnits: 1, WriteCapacityUnits: 1}, - Projection: {ProjectionType: 'ALL', NonKeyAttributes: ['a']}, - }], - ProvisionedThroughput: {ReadCapacityUnits: 1, WriteCapacityUnits: 1}}, - 'One or more parameter values were invalid: ' + + KeySchema: [ { AttributeName: 'a', KeyType: 'HASH' }, { AttributeName: 'b', KeyType: 'RANGE' } ], + ProvisionedThroughput: { ReadCapacityUnits: 1, WriteCapacityUnits: 1 }, + Projection: { ProjectionType: 'ALL', NonKeyAttributes: [ 'a' ] }, + } ], + ProvisionedThroughput: { ReadCapacityUnits: 1, WriteCapacityUnits: 1 } }, + 'One or more parameter values were invalid: ' + 'ProjectionType is ALL, but NonKeyAttributes is specified', done) }) - it('should return ValidationException for NonKeyAttributes with ProjectionType KEYS_ONLY in GlobalSecondaryIndex', function(done) { - assertValidation({TableName: 'abc', - AttributeDefinitions: [{AttributeName: 'a', AttributeType: 'S'}, {AttributeName: 'b', AttributeType: 'S'}], - KeySchema: [{KeyType: 'HASH', AttributeName: 'a'}, {KeyType: 'RANGE', AttributeName: 'b'}], - GlobalSecondaryIndexes: [{ + it('should return ValidationException for NonKeyAttributes with ProjectionType KEYS_ONLY in GlobalSecondaryIndex', function (done) { + assertValidation({ TableName: 'abc', + AttributeDefinitions: [ { AttributeName: 'a', AttributeType: 'S' }, { AttributeName: 'b', AttributeType: 'S' } ], + KeySchema: [ { KeyType: 'HASH', AttributeName: 'a' }, { KeyType: 'RANGE', AttributeName: 'b' } ], + GlobalSecondaryIndexes: [ { IndexName: 'abc', - KeySchema: [{AttributeName: 'a', KeyType: 'HASH'}, {AttributeName: 'b', KeyType: 'RANGE'}], - ProvisionedThroughput: {ReadCapacityUnits: 1, WriteCapacityUnits: 1}, - Projection: {ProjectionType: 'KEYS_ONLY', NonKeyAttributes: ['a']}, - }], - ProvisionedThroughput: {ReadCapacityUnits: 1, WriteCapacityUnits: 1}}, - 'One or more parameter values were invalid: ' + + KeySchema: [ { AttributeName: 'a', KeyType: 'HASH' }, { AttributeName: 'b', KeyType: 'RANGE' } ], + ProvisionedThroughput: { ReadCapacityUnits: 1, WriteCapacityUnits: 1 }, + Projection: { ProjectionType: 'KEYS_ONLY', NonKeyAttributes: [ 'a' ] }, + } ], + ProvisionedThroughput: { ReadCapacityUnits: 1, WriteCapacityUnits: 1 } }, + 'One or more parameter values were invalid: ' + 'ProjectionType is KEYS_ONLY, but NonKeyAttributes is specified', done) }) - it('should return ValidationException for duplicate index names in GlobalSecondaryIndexes', function(done) { - assertValidation({TableName: 'abc', - AttributeDefinitions: [{AttributeName: 'a', AttributeType: 'S'}, {AttributeName: 'b', AttributeType: 'S'}], - KeySchema: [{KeyType: 'HASH', AttributeName: 'a'}, {KeyType: 'RANGE', AttributeName: 'b'}], - GlobalSecondaryIndexes: [{ + it('should return ValidationException for duplicate index names in GlobalSecondaryIndexes', function (done) { + assertValidation({ TableName: 'abc', + AttributeDefinitions: [ { AttributeName: 'a', AttributeType: 'S' }, { AttributeName: 'b', AttributeType: 'S' } ], + KeySchema: [ { KeyType: 'HASH', AttributeName: 'a' }, { KeyType: 'RANGE', AttributeName: 'b' } ], + GlobalSecondaryIndexes: [ { IndexName: 'abc', - KeySchema: [{AttributeName: 'a', KeyType: 'HASH'}, {AttributeName: 'b', KeyType: 'RANGE'}], - ProvisionedThroughput: {ReadCapacityUnits: 1, WriteCapacityUnits: 1}, - Projection: {ProjectionType: 'ALL'}, + KeySchema: [ { AttributeName: 'a', KeyType: 'HASH' }, { AttributeName: 'b', KeyType: 'RANGE' } ], + ProvisionedThroughput: { ReadCapacityUnits: 1, WriteCapacityUnits: 1 }, + Projection: { ProjectionType: 'ALL' }, }, { IndexName: 'abc', - KeySchema: [{AttributeName: 'a', KeyType: 'HASH'}, {AttributeName: 'b', KeyType: 'RANGE'}], - ProvisionedThroughput: {ReadCapacityUnits: 1, WriteCapacityUnits: 1}, - Projection: {ProjectionType: 'ALL'}, - }], - ProvisionedThroughput: {ReadCapacityUnits: 1, WriteCapacityUnits: 1}}, - 'One or more parameter values were invalid: Duplicate index name: abc', done) - }) - - it('should return ValidationException for extraneous values in GlobalSecondaryIndexes', function(done) { - assertValidation({TableName: 'abc', - AttributeDefinitions: [{AttributeName: 'a', AttributeType: 'S'}, {AttributeName: 'b', AttributeType: 'S'}], - KeySchema: [{KeyType: 'HASH', AttributeName: 'a'}, {KeyType: 'RANGE', AttributeName: 'b'}], - GlobalSecondaryIndexes: [{ + KeySchema: [ { AttributeName: 'a', KeyType: 'HASH' }, { AttributeName: 'b', KeyType: 'RANGE' } ], + ProvisionedThroughput: { ReadCapacityUnits: 1, WriteCapacityUnits: 1 }, + Projection: { ProjectionType: 'ALL' }, + } ], + ProvisionedThroughput: { ReadCapacityUnits: 1, WriteCapacityUnits: 1 } }, + 'One or more parameter values were invalid: Duplicate index name: abc', done) + }) + + it('should return ValidationException for extraneous values in GlobalSecondaryIndexes', function (done) { + assertValidation({ TableName: 'abc', + AttributeDefinitions: [ { AttributeName: 'a', AttributeType: 'S' }, { AttributeName: 'b', AttributeType: 'S' } ], + KeySchema: [ { KeyType: 'HASH', AttributeName: 'a' }, { KeyType: 'RANGE', AttributeName: 'b' } ], + GlobalSecondaryIndexes: [ { IndexName: 'abc', - KeySchema: [{AttributeName: 'a', KeyType: 'HASH'}, {AttributeName: 'b', KeyType: 'RANGE'}], - ProvisionedThroughput: {ReadCapacityUnits: 1, WriteCapacityUnits: 1}, - Projection: {ProjectionType: 'ALL'}, + KeySchema: [ { AttributeName: 'a', KeyType: 'HASH' }, { AttributeName: 'b', KeyType: 'RANGE' } ], + ProvisionedThroughput: { ReadCapacityUnits: 1, WriteCapacityUnits: 1 }, + Projection: { ProjectionType: 'ALL' }, }, { IndexName: 'abd', - KeySchema: [{AttributeName: 'a', KeyType: 'HASH'}, {AttributeName: 'b', KeyType: 'RANGE'}], - ProvisionedThroughput: {ReadCapacityUnits: 1, WriteCapacityUnits: 1}, - Projection: {ProjectionType: 'ALL'}, + KeySchema: [ { AttributeName: 'a', KeyType: 'HASH' }, { AttributeName: 'b', KeyType: 'RANGE' } ], + ProvisionedThroughput: { ReadCapacityUnits: 1, WriteCapacityUnits: 1 }, + Projection: { ProjectionType: 'ALL' }, }, { IndexName: 'abe', - KeySchema: [{AttributeName: 'a', KeyType: 'HASH'}, {AttributeName: 'b', KeyType: 'RANGE'}], - ProvisionedThroughput: {ReadCapacityUnits: 1, WriteCapacityUnits: 1}, - Projection: {ProjectionType: 'ALL'}, + KeySchema: [ { AttributeName: 'a', KeyType: 'HASH' }, { AttributeName: 'b', KeyType: 'RANGE' } ], + ProvisionedThroughput: { ReadCapacityUnits: 1, WriteCapacityUnits: 1 }, + Projection: { ProjectionType: 'ALL' }, }, { IndexName: 'abf', - KeySchema: [{AttributeName: 'a', KeyType: 'HASH'}, {AttributeName: 'b', KeyType: 'RANGE'}], - ProvisionedThroughput: {ReadCapacityUnits: 1, WriteCapacityUnits: 1}, - Projection: {ProjectionType: 'ALL'}, + KeySchema: [ { AttributeName: 'a', KeyType: 'HASH' }, { AttributeName: 'b', KeyType: 'RANGE' } ], + ProvisionedThroughput: { ReadCapacityUnits: 1, WriteCapacityUnits: 1 }, + Projection: { ProjectionType: 'ALL' }, }, { IndexName: 'abg', - KeySchema: [{AttributeName: 'a', KeyType: 'HASH'}, {AttributeName: 'b', KeyType: 'RANGE'}], - ProvisionedThroughput: {ReadCapacityUnits: 1, WriteCapacityUnits: 1}, - Projection: {ProjectionType: 'ALL'}, + KeySchema: [ { AttributeName: 'a', KeyType: 'HASH' }, { AttributeName: 'b', KeyType: 'RANGE' } ], + ProvisionedThroughput: { ReadCapacityUnits: 1, WriteCapacityUnits: 1 }, + Projection: { ProjectionType: 'ALL' }, }, { IndexName: 'abh', - KeySchema: [{AttributeName: 'a', KeyType: 'HASH'}, {AttributeName: 'b', KeyType: 'RANGE'}], - ProvisionedThroughput: {ReadCapacityUnits: 1, WriteCapacityUnits: 1}, - Projection: {ProjectionType: 'ALL'}, - }, {}], - ProvisionedThroughput: {ReadCapacityUnits: 1, WriteCapacityUnits: 1}}, [ - 'Value null at \'globalSecondaryIndexes.7.member.projection\' failed to satisfy constraint: ' + + KeySchema: [ { AttributeName: 'a', KeyType: 'HASH' }, { AttributeName: 'b', KeyType: 'RANGE' } ], + ProvisionedThroughput: { ReadCapacityUnits: 1, WriteCapacityUnits: 1 }, + Projection: { ProjectionType: 'ALL' }, + }, {} ], + ProvisionedThroughput: { ReadCapacityUnits: 1, WriteCapacityUnits: 1 } }, [ + 'Value null at \'globalSecondaryIndexes.7.member.projection\' failed to satisfy constraint: ' + 'Member must not be null', - 'Value null at \'globalSecondaryIndexes.7.member.indexName\' failed to satisfy constraint: ' + + 'Value null at \'globalSecondaryIndexes.7.member.indexName\' failed to satisfy constraint: ' + 'Member must not be null', - 'Value null at \'globalSecondaryIndexes.7.member.keySchema\' failed to satisfy constraint: ' + + 'Value null at \'globalSecondaryIndexes.7.member.keySchema\' failed to satisfy constraint: ' + 'Member must not be null', - ], done) + ], done) }) - it('should return ValidationException for more than twenty valid GlobalSecondaryIndexes', function(done) { + it('should return ValidationException for more than twenty valid GlobalSecondaryIndexes', function (done) { var gsis = [] for (var i = 0; i < 21; i++) { gsis.push({ IndexName: 'abc' + i, - KeySchema: [{AttributeName: 'a', KeyType: 'HASH'}, {AttributeName: 'b', KeyType: 'RANGE'}], - ProvisionedThroughput: {ReadCapacityUnits: 1, WriteCapacityUnits: 1}, - Projection: {ProjectionType: 'ALL'}, + KeySchema: [ { AttributeName: 'a', KeyType: 'HASH' }, { AttributeName: 'b', KeyType: 'RANGE' } ], + ProvisionedThroughput: { ReadCapacityUnits: 1, WriteCapacityUnits: 1 }, + Projection: { ProjectionType: 'ALL' }, }) } - assertValidation({TableName: 'abc', - AttributeDefinitions: [{AttributeName: 'a', AttributeType: 'S'}, {AttributeName: 'b', AttributeType: 'S'}], - KeySchema: [{KeyType: 'HASH', AttributeName: 'a'}, {KeyType: 'RANGE', AttributeName: 'b'}], + assertValidation({ TableName: 'abc', + AttributeDefinitions: [ { AttributeName: 'a', AttributeType: 'S' }, { AttributeName: 'b', AttributeType: 'S' } ], + KeySchema: [ { KeyType: 'HASH', AttributeName: 'a' }, { KeyType: 'RANGE', AttributeName: 'b' } ], GlobalSecondaryIndexes: gsis, - ProvisionedThroughput: {ReadCapacityUnits: 1, WriteCapacityUnits: 1}}, - 'One or more parameter values were invalid: GlobalSecondaryIndex count exceeds the per-table limit of 20', done) + ProvisionedThroughput: { ReadCapacityUnits: 1, WriteCapacityUnits: 1 } }, + 'One or more parameter values were invalid: GlobalSecondaryIndex count exceeds the per-table limit of 20', done) }) - it('should return ValidationException for duplicate index names between LocalSecondaryIndexes and GlobalSecondaryIndexes', function(done) { - assertValidation({TableName: 'abc', - AttributeDefinitions: [{AttributeName: 'a', AttributeType: 'S'}, {AttributeName: 'b', AttributeType: 'S'}], - KeySchema: [{KeyType: 'HASH', AttributeName: 'a'}, {KeyType: 'RANGE', AttributeName: 'b'}], - LocalSecondaryIndexes: [{ + it('should return ValidationException for duplicate index names between LocalSecondaryIndexes and GlobalSecondaryIndexes', function (done) { + assertValidation({ TableName: 'abc', + AttributeDefinitions: [ { AttributeName: 'a', AttributeType: 'S' }, { AttributeName: 'b', AttributeType: 'S' } ], + KeySchema: [ { KeyType: 'HASH', AttributeName: 'a' }, { KeyType: 'RANGE', AttributeName: 'b' } ], + LocalSecondaryIndexes: [ { IndexName: 'abc', - KeySchema: [{AttributeName: 'a', KeyType: 'HASH'}, {AttributeName: 'b', KeyType: 'RANGE'}], - Projection: {ProjectionType: 'ALL'}, - }], - GlobalSecondaryIndexes: [{ + KeySchema: [ { AttributeName: 'a', KeyType: 'HASH' }, { AttributeName: 'b', KeyType: 'RANGE' } ], + Projection: { ProjectionType: 'ALL' }, + } ], + GlobalSecondaryIndexes: [ { IndexName: 'abc', - KeySchema: [{AttributeName: 'a', KeyType: 'HASH'}, {AttributeName: 'b', KeyType: 'RANGE'}], - ProvisionedThroughput: {ReadCapacityUnits: 1, WriteCapacityUnits: 1}, - Projection: {ProjectionType: 'ALL'}, - }], - ProvisionedThroughput: {ReadCapacityUnits: 1, WriteCapacityUnits: 1}}, - 'One or more parameter values were invalid: Duplicate index name: abc', done) - }) - - it('should return LimitExceededException for more than one table with LocalSecondaryIndexes at a time', function(done) { - assertValidation({TableName: 'abc', - AttributeDefinitions: [{AttributeName: 'a', AttributeType: 'S'}, {AttributeName: 'b', AttributeType: 'S'}], - KeySchema: [{KeyType: 'HASH', AttributeName: 'a'}, {KeyType: 'RANGE', AttributeName: 'b'}], - LocalSecondaryIndexes: [{ + KeySchema: [ { AttributeName: 'a', KeyType: 'HASH' }, { AttributeName: 'b', KeyType: 'RANGE' } ], + ProvisionedThroughput: { ReadCapacityUnits: 1, WriteCapacityUnits: 1 }, + Projection: { ProjectionType: 'ALL' }, + } ], + ProvisionedThroughput: { ReadCapacityUnits: 1, WriteCapacityUnits: 1 } }, + 'One or more parameter values were invalid: Duplicate index name: abc', done) + }) + + it('should return LimitExceededException for more than one table with LocalSecondaryIndexes at a time', function (done) { + assertValidation({ TableName: 'abc', + AttributeDefinitions: [ { AttributeName: 'a', AttributeType: 'S' }, { AttributeName: 'b', AttributeType: 'S' } ], + KeySchema: [ { KeyType: 'HASH', AttributeName: 'a' }, { KeyType: 'RANGE', AttributeName: 'b' } ], + LocalSecondaryIndexes: [ { IndexName: 'abc', - KeySchema: [{AttributeName: 'a', KeyType: 'HASH'}, {AttributeName: 'b', KeyType: 'RANGE'}], - Projection: {ProjectionType: 'ALL'}, - }], - GlobalSecondaryIndexes: [{ + KeySchema: [ { AttributeName: 'a', KeyType: 'HASH' }, { AttributeName: 'b', KeyType: 'RANGE' } ], + Projection: { ProjectionType: 'ALL' }, + } ], + GlobalSecondaryIndexes: [ { IndexName: 'abc', - KeySchema: [{AttributeName: 'a', KeyType: 'HASH'}, {AttributeName: 'b', KeyType: 'RANGE'}], - ProvisionedThroughput: {ReadCapacityUnits: 1, WriteCapacityUnits: 1}, - Projection: {ProjectionType: 'ALL'}, - }], - ProvisionedThroughput: {ReadCapacityUnits: 1, WriteCapacityUnits: 1}}, - 'One or more parameter values were invalid: Duplicate index name: abc', done) - }) - - it('should not allow ProvisionedThroughput with PAY_PER_REQUEST and GlobalSecondaryIndexes', function(done) { - assertValidation({TableName: 'abc', - AttributeDefinitions: [{AttributeName: 'a', AttributeType: 'S'}, {AttributeName: 'b', AttributeType: 'S'}], - KeySchema: [{KeyType: 'HASH', AttributeName: 'a'}], + KeySchema: [ { AttributeName: 'a', KeyType: 'HASH' }, { AttributeName: 'b', KeyType: 'RANGE' } ], + ProvisionedThroughput: { ReadCapacityUnits: 1, WriteCapacityUnits: 1 }, + Projection: { ProjectionType: 'ALL' }, + } ], + ProvisionedThroughput: { ReadCapacityUnits: 1, WriteCapacityUnits: 1 } }, + 'One or more parameter values were invalid: Duplicate index name: abc', done) + }) + + it('should not allow ProvisionedThroughput with PAY_PER_REQUEST and GlobalSecondaryIndexes', function (done) { + assertValidation({ TableName: 'abc', + AttributeDefinitions: [ { AttributeName: 'a', AttributeType: 'S' }, { AttributeName: 'b', AttributeType: 'S' } ], + KeySchema: [ { KeyType: 'HASH', AttributeName: 'a' } ], BillingMode: 'PAY_PER_REQUEST', - GlobalSecondaryIndexes: [{ + GlobalSecondaryIndexes: [ { IndexName: 'abc', - KeySchema: [{AttributeName: 'a', KeyType: 'HASH'}, {AttributeName: 'b', KeyType: 'RANGE'}], - Projection: {ProjectionType: 'ALL'}, + KeySchema: [ { AttributeName: 'a', KeyType: 'HASH' }, { AttributeName: 'b', KeyType: 'RANGE' } ], + Projection: { ProjectionType: 'ALL' }, }, { IndexName: 'abd', - KeySchema: [{AttributeName: 'a', KeyType: 'HASH'}, {AttributeName: 'b', KeyType: 'RANGE'}], - ProvisionedThroughput: {ReadCapacityUnits: 1, WriteCapacityUnits: 1}, - Projection: {ProjectionType: 'ALL'}, - }], + KeySchema: [ { AttributeName: 'a', KeyType: 'HASH' }, { AttributeName: 'b', KeyType: 'RANGE' } ], + ProvisionedThroughput: { ReadCapacityUnits: 1, WriteCapacityUnits: 1 }, + Projection: { ProjectionType: 'ALL' }, + } ], }, 'One or more parameter values were invalid: ' + 'ProvisionedThroughput should not be specified for index: abd when BillingMode is PAY_PER_REQUEST', done) }) }) - describe('functionality', function() { + describe('functionality', function () { - it('should succeed for basic', function(done) { + it('should succeed for basic', function (done) { var table = { - TableName: randomName(), - AttributeDefinitions: [{AttributeName: 'a', AttributeType: 'S'}], - KeySchema: [{KeyType: 'HASH', AttributeName: 'a'}], - ProvisionedThroughput: {ReadCapacityUnits: 1, WriteCapacityUnits: 1}, - }, createdAt = Date.now() / 1000 - request(opts(table), function(err, res) { + TableName: randomName(), + AttributeDefinitions: [ { AttributeName: 'a', AttributeType: 'S' } ], + KeySchema: [ { KeyType: 'HASH', AttributeName: 'a' } ], + ProvisionedThroughput: { ReadCapacityUnits: 1, WriteCapacityUnits: 1 }, + }, createdAt = Date.now() / 1000 + request(opts(table), function (err, res) { if (err) return done(err) res.statusCode.should.equal(200) should.exist(res.body.TableDescription) @@ -1171,14 +1171,14 @@ describe('createTable', function() { }) }) - it('should succeed for basic PAY_PER_REQUEST', function(done) { + it('should succeed for basic PAY_PER_REQUEST', function (done) { var table = { - TableName: randomName(), - AttributeDefinitions: [{AttributeName: 'a', AttributeType: 'S'}], - KeySchema: [{KeyType: 'HASH', AttributeName: 'a'}], - BillingMode: 'PAY_PER_REQUEST', - }, createdAt = Date.now() / 1000 - request(opts(table), function(err, res) { + TableName: randomName(), + AttributeDefinitions: [ { AttributeName: 'a', AttributeType: 'S' } ], + KeySchema: [ { KeyType: 'HASH', AttributeName: 'a' } ], + BillingMode: 'PAY_PER_REQUEST', + }, createdAt = Date.now() / 1000 + request(opts(table), function (err, res) { if (err) return done(err) res.statusCode.should.equal(200) should.exist(res.body.TableDescription) @@ -1193,9 +1193,9 @@ describe('createTable', function() { table.ItemCount = 0 table.TableSizeBytes = 0 table.TableStatus = 'CREATING' - table.BillingModeSummary = {BillingMode: 'PAY_PER_REQUEST'} + table.BillingModeSummary = { BillingMode: 'PAY_PER_REQUEST' } delete table.BillingMode - table.TableThroughputModeSummary = {TableThroughputMode: 'PAY_PER_REQUEST'} + table.TableThroughputModeSummary = { TableThroughputMode: 'PAY_PER_REQUEST' } table.ProvisionedThroughput = { NumberOfDecreasesToday: 0, ReadCapacityUnits: 0, @@ -1207,19 +1207,19 @@ describe('createTable', function() { }) }) - it('should change state to ACTIVE after a period', function(done) { + it('should change state to ACTIVE after a period', function (done) { this.timeout(100000) var table = { TableName: randomName(), - AttributeDefinitions: [{AttributeName: 'a', AttributeType: 'S'}], - KeySchema: [{KeyType: 'HASH', AttributeName: 'a'}], - ProvisionedThroughput: {ReadCapacityUnits: 1, WriteCapacityUnits: 1}, + AttributeDefinitions: [ { AttributeName: 'a', AttributeType: 'S' } ], + KeySchema: [ { KeyType: 'HASH', AttributeName: 'a' } ], + ProvisionedThroughput: { ReadCapacityUnits: 1, WriteCapacityUnits: 1 }, } - request(opts(table), function(err, res) { + request(opts(table), function (err, res) { if (err) return done(err) res.body.TableDescription.TableStatus.should.equal('CREATING') - helpers.waitUntilActive(table.TableName, function(err, res) { + helpers.waitUntilActive(table.TableName, function (err, res) { if (err) return done(err) res.body.Table.TableStatus.should.equal('ACTIVE') helpers.deleteWhenActive(table.TableName) @@ -1229,36 +1229,36 @@ describe('createTable', function() { }) // TODO: Seems to block until other tables with secondary indexes have been created - it('should succeed for LocalSecondaryIndexes', function(done) { + it('should succeed for LocalSecondaryIndexes', function (done) { this.timeout(100000) var table = { - TableName: randomName(), - AttributeDefinitions: [{AttributeName: 'a', AttributeType: 'S'}, {AttributeName: 'b', AttributeType: 'S'}], - KeySchema: [{KeyType: 'HASH', AttributeName: 'a'}, {KeyType: 'RANGE', AttributeName: 'b'}], - LocalSecondaryIndexes: [{ - IndexName: 'abc', - KeySchema: [{AttributeName: 'a', KeyType: 'HASH'}, {AttributeName: 'b', KeyType: 'RANGE'}], - Projection: {ProjectionType: 'ALL'}, - }, { - IndexName: 'abd', - KeySchema: [{AttributeName: 'a', KeyType: 'HASH'}, {AttributeName: 'b', KeyType: 'RANGE'}], - Projection: {ProjectionType: 'ALL'}, - }, { - IndexName: 'abe', - KeySchema: [{AttributeName: 'a', KeyType: 'HASH'}, {AttributeName: 'b', KeyType: 'RANGE'}], - Projection: {ProjectionType: 'ALL'}, - }, { - IndexName: 'abf', - KeySchema: [{AttributeName: 'a', KeyType: 'HASH'}, {AttributeName: 'b', KeyType: 'RANGE'}], - Projection: {ProjectionType: 'ALL'}, - }, { - IndexName: 'abg', - KeySchema: [{AttributeName: 'a', KeyType: 'HASH'}, {AttributeName: 'b', KeyType: 'RANGE'}], - Projection: {ProjectionType: 'ALL'}, - }], - ProvisionedThroughput: {ReadCapacityUnits: 1, WriteCapacityUnits: 1}, - }, createdAt = Date.now() / 1000 - request(opts(table), function(err, res) { + TableName: randomName(), + AttributeDefinitions: [ { AttributeName: 'a', AttributeType: 'S' }, { AttributeName: 'b', AttributeType: 'S' } ], + KeySchema: [ { KeyType: 'HASH', AttributeName: 'a' }, { KeyType: 'RANGE', AttributeName: 'b' } ], + LocalSecondaryIndexes: [ { + IndexName: 'abc', + KeySchema: [ { AttributeName: 'a', KeyType: 'HASH' }, { AttributeName: 'b', KeyType: 'RANGE' } ], + Projection: { ProjectionType: 'ALL' }, + }, { + IndexName: 'abd', + KeySchema: [ { AttributeName: 'a', KeyType: 'HASH' }, { AttributeName: 'b', KeyType: 'RANGE' } ], + Projection: { ProjectionType: 'ALL' }, + }, { + IndexName: 'abe', + KeySchema: [ { AttributeName: 'a', KeyType: 'HASH' }, { AttributeName: 'b', KeyType: 'RANGE' } ], + Projection: { ProjectionType: 'ALL' }, + }, { + IndexName: 'abf', + KeySchema: [ { AttributeName: 'a', KeyType: 'HASH' }, { AttributeName: 'b', KeyType: 'RANGE' } ], + Projection: { ProjectionType: 'ALL' }, + }, { + IndexName: 'abg', + KeySchema: [ { AttributeName: 'a', KeyType: 'HASH' }, { AttributeName: 'b', KeyType: 'RANGE' } ], + Projection: { ProjectionType: 'ALL' }, + } ], + ProvisionedThroughput: { ReadCapacityUnits: 1, WriteCapacityUnits: 1 }, + }, createdAt = Date.now() / 1000 + request(opts(table), function (err, res) { if (err) return done(err) res.statusCode.should.equal(200) should.exist(res.body.TableDescription) @@ -1270,7 +1270,7 @@ describe('createTable', function() { desc.TableArn.should.match(new RegExp( 'arn:aws:dynamodb:' + helpers.awsRegion + ':\\d+:table/' + table.TableName)) delete desc.TableArn - desc.LocalSecondaryIndexes.forEach(function(index) { + desc.LocalSecondaryIndexes.forEach(function (index) { index.IndexArn.should.match(new RegExp( 'arn:aws:dynamodb:' + helpers.awsRegion + ':\\d+:table/' + table.TableName + '/index/' + index.IndexName)) delete index.IndexArn @@ -1280,7 +1280,7 @@ describe('createTable', function() { table.TableSizeBytes = 0 table.TableStatus = 'CREATING' // DynamoDB seem to put them in a weird order, so check separately - table.LocalSecondaryIndexes.forEach(function(index) { + table.LocalSecondaryIndexes.forEach(function (index) { index.IndexSizeBytes = 0 index.ItemCount = 0 desc.LocalSecondaryIndexes.should.containEql(index) @@ -1294,41 +1294,41 @@ describe('createTable', function() { }) }) - it('should succeed for multiple GlobalSecondaryIndexes', function(done) { + it('should succeed for multiple GlobalSecondaryIndexes', function (done) { this.timeout(300000) var table = { - TableName: randomName(), - AttributeDefinitions: [{AttributeName: 'a', AttributeType: 'S'}, {AttributeName: 'b', AttributeType: 'S'}], - KeySchema: [{KeyType: 'HASH', AttributeName: 'a'}], - GlobalSecondaryIndexes: [{ - IndexName: 'abc', - KeySchema: [{AttributeName: 'a', KeyType: 'HASH'}, {AttributeName: 'b', KeyType: 'RANGE'}], - ProvisionedThroughput: {ReadCapacityUnits: 1, WriteCapacityUnits: 1}, - Projection: {ProjectionType: 'ALL'}, - }, { - IndexName: 'abd', - KeySchema: [{AttributeName: 'a', KeyType: 'HASH'}, {AttributeName: 'b', KeyType: 'RANGE'}], - ProvisionedThroughput: {ReadCapacityUnits: 1, WriteCapacityUnits: 1}, - Projection: {ProjectionType: 'ALL'}, - }, { - IndexName: 'abe', - KeySchema: [{AttributeName: 'a', KeyType: 'HASH'}, {AttributeName: 'b', KeyType: 'RANGE'}], - ProvisionedThroughput: {ReadCapacityUnits: 1, WriteCapacityUnits: 1}, - Projection: {ProjectionType: 'ALL'}, - }, { - IndexName: 'abf', - KeySchema: [{AttributeName: 'a', KeyType: 'HASH'}, {AttributeName: 'b', KeyType: 'RANGE'}], - ProvisionedThroughput: {ReadCapacityUnits: 1, WriteCapacityUnits: 1}, - Projection: {ProjectionType: 'ALL'}, - }, { - IndexName: 'abg', - KeySchema: [{AttributeName: 'a', KeyType: 'HASH'}, {AttributeName: 'b', KeyType: 'RANGE'}], - ProvisionedThroughput: {ReadCapacityUnits: 1, WriteCapacityUnits: 1}, - Projection: {ProjectionType: 'ALL'}, - }], - ProvisionedThroughput: {ReadCapacityUnits: 1, WriteCapacityUnits: 1}, - }, createdAt = Date.now() / 1000, globalIndexes = table.GlobalSecondaryIndexes - request(opts(table), function(err, res) { + TableName: randomName(), + AttributeDefinitions: [ { AttributeName: 'a', AttributeType: 'S' }, { AttributeName: 'b', AttributeType: 'S' } ], + KeySchema: [ { KeyType: 'HASH', AttributeName: 'a' } ], + GlobalSecondaryIndexes: [ { + IndexName: 'abc', + KeySchema: [ { AttributeName: 'a', KeyType: 'HASH' }, { AttributeName: 'b', KeyType: 'RANGE' } ], + ProvisionedThroughput: { ReadCapacityUnits: 1, WriteCapacityUnits: 1 }, + Projection: { ProjectionType: 'ALL' }, + }, { + IndexName: 'abd', + KeySchema: [ { AttributeName: 'a', KeyType: 'HASH' }, { AttributeName: 'b', KeyType: 'RANGE' } ], + ProvisionedThroughput: { ReadCapacityUnits: 1, WriteCapacityUnits: 1 }, + Projection: { ProjectionType: 'ALL' }, + }, { + IndexName: 'abe', + KeySchema: [ { AttributeName: 'a', KeyType: 'HASH' }, { AttributeName: 'b', KeyType: 'RANGE' } ], + ProvisionedThroughput: { ReadCapacityUnits: 1, WriteCapacityUnits: 1 }, + Projection: { ProjectionType: 'ALL' }, + }, { + IndexName: 'abf', + KeySchema: [ { AttributeName: 'a', KeyType: 'HASH' }, { AttributeName: 'b', KeyType: 'RANGE' } ], + ProvisionedThroughput: { ReadCapacityUnits: 1, WriteCapacityUnits: 1 }, + Projection: { ProjectionType: 'ALL' }, + }, { + IndexName: 'abg', + KeySchema: [ { AttributeName: 'a', KeyType: 'HASH' }, { AttributeName: 'b', KeyType: 'RANGE' } ], + ProvisionedThroughput: { ReadCapacityUnits: 1, WriteCapacityUnits: 1 }, + Projection: { ProjectionType: 'ALL' }, + } ], + ProvisionedThroughput: { ReadCapacityUnits: 1, WriteCapacityUnits: 1 }, + }, createdAt = Date.now() / 1000, globalIndexes = table.GlobalSecondaryIndexes + request(opts(table), function (err, res) { if (err) return done(err) res.statusCode.should.equal(200) should.exist(res.body.TableDescription) @@ -1340,7 +1340,7 @@ describe('createTable', function() { desc.TableArn.should.match(new RegExp( 'arn:aws:dynamodb:' + helpers.awsRegion + ':\\d+:table/' + table.TableName)) delete desc.TableArn - desc.GlobalSecondaryIndexes.forEach(function(index) { + desc.GlobalSecondaryIndexes.forEach(function (index) { index.IndexArn.should.match(new RegExp( 'arn:aws:dynamodb:' + helpers.awsRegion + ':\\d+:table/' + table.TableName + '/index/' + index.IndexName)) delete index.IndexArn @@ -1350,7 +1350,7 @@ describe('createTable', function() { table.TableSizeBytes = 0 table.TableStatus = 'CREATING' // DynamoDB seem to put them in a weird order, so check separately - globalIndexes.forEach(function(index) { + globalIndexes.forEach(function (index) { index.IndexSizeBytes = 0 index.ItemCount = 0 index.IndexStatus = 'CREATING' @@ -1363,10 +1363,10 @@ describe('createTable', function() { desc.should.eql(table) // Ensure that the indexes become active too - helpers.waitUntilIndexesActive(table.TableName, function(err, res) { + helpers.waitUntilIndexesActive(table.TableName, function (err, res) { if (err) return done(err) - res.body.Table.GlobalSecondaryIndexes.forEach(function(index) { delete index.IndexArn }) - globalIndexes.forEach(function(index) { + res.body.Table.GlobalSecondaryIndexes.forEach(function (index) { delete index.IndexArn }) + globalIndexes.forEach(function (index) { index.IndexStatus = 'ACTIVE' res.body.Table.GlobalSecondaryIndexes.should.containEql(index) }) @@ -1376,23 +1376,23 @@ describe('createTable', function() { }) }) - it('should succeed for PAY_PER_REQUEST GlobalSecondaryIndexes', function(done) { + it('should succeed for PAY_PER_REQUEST GlobalSecondaryIndexes', function (done) { var table = { - TableName: randomName(), - AttributeDefinitions: [{AttributeName: 'a', AttributeType: 'S'}, {AttributeName: 'b', AttributeType: 'S'}], - KeySchema: [{KeyType: 'HASH', AttributeName: 'a'}], - BillingMode: 'PAY_PER_REQUEST', - GlobalSecondaryIndexes: [{ - IndexName: 'abc', - KeySchema: [{AttributeName: 'a', KeyType: 'HASH'}, {AttributeName: 'b', KeyType: 'RANGE'}], - Projection: {ProjectionType: 'ALL'}, - }, { - IndexName: 'abd', - KeySchema: [{AttributeName: 'a', KeyType: 'HASH'}, {AttributeName: 'b', KeyType: 'RANGE'}], - Projection: {ProjectionType: 'ALL'}, - }], - }, createdAt = Date.now() / 1000, globalIndexes = table.GlobalSecondaryIndexes - request(opts(table), function(err, res) { + TableName: randomName(), + AttributeDefinitions: [ { AttributeName: 'a', AttributeType: 'S' }, { AttributeName: 'b', AttributeType: 'S' } ], + KeySchema: [ { KeyType: 'HASH', AttributeName: 'a' } ], + BillingMode: 'PAY_PER_REQUEST', + GlobalSecondaryIndexes: [ { + IndexName: 'abc', + KeySchema: [ { AttributeName: 'a', KeyType: 'HASH' }, { AttributeName: 'b', KeyType: 'RANGE' } ], + Projection: { ProjectionType: 'ALL' }, + }, { + IndexName: 'abd', + KeySchema: [ { AttributeName: 'a', KeyType: 'HASH' }, { AttributeName: 'b', KeyType: 'RANGE' } ], + Projection: { ProjectionType: 'ALL' }, + } ], + }, createdAt = Date.now() / 1000, globalIndexes = table.GlobalSecondaryIndexes + request(opts(table), function (err, res) { if (err) return done(err) res.statusCode.should.equal(200) should.exist(res.body.TableDescription) @@ -1404,23 +1404,23 @@ describe('createTable', function() { desc.TableArn.should.match(new RegExp( 'arn:aws:dynamodb:' + helpers.awsRegion + ':\\d+:table/' + table.TableName)) delete desc.TableArn - desc.GlobalSecondaryIndexes.forEach(function(index) { + desc.GlobalSecondaryIndexes.forEach(function (index) { index.IndexArn.should.match(new RegExp( 'arn:aws:dynamodb:' + helpers.awsRegion + ':\\d+:table/' + table.TableName + '/index/' + index.IndexName)) delete index.IndexArn }) table.ItemCount = 0 table.TableSizeBytes = 0 - table.BillingModeSummary = {BillingMode: 'PAY_PER_REQUEST'} + table.BillingModeSummary = { BillingMode: 'PAY_PER_REQUEST' } delete table.BillingMode - table.TableThroughputModeSummary = {TableThroughputMode: 'PAY_PER_REQUEST'} + table.TableThroughputModeSummary = { TableThroughputMode: 'PAY_PER_REQUEST' } table.ProvisionedThroughput = { NumberOfDecreasesToday: 0, ReadCapacityUnits: 0, WriteCapacityUnits: 0, } table.TableStatus = 'CREATING' - globalIndexes.forEach(function(index) { + globalIndexes.forEach(function (index) { index.IndexSizeBytes = 0 index.ItemCount = 0 index.IndexStatus = 'CREATING' @@ -1437,10 +1437,10 @@ describe('createTable', function() { desc.should.eql(table) // Ensure that the indexes become active too - helpers.waitUntilIndexesActive(table.TableName, function(err, res) { + helpers.waitUntilIndexesActive(table.TableName, function (err, res) { if (err) return done(err) - res.body.Table.GlobalSecondaryIndexes.forEach(function(index) { delete index.IndexArn }) - globalIndexes.forEach(function(index) { + res.body.Table.GlobalSecondaryIndexes.forEach(function (index) { delete index.IndexArn }) + globalIndexes.forEach(function (index) { index.IndexStatus = 'ACTIVE' res.body.Table.GlobalSecondaryIndexes.should.containEql(index) }) diff --git a/test/deleteItem.js b/test/deleteItem.js index 3cfc0c1..726e08f 100644 --- a/test/deleteItem.js +++ b/test/deleteItem.js @@ -1,85 +1,85 @@ var async = require('async'), - helpers = require('./helpers') + helpers = require('./helpers') var target = 'DeleteItem', - request = helpers.request, - opts = helpers.opts.bind(null, target), - assertType = helpers.assertType.bind(null, target), - assertValidation = helpers.assertValidation.bind(null, target), - assertConditional = helpers.assertConditional.bind(null, target) + request = helpers.request, + opts = helpers.opts.bind(null, target), + assertType = helpers.assertType.bind(null, target), + assertValidation = helpers.assertValidation.bind(null, target), + assertConditional = helpers.assertConditional.bind(null, target) -describe('deleteItem', function() { +describe('deleteItem', function () { - describe('serializations', function() { + describe('serializations', function () { - it('should return SerializationException when TableName is not a string', function(done) { + it('should return SerializationException when TableName is not a string', function (done) { assertType('TableName', 'String', done) }) - it('should return SerializationException when Key is not a map', function(done) { + it('should return SerializationException when Key is not a map', function (done) { assertType('Key', 'Map', done) }) - it('should return SerializationException when Key.Attr is not an attr struct', function(done) { + it('should return SerializationException when Key.Attr is not an attr struct', function (done) { this.timeout(60000) assertType('Key.Attr', 'AttrStruct', done) }) - it('should return SerializationException when Expected is not a map', function(done) { + it('should return SerializationException when Expected is not a map', function (done) { assertType('Expected', 'Map', done) }) - it('should return SerializationException when Expected.Attr is not a struct', function(done) { + it('should return SerializationException when Expected.Attr is not a struct', function (done) { assertType('Expected.Attr', 'ValueStruct', done) }) - it('should return SerializationException when Expected.Attr.Exists is not a boolean', function(done) { + it('should return SerializationException when Expected.Attr.Exists is not a boolean', function (done) { assertType('Expected.Attr.Exists', 'Boolean', done) }) - it('should return SerializationException when Expected.Attr.Value is not an attr struct', function(done) { + it('should return SerializationException when Expected.Attr.Value is not an attr struct', function (done) { this.timeout(60000) assertType('Expected.Attr.Value', 'AttrStruct', done) }) - it('should return SerializationException when ReturnConsumedCapacity is not a string', function(done) { + it('should return SerializationException when ReturnConsumedCapacity is not a string', function (done) { assertType('ReturnConsumedCapacity', 'String', done) }) - it('should return SerializationException when ReturnItemCollectionMetrics is not a string', function(done) { + it('should return SerializationException when ReturnItemCollectionMetrics is not a string', function (done) { assertType('ReturnItemCollectionMetrics', 'String', done) }) - it('should return SerializationException when ReturnValues is not a string', function(done) { + it('should return SerializationException when ReturnValues is not a string', function (done) { assertType('ReturnValues', 'String', done) }) - it('should return SerializationException when ConditionExpression is not a string', function(done) { + it('should return SerializationException when ConditionExpression is not a string', function (done) { assertType('ConditionExpression', 'String', done) }) - it('should return SerializationException when ExpressionAttributeValues is not a map', function(done) { + it('should return SerializationException when ExpressionAttributeValues is not a map', function (done) { assertType('ExpressionAttributeValues', 'Map', done) }) - it('should return SerializationException when ExpressionAttributeValues.Attr is not an attr struct', function(done) { + it('should return SerializationException when ExpressionAttributeValues.Attr is not an attr struct', function (done) { this.timeout(60000) assertType('ExpressionAttributeValues.Attr', 'AttrStruct', done) }) - it('should return SerializationException when ExpressionAttributeNames is not a map', function(done) { + it('should return SerializationException when ExpressionAttributeNames is not a map', function (done) { assertType('ExpressionAttributeNames', 'Map', done) }) - it('should return SerializationException when ExpressionAttributeNames.Attr is not a string', function(done) { + it('should return SerializationException when ExpressionAttributeNames.Attr is not a string', function (done) { assertType('ExpressionAttributeNames.Attr', 'String', done) }) }) - describe('validations', function() { + describe('validations', function () { - it('should return ValidationException for no TableName', function(done) { + it('should return ValidationException for no TableName', function (done) { assertValidation({}, [ 'Value null at \'tableName\' failed to satisfy constraint: ' + 'Member must not be null', @@ -88,8 +88,8 @@ describe('deleteItem', function() { ], done) }) - it('should return ValidationException for empty TableName', function(done) { - assertValidation({TableName: ''}, [ + it('should return ValidationException for empty TableName', function (done) { + assertValidation({ TableName: '' }, [ 'Value \'\' at \'tableName\' failed to satisfy constraint: ' + 'Member must satisfy regular expression pattern: [a-zA-Z0-9_.-]+', 'Value \'\' at \'tableName\' failed to satisfy constraint: ' + @@ -99,8 +99,8 @@ describe('deleteItem', function() { ], done) }) - it('should return ValidationException for short TableName', function(done) { - assertValidation({TableName: 'a;'}, [ + it('should return ValidationException for short TableName', function (done) { + assertValidation({ TableName: 'a;' }, [ 'Value \'a;\' at \'tableName\' failed to satisfy constraint: ' + 'Member must satisfy regular expression pattern: [a-zA-Z0-9_.-]+', 'Value \'a;\' at \'tableName\' failed to satisfy constraint: ' + @@ -110,9 +110,9 @@ describe('deleteItem', function() { ], done) }) - it('should return ValidationException for long TableName', function(done) { + it('should return ValidationException for long TableName', function (done) { var name = new Array(256 + 1).join('a') - assertValidation({TableName: name}, [ + assertValidation({ TableName: name }, [ 'Value \'' + name + '\' at \'tableName\' failed to satisfy constraint: ' + 'Member must have length less than or equal to 255', 'Value null at \'key\' failed to satisfy constraint: ' + @@ -120,23 +120,23 @@ describe('deleteItem', function() { ], done) }) - it('should return ValidationException for incorrect attributes', function(done) { - assertValidation({TableName: 'abc;', ReturnConsumedCapacity: 'hi', - ReturnItemCollectionMetrics: 'hi', ReturnValues: 'hi'}, [ - 'Value \'hi\' at \'returnConsumedCapacity\' failed to satisfy constraint: ' + + it('should return ValidationException for incorrect attributes', function (done) { + assertValidation({ TableName: 'abc;', ReturnConsumedCapacity: 'hi', + ReturnItemCollectionMetrics: 'hi', ReturnValues: 'hi' }, [ + 'Value \'hi\' at \'returnConsumedCapacity\' failed to satisfy constraint: ' + 'Member must satisfy enum value set: [INDEXES, TOTAL, NONE]', - 'Value \'abc;\' at \'tableName\' failed to satisfy constraint: ' + + 'Value \'abc;\' at \'tableName\' failed to satisfy constraint: ' + 'Member must satisfy regular expression pattern: [a-zA-Z0-9_.-]+', - 'Value \'hi\' at \'returnValues\' failed to satisfy constraint: ' + + 'Value \'hi\' at \'returnValues\' failed to satisfy constraint: ' + 'Member must satisfy enum value set: [ALL_NEW, UPDATED_OLD, ALL_OLD, NONE, UPDATED_NEW]', - 'Value \'hi\' at \'returnItemCollectionMetrics\' failed to satisfy constraint: ' + + 'Value \'hi\' at \'returnItemCollectionMetrics\' failed to satisfy constraint: ' + 'Member must satisfy enum value set: [SIZE, NONE]', - 'Value null at \'key\' failed to satisfy constraint: ' + + 'Value null at \'key\' failed to satisfy constraint: ' + 'Member must not be null', - ], done) + ], done) }) - it('should return ValidationException if expression and non-expression', function(done) { + it('should return ValidationException if expression and non-expression', function (done) { assertValidation({ TableName: 'abc', Key: {}, @@ -148,7 +148,7 @@ describe('deleteItem', function() { 'Non-expression parameters: {Expected} Expression parameters: {ConditionExpression}', done) }) - it('should return ValidationException if ExpressionAttributeNames but no ConditionExpression', function(done) { + it('should return ValidationException if ExpressionAttributeNames but no ConditionExpression', function (done) { assertValidation({ TableName: 'abc', Key: {}, @@ -158,7 +158,7 @@ describe('deleteItem', function() { }, 'ExpressionAttributeNames can only be specified when using expressions', done) }) - it('should return ValidationException if ExpressionAttributeValues but no ConditionExpression', function(done) { + it('should return ValidationException if ExpressionAttributeValues but no ConditionExpression', function (done) { assertValidation({ TableName: 'abc', Key: {}, @@ -167,7 +167,7 @@ describe('deleteItem', function() { }, 'ExpressionAttributeValues can only be specified when using expressions: ConditionExpression is null', done) }) - it('should return ValidationException for empty ExpressionAttributeNames', function(done) { + it('should return ValidationException for empty ExpressionAttributeNames', function (done) { assertValidation({ TableName: 'abc', Key: {}, @@ -177,17 +177,17 @@ describe('deleteItem', function() { }, 'ExpressionAttributeNames must not be empty', done) }) - it('should return ValidationException for invalid ExpressionAttributeNames', function(done) { + it('should return ValidationException for invalid ExpressionAttributeNames', function (done) { assertValidation({ TableName: 'abc', Key: {}, - ExpressionAttributeNames: {'a': 'a'}, + ExpressionAttributeNames: { 'a': 'a' }, ExpressionAttributeValues: {}, ConditionExpression: '', }, 'ExpressionAttributeNames contains invalid key: Syntax error; key: "a"', done) }) - it('should return ValidationException for empty ExpressionAttributeValues', function(done) { + it('should return ValidationException for empty ExpressionAttributeValues', function (done) { assertValidation({ TableName: 'abc', Key: {}, @@ -196,87 +196,87 @@ describe('deleteItem', function() { }, 'ExpressionAttributeValues must not be empty', done) }) - it('should return ValidationException for invalid keys in ExpressionAttributeValues', function(done) { + it('should return ValidationException for invalid keys in ExpressionAttributeValues', function (done) { assertValidation({ TableName: 'abc', Key: {}, - ExpressionAttributeValues: {':b': {a: ''}, 'b': {S: 'a'}}, + ExpressionAttributeValues: { ':b': { a: '' }, 'b': { S: 'a' } }, ConditionExpression: '', }, 'ExpressionAttributeValues contains invalid key: Syntax error; key: "b"', done) }) - it('should return ValidationException for unsupported datatype in ExpressionAttributeValues', function(done) { + it('should return ValidationException for unsupported datatype in ExpressionAttributeValues', function (done) { async.forEach([ {}, - {a: ''}, - {M: {a: {}}}, - {L: [{}]}, - {L: [{a: {}}]}, - ], function(expr, cb) { + { a: '' }, + { M: { a: {} } }, + { L: [ {} ] }, + { L: [ { a: {} } ] }, + ], function (expr, cb) { assertValidation({ TableName: 'abc', Key: {}, - ExpressionAttributeValues: {':b': expr}, + ExpressionAttributeValues: { ':b': expr }, ConditionExpression: '', }, 'ExpressionAttributeValues contains invalid value: ' + 'Supplied AttributeValue is empty, must contain exactly one of the supported datatypes for key :b', cb) }, done) }) - it('should return ValidationException for invalid values in ExpressionAttributeValues', function(done) { + it('should return ValidationException for invalid values in ExpressionAttributeValues', function (done) { async.forEach([ - [{NULL: 'no'}, 'Null attribute value types must have the value of true'], - [{SS: []}, 'An string set may not be empty'], - [{NS: []}, 'An number set may not be empty'], - [{BS: []}, 'Binary sets should not be empty'], - [{SS: ['a', 'a']}, 'Input collection [a, a] contains duplicates.'], - [{BS: ['Yg==', 'Yg==']}, 'Input collection [Yg==, Yg==]of type BS contains duplicates.'], - ], function(expr, cb) { + [ { NULL: 'no' }, 'Null attribute value types must have the value of true' ], + [ { SS: [] }, 'An string set may not be empty' ], + [ { NS: [] }, 'An number set may not be empty' ], + [ { BS: [] }, 'Binary sets should not be empty' ], + [ { SS: [ 'a', 'a' ] }, 'Input collection [a, a] contains duplicates.' ], + [ { BS: [ 'Yg==', 'Yg==' ] }, 'Input collection [Yg==, Yg==]of type BS contains duplicates.' ], + ], function (expr, cb) { assertValidation({ TableName: 'abc', Key: {}, - ExpressionAttributeValues: {':b': expr[0]}, + ExpressionAttributeValues: { ':b': expr[0] }, ConditionExpression: '', }, 'ExpressionAttributeValues contains invalid value: ' + 'One or more parameter values were invalid: ' + expr[1] + ' for key :b', cb) }, done) }) - it('should return ValidationException for empty/invalid numbers in ExpressionAttributeValues', function(done) { + it('should return ValidationException for empty/invalid numbers in ExpressionAttributeValues', function (done) { async.forEach([ - [{S: '', N: ''}, 'The parameter cannot be converted to a numeric value'], - [{S: 'a', N: ''}, 'The parameter cannot be converted to a numeric value'], - [{S: 'a', N: 'b'}, 'The parameter cannot be converted to a numeric value: b'], - [{NS: ['1', '']}, 'The parameter cannot be converted to a numeric value'], - [{NS: ['1', 'b']}, 'The parameter cannot be converted to a numeric value: b'], - [{NS: ['1', '1']}, 'Input collection contains duplicates'], - [{N: '123456789012345678901234567890123456789'}, 'Attempting to store more than 38 significant digits in a Number'], - [{N: '-1.23456789012345678901234567890123456789'}, 'Attempting to store more than 38 significant digits in a Number'], - [{N: '1e126'}, 'Number overflow. Attempting to store a number with magnitude larger than supported range'], - [{N: '-1e126'}, 'Number overflow. Attempting to store a number with magnitude larger than supported range'], - [{N: '1e-131'}, 'Number underflow. Attempting to store a number with magnitude smaller than supported range'], - [{N: '-1e-131'}, 'Number underflow. Attempting to store a number with magnitude smaller than supported range'], - ], function(expr, cb) { + [ { S: '', N: '' }, 'The parameter cannot be converted to a numeric value' ], + [ { S: 'a', N: '' }, 'The parameter cannot be converted to a numeric value' ], + [ { S: 'a', N: 'b' }, 'The parameter cannot be converted to a numeric value: b' ], + [ { NS: [ '1', '' ] }, 'The parameter cannot be converted to a numeric value' ], + [ { NS: [ '1', 'b' ] }, 'The parameter cannot be converted to a numeric value: b' ], + [ { NS: [ '1', '1' ] }, 'Input collection contains duplicates' ], + [ { N: '123456789012345678901234567890123456789' }, 'Attempting to store more than 38 significant digits in a Number' ], + [ { N: '-1.23456789012345678901234567890123456789' }, 'Attempting to store more than 38 significant digits in a Number' ], + [ { N: '1e126' }, 'Number overflow. Attempting to store a number with magnitude larger than supported range' ], + [ { N: '-1e126' }, 'Number overflow. Attempting to store a number with magnitude larger than supported range' ], + [ { N: '1e-131' }, 'Number underflow. Attempting to store a number with magnitude smaller than supported range' ], + [ { N: '-1e-131' }, 'Number underflow. Attempting to store a number with magnitude smaller than supported range' ], + ], function (expr, cb) { assertValidation({ TableName: 'abc', Key: {}, - ExpressionAttributeValues: {':b': expr[0]}, + ExpressionAttributeValues: { ':b': expr[0] }, ConditionExpression: '', }, 'ExpressionAttributeValues contains invalid value: ' + expr[1] + ' for key :b', cb) }, done) }) - it('should return ValidationException for multiple datatypes in ExpressionAttributeValues', function(done) { + it('should return ValidationException for multiple datatypes in ExpressionAttributeValues', function (done) { assertValidation({ TableName: 'abc', Key: {}, - ExpressionAttributeValues: {':b': {S: 'a', N: '1'}}, + ExpressionAttributeValues: { ':b': { S: 'a', N: '1' } }, ConditionExpression: '', }, 'ExpressionAttributeValues contains invalid value: ' + 'Supplied AttributeValue has more than one datatypes set, must contain exactly one of the supported datatypes for key :b', done) }) - it('should return ValidationException for empty ConditionExpression', function(done) { + it('should return ValidationException for empty ConditionExpression', function (done) { assertValidation({ TableName: 'abc', Key: {}, @@ -284,7 +284,7 @@ describe('deleteItem', function() { }, 'Invalid ConditionExpression: The expression can not be empty;', done) }) - it('should return ValidationException for incorrect ConditionExpression', function(done) { + it('should return ValidationException for incorrect ConditionExpression', function (done) { assertValidation({ TableName: 'abc', Key: {}, @@ -292,167 +292,167 @@ describe('deleteItem', function() { }, /^Invalid ConditionExpression: Syntax error; /, done) }) - it('should return ValidationException for unsupported datatype in Key', function(done) { + it('should return ValidationException for unsupported datatype in Key', function (done) { async.forEach([ {}, - {a: ''}, - {M: {a: {}}}, - {L: [{}]}, - {L: [{a: {}}]}, - ], function(expr, cb) { - assertValidation({TableName: 'abc', Key: {a: expr}}, + { a: '' }, + { M: { a: {} } }, + { L: [ {} ] }, + { L: [ { a: {} } ] }, + ], function (expr, cb) { + assertValidation({ TableName: 'abc', Key: { a: expr } }, 'Supplied AttributeValue is empty, must contain exactly one of the supported datatypes', cb) }, done) }) - it('should return ValidationException for invalid values in Key', function(done) { + it('should return ValidationException for invalid values in Key', function (done) { async.forEach([ - [{NULL: 'no'}, 'Null attribute value types must have the value of true'], - [{SS: []}, 'An string set may not be empty'], - [{NS: []}, 'An number set may not be empty'], - [{BS: []}, 'Binary sets should not be empty'], - [{SS: ['a', 'a']}, 'Input collection [a, a] contains duplicates.'], - [{BS: ['Yg==', 'Yg==']}, 'Input collection [Yg==, Yg==]of type BS contains duplicates.'], - ], function(expr, cb) { - assertValidation({TableName: 'abc', Key: {a: expr[0]}}, + [ { NULL: 'no' }, 'Null attribute value types must have the value of true' ], + [ { SS: [] }, 'An string set may not be empty' ], + [ { NS: [] }, 'An number set may not be empty' ], + [ { BS: [] }, 'Binary sets should not be empty' ], + [ { SS: [ 'a', 'a' ] }, 'Input collection [a, a] contains duplicates.' ], + [ { BS: [ 'Yg==', 'Yg==' ] }, 'Input collection [Yg==, Yg==]of type BS contains duplicates.' ], + ], function (expr, cb) { + assertValidation({ TableName: 'abc', Key: { a: expr[0] } }, 'One or more parameter values were invalid: ' + expr[1], cb) }, done) }) - it('should return ValidationException for empty/invalid numbers in Key', function(done) { + it('should return ValidationException for empty/invalid numbers in Key', function (done) { async.forEach([ - [{S: '', N: ''}, 'The parameter cannot be converted to a numeric value'], - [{S: 'a', N: ''}, 'The parameter cannot be converted to a numeric value'], - [{S: 'a', N: 'b'}, 'The parameter cannot be converted to a numeric value: b'], - [{NS: ['1', '']}, 'The parameter cannot be converted to a numeric value'], - [{NS: ['1', 'b']}, 'The parameter cannot be converted to a numeric value: b'], - [{NS: ['1', '1']}, 'Input collection contains duplicates'], - [{N: '123456789012345678901234567890123456789'}, 'Attempting to store more than 38 significant digits in a Number'], - [{N: '-1.23456789012345678901234567890123456789'}, 'Attempting to store more than 38 significant digits in a Number'], - [{N: '1e126'}, 'Number overflow. Attempting to store a number with magnitude larger than supported range'], - [{N: '-1e126'}, 'Number overflow. Attempting to store a number with magnitude larger than supported range'], - [{N: '1e-131'}, 'Number underflow. Attempting to store a number with magnitude smaller than supported range'], - [{N: '-1e-131'}, 'Number underflow. Attempting to store a number with magnitude smaller than supported range'], - ], function(expr, cb) { - assertValidation({TableName: 'abc', Key: {a: expr[0]}}, expr[1], cb) + [ { S: '', N: '' }, 'The parameter cannot be converted to a numeric value' ], + [ { S: 'a', N: '' }, 'The parameter cannot be converted to a numeric value' ], + [ { S: 'a', N: 'b' }, 'The parameter cannot be converted to a numeric value: b' ], + [ { NS: [ '1', '' ] }, 'The parameter cannot be converted to a numeric value' ], + [ { NS: [ '1', 'b' ] }, 'The parameter cannot be converted to a numeric value: b' ], + [ { NS: [ '1', '1' ] }, 'Input collection contains duplicates' ], + [ { N: '123456789012345678901234567890123456789' }, 'Attempting to store more than 38 significant digits in a Number' ], + [ { N: '-1.23456789012345678901234567890123456789' }, 'Attempting to store more than 38 significant digits in a Number' ], + [ { N: '1e126' }, 'Number overflow. Attempting to store a number with magnitude larger than supported range' ], + [ { N: '-1e126' }, 'Number overflow. Attempting to store a number with magnitude larger than supported range' ], + [ { N: '1e-131' }, 'Number underflow. Attempting to store a number with magnitude smaller than supported range' ], + [ { N: '-1e-131' }, 'Number underflow. Attempting to store a number with magnitude smaller than supported range' ], + ], function (expr, cb) { + assertValidation({ TableName: 'abc', Key: { a: expr[0] } }, expr[1], cb) }, done) }) - it('should return ValidationException for multiple datatypes in Key', function(done) { - assertValidation({TableName: 'abc', Key: {'a': {S: 'a', N: '1'}}}, + it('should return ValidationException for multiple datatypes in Key', function (done) { + assertValidation({ TableName: 'abc', Key: { 'a': { S: 'a', N: '1' } } }, 'Supplied AttributeValue has more than one datatypes set, must contain exactly one of the supported datatypes', done) }) - it('should return ValidationException if ComparisonOperator used alone', function(done) { - assertValidation({TableName: 'aaa', Key: {}, Expected: {a: {ComparisonOperator: 'LT'}}}, + it('should return ValidationException if ComparisonOperator used alone', function (done) { + assertValidation({ TableName: 'aaa', Key: {}, Expected: { a: { ComparisonOperator: 'LT' } } }, 'One or more parameter values were invalid: Value or AttributeValueList must be used with ComparisonOperator: LT for Attribute: a', done) }) - it('should return ValidationException if ComparisonOperator and Exists are used together', function(done) { - assertValidation({TableName: 'aaa', Key: {}, Expected: {a: {Exists: true, ComparisonOperator: 'LT'}}}, + it('should return ValidationException if ComparisonOperator and Exists are used together', function (done) { + assertValidation({ TableName: 'aaa', Key: {}, Expected: { a: { Exists: true, ComparisonOperator: 'LT' } } }, 'One or more parameter values were invalid: Exists and ComparisonOperator cannot be used together for Attribute: a', done) }) - it('should return ValidationException if AttributeValueList is used alone', function(done) { - assertValidation({TableName: 'aaa', Key: {}, Expected: {a: {AttributeValueList: []}}}, + it('should return ValidationException if AttributeValueList is used alone', function (done) { + assertValidation({ TableName: 'aaa', Key: {}, Expected: { a: { AttributeValueList: [] } } }, 'One or more parameter values were invalid: AttributeValueList can only be used with a ComparisonOperator for Attribute: a', done) }) - it('should return ValidationException if AttributeValueList and Exists are used together', function(done) { - assertValidation({TableName: 'aaa', Key: {}, Expected: {a: {Exists: true, AttributeValueList: []}}}, + it('should return ValidationException if AttributeValueList and Exists are used together', function (done) { + assertValidation({ TableName: 'aaa', Key: {}, Expected: { a: { Exists: true, AttributeValueList: [] } } }, 'One or more parameter values were invalid: AttributeValueList can only be used with a ComparisonOperator for Attribute: a', done) }) - it('should return ValidationException if AttributeValueList and Value are used together', function(done) { - assertValidation({TableName: 'aaa', Key: {}, Expected: {a: {Value: {S: 'a'}, AttributeValueList: []}}}, + it('should return ValidationException if AttributeValueList and Value are used together', function (done) { + assertValidation({ TableName: 'aaa', Key: {}, Expected: { a: { Value: { S: 'a' }, AttributeValueList: [] } } }, 'One or more parameter values were invalid: Value and AttributeValueList cannot be used together for Attribute: a', done) }) - it('should return ValidationException if Value provides incorrect number of attributes: BETWEEN', function(done) { - var expected = {a: { - Value: {S: 'a'}, + it('should return ValidationException if Value provides incorrect number of attributes: BETWEEN', function (done) { + var expected = { a: { + Value: { S: 'a' }, ComparisonOperator: 'BETWEEN', - }} - assertValidation({TableName: 'aaa', Key: {}, Expected: expected}, + } } + assertValidation({ TableName: 'aaa', Key: {}, Expected: expected }, 'One or more parameter values were invalid: Invalid number of argument(s) for the BETWEEN ComparisonOperator', done) }) - it('should return ValidationException if Value provides incorrect number of attributes: NULL', function(done) { - var expected = {a: { - Value: {S: 'a'}, + it('should return ValidationException if Value provides incorrect number of attributes: NULL', function (done) { + var expected = { a: { + Value: { S: 'a' }, ComparisonOperator: 'NULL', - }} - assertValidation({TableName: 'aaa', Key: {}, Expected: expected}, + } } + assertValidation({ TableName: 'aaa', Key: {}, Expected: expected }, 'One or more parameter values were invalid: Invalid number of argument(s) for the NULL ComparisonOperator', done) }) - it('should return ValidationException if AttributeValueList has different types', function(done) { + it('should return ValidationException if AttributeValueList has different types', function (done) { assertValidation({ TableName: 'aaa', Key: {}, - Expected: {a: {ComparisonOperator: 'IN', AttributeValueList: [{S: 'b'}, {N: '1'}]}}, + Expected: { a: { ComparisonOperator: 'IN', AttributeValueList: [ { S: 'b' }, { N: '1' } ] } }, }, 'One or more parameter values were invalid: AttributeValues inside AttributeValueList must be of same type', done) }) - it('should return ValidationException if BETWEEN arguments are in the incorrect order', function(done) { + it('should return ValidationException if BETWEEN arguments are in the incorrect order', function (done) { assertValidation({ TableName: 'aaa', Key: {}, - Expected: {a: {ComparisonOperator: 'BETWEEN', AttributeValueList: [{S: 'b'}, {S: 'a'}]}}, + Expected: { a: { ComparisonOperator: 'BETWEEN', AttributeValueList: [ { S: 'b' }, { S: 'a' } ] } }, }, 'The BETWEEN condition was provided a range where the lower bound is greater than the upper bound', done) }) - it('should return ValidationException if ConditionExpression BETWEEN args have different types', function(done) { + it('should return ValidationException if ConditionExpression BETWEEN args have different types', function (done) { assertValidation({ TableName: 'aaa', Key: {}, ConditionExpression: 'a between :b and :a', - ExpressionAttributeValues: {':a': {S: 'a'}, ':b': {N: '1'}}, + ExpressionAttributeValues: { ':a': { S: 'a' }, ':b': { N: '1' } }, }, 'Invalid ConditionExpression: The BETWEEN operator requires same data type for lower and upper bounds; ' + 'lower bound operand: AttributeValue: {N:1}, upper bound operand: AttributeValue: {S:a}', done) }) - it('should return ValidationException if ConditionExpression BETWEEN args are in the incorrect order', function(done) { + it('should return ValidationException if ConditionExpression BETWEEN args are in the incorrect order', function (done) { assertValidation({ TableName: 'aaa', Key: {}, ConditionExpression: 'a between :b and :a', - ExpressionAttributeValues: {':a': {S: 'a'}, ':b': {S: 'b'}}, + ExpressionAttributeValues: { ':a': { S: 'a' }, ':b': { S: 'b' } }, }, 'Invalid ConditionExpression: The BETWEEN operator requires upper bound to be greater than or equal to lower bound; ' + 'lower bound operand: AttributeValue: {S:b}, upper bound operand: AttributeValue: {S:a}', done) }) - it('should return ValidationException if key does not match schema', function(done) { + it('should return ValidationException if key does not match schema', function (done) { async.forEach([ {}, - {b: {S: 'a'}}, - {a: {S: 'a'}, b: {S: 'a'}}, - {a: {B: 'abcd'}}, - {a: {N: '1'}}, - {a: {BOOL: true}}, - {a: {NULL: true}}, - {a: {SS: ['a']}}, - {a: {NS: ['1']}}, - {a: {BS: ['aaaa']}}, - {a: {M: {}}}, - {a: {L: []}}, - ], function(expr, cb) { - assertValidation({TableName: helpers.testHashTable, Key: expr}, + { b: { S: 'a' } }, + { a: { S: 'a' }, b: { S: 'a' } }, + { a: { B: 'abcd' } }, + { a: { N: '1' } }, + { a: { BOOL: true } }, + { a: { NULL: true } }, + { a: { SS: [ 'a' ] } }, + { a: { NS: [ '1' ] } }, + { a: { BS: [ 'aaaa' ] } }, + { a: { M: {} } }, + { a: { L: [] } }, + ], function (expr, cb) { + assertValidation({ TableName: helpers.testHashTable, Key: expr }, 'The provided key element does not match the schema', cb) }, done) }) - it('should return ValidationException if range key does not match schema', function(done) { - assertValidation({TableName: helpers.testRangeTable, Key: {a: {S: 'a'}}}, + it('should return ValidationException if range key does not match schema', function (done) { + assertValidation({ TableName: helpers.testRangeTable, Key: { a: { S: 'a' } } }, 'The provided key element does not match the schema', done) }) }) - describe('functionality', function() { + describe('functionality', function () { - it('should return nothing if item does not exist', function(done) { - request(opts({TableName: helpers.testHashTable, Key: {a: {S: helpers.randomString()}}}), function(err, res) { + it('should return nothing if item does not exist', function (done) { + request(opts({ TableName: helpers.testHashTable, Key: { a: { S: helpers.randomString() } } }), function (err, res) { if (err) return done(err) res.statusCode.should.equal(200) res.body.should.eql({}) @@ -460,32 +460,32 @@ describe('deleteItem', function() { }) }) - it('should return ConsumedCapacity if specified and item does not exist', function(done) { - var req = {TableName: helpers.testHashTable, Key: {a: {S: helpers.randomString()}}, ReturnConsumedCapacity: 'TOTAL'} - request(opts(req), function(err, res) { + it('should return ConsumedCapacity if specified and item does not exist', function (done) { + var req = { TableName: helpers.testHashTable, Key: { a: { S: helpers.randomString() } }, ReturnConsumedCapacity: 'TOTAL' } + request(opts(req), function (err, res) { if (err) return done(err) res.statusCode.should.equal(200) - res.body.should.eql({ConsumedCapacity: {CapacityUnits: 1, TableName: helpers.testHashTable}}) + res.body.should.eql({ ConsumedCapacity: { CapacityUnits: 1, TableName: helpers.testHashTable } }) req.ReturnConsumedCapacity = 'INDEXES' - request(opts(req), function(err, res) { + request(opts(req), function (err, res) { if (err) return done(err) res.statusCode.should.equal(200) - res.body.should.eql({ConsumedCapacity: {CapacityUnits: 1, Table: {CapacityUnits: 1}, TableName: helpers.testHashTable}}) + res.body.should.eql({ ConsumedCapacity: { CapacityUnits: 1, Table: { CapacityUnits: 1 }, TableName: helpers.testHashTable } }) done() }) }) }) - it('should delete item successfully', function(done) { - var item = {a: {S: helpers.randomString()}} - request(helpers.opts('PutItem', {TableName: helpers.testHashTable, Item: item}), function(err, res) { + it('should delete item successfully', function (done) { + var item = { a: { S: helpers.randomString() } } + request(helpers.opts('PutItem', { TableName: helpers.testHashTable, Item: item }), function (err, res) { if (err) return done(err) res.statusCode.should.equal(200) - request(opts({TableName: helpers.testHashTable, Key: {a: item.a}}), function(err, res) { + request(opts({ TableName: helpers.testHashTable, Key: { a: item.a } }), function (err, res) { if (err) return done(err) res.statusCode.should.equal(200) res.body.should.eql({}) - request(helpers.opts('GetItem', {TableName: helpers.testHashTable, Key: {a: item.a}, ConsistentRead: true}), function(err, res) { + request(helpers.opts('GetItem', { TableName: helpers.testHashTable, Key: { a: item.a }, ConsistentRead: true }), function (err, res) { if (err) return done(err) res.statusCode.should.equal(200) res.body.should.eql({}) @@ -495,58 +495,58 @@ describe('deleteItem', function() { }) }) - it('should delete item successfully and return old values', function(done) { - var item = {a: {S: helpers.randomString()}, b: {S: 'b'}} - request(helpers.opts('PutItem', {TableName: helpers.testHashTable, Item: item}), function(err, res) { + it('should delete item successfully and return old values', function (done) { + var item = { a: { S: helpers.randomString() }, b: { S: 'b' } } + request(helpers.opts('PutItem', { TableName: helpers.testHashTable, Item: item }), function (err, res) { if (err) return done(err) res.statusCode.should.equal(200) - request(opts({TableName: helpers.testHashTable, Key: {a: item.a}, ReturnValues: 'ALL_OLD'}), function(err, res) { + request(opts({ TableName: helpers.testHashTable, Key: { a: item.a }, ReturnValues: 'ALL_OLD' }), function (err, res) { if (err) return done(err) res.statusCode.should.equal(200) - res.body.should.eql({Attributes: item}) + res.body.should.eql({ Attributes: item }) done() }) }) }) - it('should return ConditionalCheckFailedException if expecting non-existent key to exist', function(done) { + it('should return ConditionalCheckFailedException if expecting non-existent key to exist', function (done) { async.forEach([ - {Expected: {a: {Value: {S: helpers.randomString()}}}}, - {ConditionExpression: 'a = :a', ExpressionAttributeValues: {':a': {S: helpers.randomString()}}}, - {ConditionExpression: '#a = :a', ExpressionAttributeNames: {'#a': 'a'}, ExpressionAttributeValues: {':a': {S: helpers.randomString()}}}, - ], function(deleteOpts, cb) { + { Expected: { a: { Value: { S: helpers.randomString() } } } }, + { ConditionExpression: 'a = :a', ExpressionAttributeValues: { ':a': { S: helpers.randomString() } } }, + { ConditionExpression: '#a = :a', ExpressionAttributeNames: { '#a': 'a' }, ExpressionAttributeValues: { ':a': { S: helpers.randomString() } } }, + ], function (deleteOpts, cb) { deleteOpts.TableName = helpers.testHashTable - deleteOpts.Key = {a: {S: helpers.randomString()}} + deleteOpts.Key = { a: { S: helpers.randomString() } } assertConditional(deleteOpts, cb) }, done) }) - it('should return ConditionalCheckFailedException if expecting existing key to not exist', function(done) { - var item = {a: {S: helpers.randomString()}} - request(helpers.opts('PutItem', {TableName: helpers.testHashTable, Item: item}), function(err) { + it('should return ConditionalCheckFailedException if expecting existing key to not exist', function (done) { + var item = { a: { S: helpers.randomString() } } + request(helpers.opts('PutItem', { TableName: helpers.testHashTable, Item: item }), function (err) { if (err) return done(err) async.forEach([ - {Expected: {a: {Exists: false}}}, - {ConditionExpression: 'attribute_not_exists(a)'}, - ], function(deleteOpts, cb) { + { Expected: { a: { Exists: false } } }, + { ConditionExpression: 'attribute_not_exists(a)' }, + ], function (deleteOpts, cb) { deleteOpts.TableName = helpers.testHashTable - deleteOpts.Key = {a: item.a} + deleteOpts.Key = { a: item.a } assertConditional(deleteOpts, cb) }, done) }) }) - it('should succeed if conditional key is different and exists is false', function(done) { - var item = {a: {S: helpers.randomString()}} - request(helpers.opts('PutItem', {TableName: helpers.testHashTable, Item: item}), function(err) { + it('should succeed if conditional key is different and exists is false', function (done) { + var item = { a: { S: helpers.randomString() } } + request(helpers.opts('PutItem', { TableName: helpers.testHashTable, Item: item }), function (err) { if (err) return done(err) async.forEach([ - {Expected: {a: {Exists: false}}}, - {ConditionExpression: 'attribute_not_exists(a)'}, - ], function(deleteOpts, cb) { + { Expected: { a: { Exists: false } } }, + { ConditionExpression: 'attribute_not_exists(a)' }, + ], function (deleteOpts, cb) { deleteOpts.TableName = helpers.testHashTable - deleteOpts.Key = {a: {S: helpers.randomString()}} - request(opts(deleteOpts), function(err, res) { + deleteOpts.Key = { a: { S: helpers.randomString() } } + request(opts(deleteOpts), function (err, res) { if (err) return cb(err) res.statusCode.should.equal(200) res.body.should.eql({}) @@ -556,18 +556,18 @@ describe('deleteItem', function() { }) }) - it('should succeed if conditional key is same and exists is true', function(done) { + it('should succeed if conditional key is same and exists is true', function (done) { async.forEach([ - {Expected: {a: {Value: {S: helpers.randomString()}}}}, - {ConditionExpression: 'a = :a', ExpressionAttributeValues: {':a': {S: helpers.randomString()}}}, - {ConditionExpression: '#a = :a', ExpressionAttributeNames: {'#a': 'a'}, ExpressionAttributeValues: {':a': {S: helpers.randomString()}}}, - ], function(deleteOpts, cb) { - var item = {a: deleteOpts.Expected ? deleteOpts.Expected.a.Value : deleteOpts.ExpressionAttributeValues[':a']} - request(helpers.opts('PutItem', {TableName: helpers.testHashTable, Item: item}), function(err) { + { Expected: { a: { Value: { S: helpers.randomString() } } } }, + { ConditionExpression: 'a = :a', ExpressionAttributeValues: { ':a': { S: helpers.randomString() } } }, + { ConditionExpression: '#a = :a', ExpressionAttributeNames: { '#a': 'a' }, ExpressionAttributeValues: { ':a': { S: helpers.randomString() } } }, + ], function (deleteOpts, cb) { + var item = { a: deleteOpts.Expected ? deleteOpts.Expected.a.Value : deleteOpts.ExpressionAttributeValues[':a'] } + request(helpers.opts('PutItem', { TableName: helpers.testHashTable, Item: item }), function (err) { if (err) return cb(err) deleteOpts.TableName = helpers.testHashTable deleteOpts.Key = item - request(opts(deleteOpts), function(err, res) { + request(opts(deleteOpts), function (err, res) { if (err) return cb(err) res.statusCode.should.equal(200) res.body.should.eql({}) @@ -577,17 +577,17 @@ describe('deleteItem', function() { }, done) }) - it('should succeed if expecting non-existant value to not exist', function(done) { + it('should succeed if expecting non-existant value to not exist', function (done) { async.forEach([ - {Expected: {b: {Exists: false}}, Key: {a: {S: helpers.randomString()}}}, - {ConditionExpression: 'attribute_not_exists(b)', Key: {a: {S: helpers.randomString()}}}, - {ConditionExpression: 'attribute_not_exists(#b)', ExpressionAttributeNames: {'#b': 'b'}, Key: {a: {S: helpers.randomString()}}}, - ], function(deleteOpts, cb) { + { Expected: { b: { Exists: false } }, Key: { a: { S: helpers.randomString() } } }, + { ConditionExpression: 'attribute_not_exists(b)', Key: { a: { S: helpers.randomString() } } }, + { ConditionExpression: 'attribute_not_exists(#b)', ExpressionAttributeNames: { '#b': 'b' }, Key: { a: { S: helpers.randomString() } } }, + ], function (deleteOpts, cb) { var item = deleteOpts.Key - request(helpers.opts('PutItem', {TableName: helpers.testHashTable, Item: item}), function(err) { + request(helpers.opts('PutItem', { TableName: helpers.testHashTable, Item: item }), function (err) { if (err) return cb(err) deleteOpts.TableName = helpers.testHashTable - request(opts(deleteOpts), function(err, res) { + request(opts(deleteOpts), function (err, res) { if (err) return cb(err) res.statusCode.should.equal(200) res.body.should.eql({}) @@ -597,35 +597,35 @@ describe('deleteItem', function() { }, done) }) - it('should return ConditionalCheckFailedException if expecting existing value to not exist', function(done) { - var item = {a: {S: helpers.randomString()}, b: {S: helpers.randomString()}} - request(helpers.opts('PutItem', {TableName: helpers.testHashTable, Item: item}), function(err) { + it('should return ConditionalCheckFailedException if expecting existing value to not exist', function (done) { + var item = { a: { S: helpers.randomString() }, b: { S: helpers.randomString() } } + request(helpers.opts('PutItem', { TableName: helpers.testHashTable, Item: item }), function (err) { if (err) return done(err) async.forEach([ - {Expected: {b: {Exists: false}}}, - {ConditionExpression: 'attribute_not_exists(b)'}, - {ConditionExpression: 'attribute_not_exists(#b)', ExpressionAttributeNames: {'#b': 'b'}}, - ], function(deleteOpts, cb) { + { Expected: { b: { Exists: false } } }, + { ConditionExpression: 'attribute_not_exists(b)' }, + { ConditionExpression: 'attribute_not_exists(#b)', ExpressionAttributeNames: { '#b': 'b' } }, + ], function (deleteOpts, cb) { deleteOpts.TableName = helpers.testHashTable - deleteOpts.Key = {a: item.a} + deleteOpts.Key = { a: item.a } assertConditional(deleteOpts, cb) }, done) }) }) - it('should succeed for multiple conditional checks if all are valid', function(done) { + it('should succeed for multiple conditional checks if all are valid', function (done) { async.forEach([ - {Expected: {a: {Value: {S: helpers.randomString()}}, b: {Exists: false}, c: {Value: {S: helpers.randomString()}}}}, - {ConditionExpression: 'a = :a AND attribute_not_exists(b) AND c = :c', ExpressionAttributeValues: {':a': {S: helpers.randomString()}, ':c': {S: helpers.randomString()}}}, - {ConditionExpression: '#a = :a AND attribute_not_exists(#b) AND #c = :c', ExpressionAttributeNames: {'#a': 'a', '#b': 'b', '#c': 'c'}, ExpressionAttributeValues: {':a': {S: helpers.randomString()}, ':c': {S: helpers.randomString()}}}, - ], function(deleteOpts, cb) { - var item = deleteOpts.Expected ? {a: deleteOpts.Expected.a.Value, c: deleteOpts.Expected.c.Value} : - {a: deleteOpts.ExpressionAttributeValues[':a'], c: deleteOpts.ExpressionAttributeValues[':c']} - request(helpers.opts('PutItem', {TableName: helpers.testHashTable, Item: item}), function(err) { + { Expected: { a: { Value: { S: helpers.randomString() } }, b: { Exists: false }, c: { Value: { S: helpers.randomString() } } } }, + { ConditionExpression: 'a = :a AND attribute_not_exists(b) AND c = :c', ExpressionAttributeValues: { ':a': { S: helpers.randomString() }, ':c': { S: helpers.randomString() } } }, + { ConditionExpression: '#a = :a AND attribute_not_exists(#b) AND #c = :c', ExpressionAttributeNames: { '#a': 'a', '#b': 'b', '#c': 'c' }, ExpressionAttributeValues: { ':a': { S: helpers.randomString() }, ':c': { S: helpers.randomString() } } }, + ], function (deleteOpts, cb) { + var item = deleteOpts.Expected ? { a: deleteOpts.Expected.a.Value, c: deleteOpts.Expected.c.Value } : + { a: deleteOpts.ExpressionAttributeValues[':a'], c: deleteOpts.ExpressionAttributeValues[':c'] } + request(helpers.opts('PutItem', { TableName: helpers.testHashTable, Item: item }), function (err) { if (err) return cb(err) deleteOpts.TableName = helpers.testHashTable - deleteOpts.Key = {a: item.a} - request(opts(deleteOpts), function(err, res) { + deleteOpts.Key = { a: item.a } + request(opts(deleteOpts), function (err, res) { if (err) return cb(err) res.statusCode.should.equal(200) res.body.should.eql({}) @@ -635,47 +635,47 @@ describe('deleteItem', function() { }, done) }) - it('should return ConditionalCheckFailedException for multiple conditional checks if one is invalid', function(done) { - var item = {a: {S: helpers.randomString()}, c: {S: helpers.randomString()}} - request(helpers.opts('PutItem', {TableName: helpers.testHashTable, Item: item}), function(err) { + it('should return ConditionalCheckFailedException for multiple conditional checks if one is invalid', function (done) { + var item = { a: { S: helpers.randomString() }, c: { S: helpers.randomString() } } + request(helpers.opts('PutItem', { TableName: helpers.testHashTable, Item: item }), function (err) { if (err) return done(err) async.forEach([ - {Expected: {a: {Value: item.a}, b: {Exists: false}, c: {Value: {S: helpers.randomString()}}}}, - {ConditionExpression: 'a = :a AND attribute_not_exists(b) AND c = :c', ExpressionAttributeValues: {':a': item.a, ':c': {S: helpers.randomString()}}}, - {ConditionExpression: '#a = :a AND attribute_not_exists(#b) AND #c = :c', ExpressionAttributeNames: {'#a': 'a', '#b': 'b', '#c': 'c'}, ExpressionAttributeValues: {':a': item.a, ':c': {S: helpers.randomString()}}}, - ], function(deleteOpts, cb) { + { Expected: { a: { Value: item.a }, b: { Exists: false }, c: { Value: { S: helpers.randomString() } } } }, + { ConditionExpression: 'a = :a AND attribute_not_exists(b) AND c = :c', ExpressionAttributeValues: { ':a': item.a, ':c': { S: helpers.randomString() } } }, + { ConditionExpression: '#a = :a AND attribute_not_exists(#b) AND #c = :c', ExpressionAttributeNames: { '#a': 'a', '#b': 'b', '#c': 'c' }, ExpressionAttributeValues: { ':a': item.a, ':c': { S: helpers.randomString() } } }, + ], function (deleteOpts, cb) { deleteOpts.TableName = helpers.testHashTable - deleteOpts.Key = {a: item.a} + deleteOpts.Key = { a: item.a } assertConditional(deleteOpts, cb) }, done) }) }) - it('should return ConsumedCapacity for small item', function(done) { + it('should return ConsumedCapacity for small item', function (done) { var a = helpers.randomString(), b = new Array(1010 - a.length).join('b'), - item = {a: {S: a}, b: {S: b}, c: {N: '12.3456'}, d: {B: 'AQI='}, e: {BS: ['AQI=', 'Ag==', 'AQ==']}} - request(helpers.opts('PutItem', {TableName: helpers.testHashTable, Item: item}), function(err, res) { + item = { a: { S: a }, b: { S: b }, c: { N: '12.3456' }, d: { B: 'AQI=' }, e: { BS: [ 'AQI=', 'Ag==', 'AQ==' ] } } + request(helpers.opts('PutItem', { TableName: helpers.testHashTable, Item: item }), function (err, res) { if (err) return done(err) res.statusCode.should.equal(200) - request(opts({TableName: helpers.testHashTable, Key: {a: item.a}, ReturnConsumedCapacity: 'TOTAL'}), function(err, res) { + request(opts({ TableName: helpers.testHashTable, Key: { a: item.a }, ReturnConsumedCapacity: 'TOTAL' }), function (err, res) { if (err) return done(err) res.statusCode.should.equal(200) - res.body.should.eql({ConsumedCapacity: {CapacityUnits: 1, TableName: helpers.testHashTable}}) + res.body.should.eql({ ConsumedCapacity: { CapacityUnits: 1, TableName: helpers.testHashTable } }) done() }) }) }) - it('should return ConsumedCapacity for larger item', function(done) { + it('should return ConsumedCapacity for larger item', function (done) { var a = helpers.randomString(), b = new Array(1012 - a.length).join('b'), - item = {a: {S: a}, b: {S: b}, c: {N: '12.3456'}, d: {B: 'AQI='}, e: {BS: ['AQI=', 'Ag==']}} - request(helpers.opts('PutItem', {TableName: helpers.testHashTable, Item: item}), function(err, res) { + item = { a: { S: a }, b: { S: b }, c: { N: '12.3456' }, d: { B: 'AQI=' }, e: { BS: [ 'AQI=', 'Ag==' ] } } + request(helpers.opts('PutItem', { TableName: helpers.testHashTable, Item: item }), function (err, res) { if (err) return done(err) res.statusCode.should.equal(200) - request(opts({TableName: helpers.testHashTable, Key: {a: item.a}, ReturnConsumedCapacity: 'TOTAL'}), function(err, res) { + request(opts({ TableName: helpers.testHashTable, Key: { a: item.a }, ReturnConsumedCapacity: 'TOTAL' }), function (err, res) { if (err) return done(err) res.statusCode.should.equal(200) - res.body.should.eql({ConsumedCapacity: {CapacityUnits: 2, TableName: helpers.testHashTable}}) + res.body.should.eql({ ConsumedCapacity: { CapacityUnits: 2, TableName: helpers.testHashTable } }) done() }) }) diff --git a/test/deleteTable.js b/test/deleteTable.js index 524e29e..3ba8db9 100644 --- a/test/deleteTable.js +++ b/test/deleteTable.js @@ -1,96 +1,96 @@ var should = require('should'), - helpers = require('./helpers') + helpers = require('./helpers') var target = 'DeleteTable', - request = helpers.request, - randomName = helpers.randomName, - opts = helpers.opts.bind(null, target), - assertType = helpers.assertType.bind(null, target), - assertValidation = helpers.assertValidation.bind(null, target), - assertNotFound = helpers.assertNotFound.bind(null, target), - assertInUse = helpers.assertInUse.bind(null, target) + request = helpers.request, + randomName = helpers.randomName, + opts = helpers.opts.bind(null, target), + assertType = helpers.assertType.bind(null, target), + assertValidation = helpers.assertValidation.bind(null, target), + assertNotFound = helpers.assertNotFound.bind(null, target), + assertInUse = helpers.assertInUse.bind(null, target) -describe('deleteTable', function() { +describe('deleteTable', function () { - describe('serializations', function() { + describe('serializations', function () { - it('should return SerializationException when TableName is not a string', function(done) { + it('should return SerializationException when TableName is not a string', function (done) { assertType('TableName', 'String', done) }) }) - describe('validations', function() { + describe('validations', function () { - it('should return ValidationException for no TableName', function(done) { + it('should return ValidationException for no TableName', function (done) { assertValidation({}, 'The parameter \'TableName\' is required but was not present in the request', done) }) - it('should return ValidationException for empty TableName', function(done) { - assertValidation({TableName: ''}, + it('should return ValidationException for empty TableName', function (done) { + assertValidation({ TableName: '' }, 'TableName must be at least 3 characters long and at most 255 characters long', done) }) - it('should return ValidationException for short TableName', function(done) { - assertValidation({TableName: 'a;'}, + it('should return ValidationException for short TableName', function (done) { + assertValidation({ TableName: 'a;' }, 'TableName must be at least 3 characters long and at most 255 characters long', done) }) - it('should return ValidationException for long TableName', function(done) { - assertValidation({TableName: new Array(256 + 1).join('a')}, + it('should return ValidationException for long TableName', function (done) { + assertValidation({ TableName: new Array(256 + 1).join('a') }, 'TableName must be at least 3 characters long and at most 255 characters long', done) }) - it('should return ValidationException for null attributes', function(done) { - assertValidation({TableName: 'abc;'}, + it('should return ValidationException for null attributes', function (done) { + assertValidation({ TableName: 'abc;' }, '1 validation error detected: ' + 'Value \'abc;\' at \'tableName\' failed to satisfy constraint: ' + 'Member must satisfy regular expression pattern: [a-zA-Z0-9_.-]+', done) }) - it('should return ResourceNotFoundException if table does not exist', function(done) { + it('should return ResourceNotFoundException if table does not exist', function (done) { var name = helpers.randomString() - assertNotFound({TableName: name}, 'Requested resource not found: Table: ' + name + ' not found', done) + assertNotFound({ TableName: name }, 'Requested resource not found: Table: ' + name + ' not found', done) }) }) - describe('functionality', function() { + describe('functionality', function () { - it('should eventually delete', function(done) { + it('should eventually delete', function (done) { this.timeout(100000) var table = { TableName: randomName(), - AttributeDefinitions: [{AttributeName: 'a', AttributeType: 'S'}], - KeySchema: [{KeyType: 'HASH', AttributeName: 'a'}], - ProvisionedThroughput: {ReadCapacityUnits: 1, WriteCapacityUnits: 1}, - GlobalSecondaryIndexes: [{ + AttributeDefinitions: [ { AttributeName: 'a', AttributeType: 'S' } ], + KeySchema: [ { KeyType: 'HASH', AttributeName: 'a' } ], + ProvisionedThroughput: { ReadCapacityUnits: 1, WriteCapacityUnits: 1 }, + GlobalSecondaryIndexes: [ { IndexName: 'abc', - KeySchema: [{AttributeName: 'a', KeyType: 'HASH'}], - ProvisionedThroughput: {ReadCapacityUnits: 1, WriteCapacityUnits: 1}, - Projection: {ProjectionType: 'KEYS_ONLY'}, - }], + KeySchema: [ { AttributeName: 'a', KeyType: 'HASH' } ], + ProvisionedThroughput: { ReadCapacityUnits: 1, WriteCapacityUnits: 1 }, + Projection: { ProjectionType: 'KEYS_ONLY' }, + } ], } - request(helpers.opts('CreateTable', table), function(err, res) { + request(helpers.opts('CreateTable', table), function (err, res) { if (err) return done(err) res.statusCode.should.equal(200) - assertInUse({TableName: table.TableName}, 'Attempt to change a resource which is still in use: ' + - 'Table is being created: ' + table.TableName, function(err) { + assertInUse({ TableName: table.TableName }, 'Attempt to change a resource which is still in use: ' + + 'Table is being created: ' + table.TableName, function (err) { if (err) return done(err) - helpers.waitUntilActive(table.TableName, function(err) { + helpers.waitUntilActive(table.TableName, function (err) { if (err) return done(err) - request(opts(table), function(err, res) { + request(opts(table), function (err, res) { if (err) return done(err) res.statusCode.should.equal(200) res.body.TableDescription.TableStatus.should.equal('DELETING') should.not.exist(res.body.TableDescription.GlobalSecondaryIndexes) - helpers.waitUntilDeleted(table.TableName, function(err, res) { + helpers.waitUntilDeleted(table.TableName, function (err, res) { if (err) return done(err) res.body.__type.should.equal('com.amazonaws.dynamodb.v20120810#ResourceNotFoundException') done() diff --git a/test/describeTable.js b/test/describeTable.js index 2dc98c3..729b13a 100644 --- a/test/describeTable.js +++ b/test/describeTable.js @@ -1,52 +1,52 @@ var helpers = require('./helpers') var target = 'DescribeTable', - assertType = helpers.assertType.bind(null, target), - assertValidation = helpers.assertValidation.bind(null, target), - assertNotFound = helpers.assertNotFound.bind(null, target) + assertType = helpers.assertType.bind(null, target), + assertValidation = helpers.assertValidation.bind(null, target), + assertNotFound = helpers.assertNotFound.bind(null, target) -describe('describeTable', function() { +describe('describeTable', function () { - describe('serializations', function() { + describe('serializations', function () { - it('should return SerializationException when TableName is not a string', function(done) { + it('should return SerializationException when TableName is not a string', function (done) { assertType('TableName', 'String', done) }) }) - describe('validations', function() { + describe('validations', function () { - it('should return ValidationException for no TableName', function(done) { + it('should return ValidationException for no TableName', function (done) { assertValidation({}, 'The parameter \'TableName\' is required but was not present in the request', done) }) - it('should return ValidationException for empty TableName', function(done) { - assertValidation({TableName: ''}, + it('should return ValidationException for empty TableName', function (done) { + assertValidation({ TableName: '' }, 'TableName must be at least 3 characters long and at most 255 characters long', done) }) - it('should return ValidationException for short TableName', function(done) { - assertValidation({TableName: 'a;'}, + it('should return ValidationException for short TableName', function (done) { + assertValidation({ TableName: 'a;' }, 'TableName must be at least 3 characters long and at most 255 characters long', done) }) - it('should return ValidationException for long TableName', function(done) { - assertValidation({TableName: new Array(256 + 1).join('a')}, + it('should return ValidationException for long TableName', function (done) { + assertValidation({ TableName: new Array(256 + 1).join('a') }, 'TableName must be at least 3 characters long and at most 255 characters long', done) }) - it('should return ValidationException for null attributes', function(done) { - assertValidation({TableName: 'abc;'}, + it('should return ValidationException for null attributes', function (done) { + assertValidation({ TableName: 'abc;' }, '1 validation error detected: ' + 'Value \'abc;\' at \'tableName\' failed to satisfy constraint: ' + 'Member must satisfy regular expression pattern: [a-zA-Z0-9_.-]+', done) }) - it('should return ResourceNotFoundException if table does not exist', function(done) { + it('should return ResourceNotFoundException if table does not exist', function (done) { var name = helpers.randomString() - assertNotFound({TableName: name}, 'Requested resource not found: Table: ' + name + ' not found', done) + assertNotFound({ TableName: name }, 'Requested resource not found: Table: ' + name + ' not found', done) }) }) diff --git a/test/describeTimeToLive.js b/test/describeTimeToLive.js index 3677682..d62931b 100644 --- a/test/describeTimeToLive.js +++ b/test/describeTimeToLive.js @@ -1,65 +1,65 @@ var helpers = require('./helpers') var target = 'DescribeTimeToLive', - request = helpers.request, - opts = helpers.opts.bind(null, target), - assertType = helpers.assertType.bind(null, target), - assertValidation = helpers.assertValidation.bind(null, target), - assertNotFound = helpers.assertNotFound.bind(null, target) + request = helpers.request, + opts = helpers.opts.bind(null, target), + assertType = helpers.assertType.bind(null, target), + assertValidation = helpers.assertValidation.bind(null, target), + assertNotFound = helpers.assertNotFound.bind(null, target) -describe('describeTimeToLive', function() { +describe('describeTimeToLive', function () { - describe('serializations', function() { + describe('serializations', function () { - it('should return SerializationException when TableName is not a string', function(done) { + it('should return SerializationException when TableName is not a string', function (done) { assertType('TableName', 'String', done) }) }) - describe('validations', function() { + describe('validations', function () { - it('should return ValidationException for no TableName', function(done) { + it('should return ValidationException for no TableName', function (done) { assertValidation({}, 'The parameter \'TableName\' is required but was not present in the request', done) }) - it('should return ValidationException for empty TableName', function(done) { - assertValidation({TableName: ''}, + it('should return ValidationException for empty TableName', function (done) { + assertValidation({ TableName: '' }, 'TableName must be at least 3 characters long and at most 255 characters long', done) }) - it('should return ValidationException for short TableName', function(done) { - assertValidation({TableName: 'a;'}, + it('should return ValidationException for short TableName', function (done) { + assertValidation({ TableName: 'a;' }, 'TableName must be at least 3 characters long and at most 255 characters long', done) }) - it('should return ValidationException for long TableName', function(done) { - assertValidation({TableName: new Array(256 + 1).join('a')}, + it('should return ValidationException for long TableName', function (done) { + assertValidation({ TableName: new Array(256 + 1).join('a') }, 'TableName must be at least 3 characters long and at most 255 characters long', done) }) - it('should return ValidationException for null attributes', function(done) { - assertValidation({TableName: 'abc;'}, + it('should return ValidationException for null attributes', function (done) { + assertValidation({ TableName: 'abc;' }, '1 validation error detected: ' + 'Value \'abc;\' at \'tableName\' failed to satisfy constraint: ' + 'Member must satisfy regular expression pattern: [a-zA-Z0-9_.-]+', done) }) - it('should return ResourceNotFoundException if table does not exist', function(done) { + it('should return ResourceNotFoundException if table does not exist', function (done) { var name = helpers.randomString() - assertNotFound({TableName: name}, 'Requested resource not found: Table: ' + name + ' not found', done) + assertNotFound({ TableName: name }, 'Requested resource not found: Table: ' + name + ' not found', done) }) }) - describe('functionality', function() { + describe('functionality', function () { - it('should succeed if table exists', function(done) { - request(opts({TableName: helpers.testHashTable}), function(err, res) { + it('should succeed if table exists', function (done) { + request(opts({ TableName: helpers.testHashTable }), function (err, res) { if (err) return done(err) res.statusCode.should.equal(200) - res.body.should.eql({TimeToLiveDescription: {TimeToLiveStatus: 'DISABLED'}}) + res.body.should.eql({ TimeToLiveDescription: { TimeToLiveStatus: 'DISABLED' } }) done() }) }) diff --git a/test/getItem.js b/test/getItem.js index e07014a..0ad0058 100644 --- a/test/getItem.js +++ b/test/getItem.js @@ -1,60 +1,60 @@ var async = require('async'), - helpers = require('./helpers') + helpers = require('./helpers') var target = 'GetItem', - request = helpers.request, - randomName = helpers.randomName, - opts = helpers.opts.bind(null, target), - assertType = helpers.assertType.bind(null, target), - assertValidation = helpers.assertValidation.bind(null, target), - assertNotFound = helpers.assertNotFound.bind(null, target) + request = helpers.request, + randomName = helpers.randomName, + opts = helpers.opts.bind(null, target), + assertType = helpers.assertType.bind(null, target), + assertValidation = helpers.assertValidation.bind(null, target), + assertNotFound = helpers.assertNotFound.bind(null, target) -describe('getItem', function() { +describe('getItem', function () { - describe('serializations', function() { + describe('serializations', function () { - it('should return SerializationException when TableName is not a string', function(done) { + it('should return SerializationException when TableName is not a string', function (done) { assertType('TableName', 'String', done) }) - it('should return SerializationException when Key is not a map', function(done) { + it('should return SerializationException when Key is not a map', function (done) { assertType('Key', 'Map', done) }) - it('should return SerializationException when Key.Attr is not an attr struct', function(done) { + it('should return SerializationException when Key.Attr is not an attr struct', function (done) { this.timeout(60000) assertType('Key.Attr', 'AttrStruct', done) }) - it('should return SerializationException when AttributesToGet is not a list', function(done) { + it('should return SerializationException when AttributesToGet is not a list', function (done) { assertType('AttributesToGet', 'List', done) }) - it('should return SerializationException when ConsistentRead is not a boolean', function(done) { + it('should return SerializationException when ConsistentRead is not a boolean', function (done) { assertType('ConsistentRead', 'Boolean', done) }) - it('should return SerializationException when ReturnConsumedCapacity is not a string', function(done) { + it('should return SerializationException when ReturnConsumedCapacity is not a string', function (done) { assertType('ReturnConsumedCapacity', 'String', done) }) - it('should return SerializationException when ExpressionAttributeNames is not a map', function(done) { + it('should return SerializationException when ExpressionAttributeNames is not a map', function (done) { assertType('ExpressionAttributeNames', 'Map', done) }) - it('should return SerializationException when ExpressionAttributeNames.Attr is not a string', function(done) { + it('should return SerializationException when ExpressionAttributeNames.Attr is not a string', function (done) { assertType('ExpressionAttributeNames.Attr', 'String', done) }) - it('should return SerializationException when ProjectionExpression is not a string', function(done) { + it('should return SerializationException when ProjectionExpression is not a string', function (done) { assertType('ProjectionExpression', 'String', done) }) }) - describe('validations', function() { + describe('validations', function () { - it('should return ValidationException for no TableName', function(done) { + it('should return ValidationException for no TableName', function (done) { assertValidation({}, [ 'Value null at \'key\' failed to satisfy constraint: ' + 'Member must not be null', @@ -63,8 +63,8 @@ describe('getItem', function() { ], done) }) - it('should return ValidationException for empty TableName', function(done) { - assertValidation({TableName: ''}, [ + it('should return ValidationException for empty TableName', function (done) { + assertValidation({ TableName: '' }, [ 'Value \'\' at \'tableName\' failed to satisfy constraint: ' + 'Member must satisfy regular expression pattern: [a-zA-Z0-9_.-]+', 'Value \'\' at \'tableName\' failed to satisfy constraint: ' + @@ -74,8 +74,8 @@ describe('getItem', function() { ], done) }) - it('should return ValidationException for short TableName', function(done) { - assertValidation({TableName: 'a;'}, [ + it('should return ValidationException for short TableName', function (done) { + assertValidation({ TableName: 'a;' }, [ 'Value \'a;\' at \'tableName\' failed to satisfy constraint: ' + 'Member must satisfy regular expression pattern: [a-zA-Z0-9_.-]+', 'Value \'a;\' at \'tableName\' failed to satisfy constraint: ' + @@ -85,9 +85,9 @@ describe('getItem', function() { ], done) }) - it('should return ValidationException for long TableName', function(done) { + it('should return ValidationException for long TableName', function (done) { var name = new Array(256 + 1).join('a') - assertValidation({TableName: name}, [ + assertValidation({ TableName: name }, [ 'Value null at \'key\' failed to satisfy constraint: ' + 'Member must not be null', 'Value \'' + name + '\' at \'tableName\' failed to satisfy constraint: ' + @@ -95,8 +95,8 @@ describe('getItem', function() { ], done) }) - it('should return ValidationException for incorrect attributes', function(done) { - assertValidation({TableName: 'abc;', ReturnConsumedCapacity: 'hi', AttributesToGet: []}, [ + it('should return ValidationException for incorrect attributes', function (done) { + assertValidation({ TableName: 'abc;', ReturnConsumedCapacity: 'hi', AttributesToGet: [] }, [ 'Value \'[]\' at \'attributesToGet\' failed to satisfy constraint: ' + 'Member must have length greater than or equal to 1', 'Value \'hi\' at \'returnConsumedCapacity\' failed to satisfy constraint: ' + @@ -108,83 +108,83 @@ describe('getItem', function() { ], done) }) - it('should return ValidationException if expression and non-expression', function(done) { + it('should return ValidationException if expression and non-expression', function (done) { assertValidation({ TableName: 'abc', - Key: {a: {}}, - AttributesToGet: ['a'], + Key: { a: {} }, + AttributesToGet: [ 'a' ], ExpressionAttributeNames: {}, ProjectionExpression: '', }, 'Can not use both expression and non-expression parameters in the same request: ' + 'Non-expression parameters: {AttributesToGet} Expression parameters: {ProjectionExpression}', done) }) - it('should return ValidationException if ExpressionAttributeNames but no ProjectionExpression', function(done) { + it('should return ValidationException if ExpressionAttributeNames but no ProjectionExpression', function (done) { assertValidation({ TableName: 'abc', - Key: {a: {}}, - AttributesToGet: ['a'], + Key: { a: {} }, + AttributesToGet: [ 'a' ], ExpressionAttributeNames: {}, }, 'ExpressionAttributeNames can only be specified when using expressions', done) }) - it('should return ValidationException for unsupported datatype in Key', function(done) { + it('should return ValidationException for unsupported datatype in Key', function (done) { async.forEach([ {}, - {a: ''}, - {M: {a: {}}}, - {L: [{}]}, - {L: [{a: {}}]}, - ], function(expr, cb) { - assertValidation({TableName: 'abc', Key: {a: expr}, ProjectionExpression: '', ExpressionAttributeNames: {}}, + { a: '' }, + { M: { a: {} } }, + { L: [ {} ] }, + { L: [ { a: {} } ] }, + ], function (expr, cb) { + assertValidation({ TableName: 'abc', Key: { a: expr }, ProjectionExpression: '', ExpressionAttributeNames: {} }, 'Supplied AttributeValue is empty, must contain exactly one of the supported datatypes', cb) }, done) }) - it('should return ValidationException for invalid values in Key', function(done) { + it('should return ValidationException for invalid values in Key', function (done) { async.forEach([ - [{NULL: 'no'}, 'Null attribute value types must have the value of true'], - [{SS: []}, 'An string set may not be empty'], - [{NS: []}, 'An number set may not be empty'], - [{BS: []}, 'Binary sets should not be empty'], - [{SS: ['a', 'a']}, 'Input collection [a, a] contains duplicates.'], - [{BS: ['Yg==', 'Yg==']}, 'Input collection [Yg==, Yg==]of type BS contains duplicates.'], - ], function(expr, cb) { - assertValidation({TableName: 'abc', Key: {a: expr[0]}, AttributesToGet: ['a', 'a']}, + [ { NULL: 'no' }, 'Null attribute value types must have the value of true' ], + [ { SS: [] }, 'An string set may not be empty' ], + [ { NS: [] }, 'An number set may not be empty' ], + [ { BS: [] }, 'Binary sets should not be empty' ], + [ { SS: [ 'a', 'a' ] }, 'Input collection [a, a] contains duplicates.' ], + [ { BS: [ 'Yg==', 'Yg==' ] }, 'Input collection [Yg==, Yg==]of type BS contains duplicates.' ], + ], function (expr, cb) { + assertValidation({ TableName: 'abc', Key: { a: expr[0] }, AttributesToGet: [ 'a', 'a' ] }, 'One or more parameter values were invalid: ' + expr[1], cb) }, done) }) - it('should return ValidationException for empty/invalid numbers in Key', function(done) { + it('should return ValidationException for empty/invalid numbers in Key', function (done) { async.forEach([ - [{S: '', N: ''}, 'The parameter cannot be converted to a numeric value'], - [{S: 'a', N: ''}, 'The parameter cannot be converted to a numeric value'], - [{S: 'a', N: 'b'}, 'The parameter cannot be converted to a numeric value: b'], - [{NS: ['1', '']}, 'The parameter cannot be converted to a numeric value'], - [{NS: ['1', 'b']}, 'The parameter cannot be converted to a numeric value: b'], - [{NS: ['1', '1']}, 'Input collection contains duplicates'], - [{N: '123456789012345678901234567890123456789'}, 'Attempting to store more than 38 significant digits in a Number'], - [{N: '-1.23456789012345678901234567890123456789'}, 'Attempting to store more than 38 significant digits in a Number'], - [{N: '1e126'}, 'Number overflow. Attempting to store a number with magnitude larger than supported range'], - [{N: '-1e126'}, 'Number overflow. Attempting to store a number with magnitude larger than supported range'], - [{N: '1e-131'}, 'Number underflow. Attempting to store a number with magnitude smaller than supported range'], - [{N: '-1e-131'}, 'Number underflow. Attempting to store a number with magnitude smaller than supported range'], - ], function(expr, cb) { - assertValidation({TableName: 'abc', Key: {a: expr[0]}}, expr[1], cb) + [ { S: '', N: '' }, 'The parameter cannot be converted to a numeric value' ], + [ { S: 'a', N: '' }, 'The parameter cannot be converted to a numeric value' ], + [ { S: 'a', N: 'b' }, 'The parameter cannot be converted to a numeric value: b' ], + [ { NS: [ '1', '' ] }, 'The parameter cannot be converted to a numeric value' ], + [ { NS: [ '1', 'b' ] }, 'The parameter cannot be converted to a numeric value: b' ], + [ { NS: [ '1', '1' ] }, 'Input collection contains duplicates' ], + [ { N: '123456789012345678901234567890123456789' }, 'Attempting to store more than 38 significant digits in a Number' ], + [ { N: '-1.23456789012345678901234567890123456789' }, 'Attempting to store more than 38 significant digits in a Number' ], + [ { N: '1e126' }, 'Number overflow. Attempting to store a number with magnitude larger than supported range' ], + [ { N: '-1e126' }, 'Number overflow. Attempting to store a number with magnitude larger than supported range' ], + [ { N: '1e-131' }, 'Number underflow. Attempting to store a number with magnitude smaller than supported range' ], + [ { N: '-1e-131' }, 'Number underflow. Attempting to store a number with magnitude smaller than supported range' ], + ], function (expr, cb) { + assertValidation({ TableName: 'abc', Key: { a: expr[0] } }, expr[1], cb) }, done) }) - it('should return ValidationException for multiple datatypes in Key', function(done) { - assertValidation({TableName: 'abc', Key: {'a': {S: 'a', N: '1'}}}, + it('should return ValidationException for multiple datatypes in Key', function (done) { + assertValidation({ TableName: 'abc', Key: { 'a': { S: 'a', N: '1' } } }, 'Supplied AttributeValue has more than one datatypes set, must contain exactly one of the supported datatypes', done) }) - it('should return ValidationException duplicate values in AttributesToGet', function(done) { - assertValidation({TableName: 'abc', Key: {}, AttributesToGet: ['a', 'a']}, + it('should return ValidationException duplicate values in AttributesToGet', function (done) { + assertValidation({ TableName: 'abc', Key: {}, AttributesToGet: [ 'a', 'a' ] }, 'One or more parameter values were invalid: Duplicate value in attribute name: a', done) }) - it('should return ValidationException for empty ExpressionAttributeNames', function(done) { + it('should return ValidationException for empty ExpressionAttributeNames', function (done) { assertValidation({ TableName: 'abc', Key: {}, @@ -193,16 +193,16 @@ describe('getItem', function() { }, 'ExpressionAttributeNames must not be empty', done) }) - it('should return ValidationException for invalid ExpressionAttributeNames', function(done) { + it('should return ValidationException for invalid ExpressionAttributeNames', function (done) { assertValidation({ TableName: 'abc', Key: {}, - ExpressionAttributeNames: {'a': 'a'}, + ExpressionAttributeNames: { 'a': 'a' }, ProjectionExpression: '', }, 'ExpressionAttributeNames contains invalid key: Syntax error; key: "a"', done) }) - it('should return ValidationException for empty ProjectionExpression', function(done) { + it('should return ValidationException for empty ProjectionExpression', function (done) { assertValidation({ TableName: 'abc', Key: {}, @@ -210,7 +210,7 @@ describe('getItem', function() { }, 'Invalid ProjectionExpression: The expression can not be empty;', done) }) - it('should return ValidationException for syntax error in ProjectionExpression', function(done) { + it('should return ValidationException for syntax error in ProjectionExpression', function (done) { async.forEach([ 'whatever(stuff)', ':a', @@ -223,7 +223,7 @@ describe('getItem', function() { '(a),(b)', '(a,b)', 'a-b', - ], function(expr, cb) { + ], function (expr, cb) { assertValidation({ TableName: 'abc', Key: {}, @@ -232,11 +232,11 @@ describe('getItem', function() { }, done) }) - it('should return ValidationException for reserved keywords in ProjectionExpression', function(done) { + it('should return ValidationException for reserved keywords in ProjectionExpression', function (done) { async.forEach([ 'a.abORt', '#a,ABSoLUTE', - ], function(expr, cb) { + ], function (expr, cb) { assertValidation({ TableName: 'abc', Key: {}, @@ -245,10 +245,10 @@ describe('getItem', function() { }, done) }) - it('should return ValidationException for missing names in ProjectionExpression', function(done) { + it('should return ValidationException for missing names in ProjectionExpression', function (done) { async.forEach([ 'a,b,a,#a', - ], function(expr, cb) { + ], function (expr, cb) { assertValidation({ TableName: 'abc', Key: {}, @@ -257,147 +257,147 @@ describe('getItem', function() { }, done) }) - it('should return ValidationException for overlapping paths in ProjectionExpression', function(done) { + it('should return ValidationException for overlapping paths in ProjectionExpression', function (done) { async.forEach([ - ['b[1], b.a, #a.b, a', '[a, b]', '[a]'], - ['a, #a[1]', '[a]', '[a, [1]]'], + [ 'b[1], b.a, #a.b, a', '[a, b]', '[a]' ], + [ 'a, #a[1]', '[a]', '[a, [1]]' ], // TODO: This changed at some point, now conflicts with [b] instead of [a]? // ['a,b,a', '[a]', '[b]'], - ], function(expr, cb) { + ], function (expr, cb) { assertValidation({ TableName: 'abc', Key: {}, ProjectionExpression: expr[0], - ExpressionAttributeNames: {'#a': 'a'}, + ExpressionAttributeNames: { '#a': 'a' }, }, 'Invalid ProjectionExpression: Two document paths overlap with each other; ' + 'must remove or rewrite one of these paths; path one: ' + expr[1] + ', path two: ' + expr[2], cb) }, done) }) - it('should return ValidationException for conflicting paths in ProjectionExpression', function(done) { + it('should return ValidationException for conflicting paths in ProjectionExpression', function (done) { async.forEach([ - ['a.b, #a[1], #b', '[a, b]', '[a, [1]]'], - ['a.b[1], #a[1], #b', '[a, b, [1]]', '[a, [1]]'], - ['a[3].b, #a.#b.b', '[a, [3], b]', '[a, [3], b]'], - ], function(expr, cb) { + [ 'a.b, #a[1], #b', '[a, b]', '[a, [1]]' ], + [ 'a.b[1], #a[1], #b', '[a, b, [1]]', '[a, [1]]' ], + [ 'a[3].b, #a.#b.b', '[a, [3], b]', '[a, [3], b]' ], + ], function (expr, cb) { assertValidation({ TableName: 'abc', Key: {}, ProjectionExpression: expr[0], - ExpressionAttributeNames: {'#a': 'a', '#b': '[3]'}, + ExpressionAttributeNames: { '#a': 'a', '#b': '[3]' }, }, 'Invalid ProjectionExpression: Two document paths conflict with each other; ' + 'must remove or rewrite one of these paths; path one: ' + expr[1] + ', path two: ' + expr[2], cb) }, done) }) - it('should return ValidationException for unused names in ProjectionExpression', function(done) { + it('should return ValidationException for unused names in ProjectionExpression', function (done) { async.forEach([ 'a', 'a,b', - ], function(expr, cb) { + ], function (expr, cb) { assertValidation({ TableName: 'abc', Key: {}, ProjectionExpression: expr, - ExpressionAttributeNames: {'#a': 'a', '#b': 'b'}, + ExpressionAttributeNames: { '#a': 'a', '#b': 'b' }, }, 'Value provided in ExpressionAttributeNames unused in expressions: keys: {#a, #b}', cb) }, done) }) - it('should return ResourceNotFoundException if key is empty and table does not exist', function(done) { - assertNotFound({TableName: helpers.randomString(), Key: {}}, + it('should return ResourceNotFoundException if key is empty and table does not exist', function (done) { + assertNotFound({ TableName: helpers.randomString(), Key: {} }, 'Requested resource not found', done) }) - it('should return ValidationException if key does not match schema', function(done) { + it('should return ValidationException if key does not match schema', function (done) { async.forEach([ {}, - {b: {S: 'a'}}, - {a: {S: 'a'}, b: {S: 'a'}}, - {a: {B: 'abcd'}}, - {a: {N: '1'}}, - {a: {BOOL: true}}, - {a: {NULL: true}}, - {a: {SS: ['a']}}, - {a: {NS: ['1']}}, - {a: {BS: ['aaaa']}}, - {a: {M: {}}}, - {a: {L: []}}, - ], function(expr, cb) { - assertValidation({TableName: helpers.testHashTable, Key: expr}, + { b: { S: 'a' } }, + { a: { S: 'a' }, b: { S: 'a' } }, + { a: { B: 'abcd' } }, + { a: { N: '1' } }, + { a: { BOOL: true } }, + { a: { NULL: true } }, + { a: { SS: [ 'a' ] } }, + { a: { NS: [ '1' ] } }, + { a: { BS: [ 'aaaa' ] } }, + { a: { M: {} } }, + { a: { L: [] } }, + ], function (expr, cb) { + assertValidation({ TableName: helpers.testHashTable, Key: expr }, 'The provided key element does not match the schema', cb) }, done) }) - it('should return ValidationException if range key does not match schema', function(done) { - assertValidation({TableName: helpers.testRangeTable, Key: {a: {S: 'a'}}}, + it('should return ValidationException if range key does not match schema', function (done) { + assertValidation({ TableName: helpers.testRangeTable, Key: { a: { S: 'a' } } }, 'The provided key element does not match the schema', done) }) - it('should return ValidationException if string key has empty string', function(done) { - assertValidation({TableName: helpers.testHashTable, Key: {a: {S: ''}}}, + it('should return ValidationException if string key has empty string', function (done) { + assertValidation({ TableName: helpers.testHashTable, Key: { a: { S: '' } } }, 'One or more parameter values were invalid: ' + 'The AttributeValue for a key attribute cannot contain an empty string value. Key: a', done) }) - it('should return ValidationException if binary key has empty string', function(done) { - assertValidation({TableName: helpers.testRangeBTable, Key: {a: {S: 'a'}, b: {B: ''}}}, + it('should return ValidationException if binary key has empty string', function (done) { + assertValidation({ TableName: helpers.testRangeBTable, Key: { a: { S: 'a' }, b: { B: '' } } }, 'One or more parameter values were invalid: ' + 'The AttributeValue for a key attribute cannot contain an empty binary value. Key: b', done) }) - it('should return ValidationException if hash key is too big', function(done) { + it('should return ValidationException if hash key is too big', function (done) { var keyStr = (helpers.randomString() + new Array(2048).join('a')).slice(0, 2049) - assertValidation({TableName: helpers.testHashTable, Key: {a: {S: keyStr}}}, + assertValidation({ TableName: helpers.testHashTable, Key: { a: { S: keyStr } } }, 'One or more parameter values were invalid: ' + 'Size of hashkey has exceeded the maximum size limit of2048 bytes', done) }) - it('should return ValidationException if range key is too big', function(done) { + it('should return ValidationException if range key is too big', function (done) { var keyStr = (helpers.randomString() + new Array(1024).join('a')).slice(0, 1025) - assertValidation({TableName: helpers.testRangeTable, Key: {a: {S: 'a'}, b: {S: keyStr}}}, + assertValidation({ TableName: helpers.testRangeTable, Key: { a: { S: 'a' }, b: { S: keyStr } } }, 'One or more parameter values were invalid: ' + 'Aggregated size of all range keys has exceeded the size limit of 1024 bytes', done) }) - it('should return ValidationException for non-scalar key access in ProjectionExpression', function(done) { + it('should return ValidationException for non-scalar key access in ProjectionExpression', function (done) { async.forEach([ '#a.b.c', '#a[0]', - ], function(expr, cb) { + ], function (expr, cb) { assertValidation({ TableName: helpers.testHashTable, - Key: {a: {S: helpers.randomString()}}, + Key: { a: { S: helpers.randomString() } }, ProjectionExpression: expr, - ExpressionAttributeNames: {'#a': 'a'}, + ExpressionAttributeNames: { '#a': 'a' }, }, 'Key attributes must be scalars; list random access \'[]\' and map lookup \'.\' are not allowed: Key: a', cb) }, done) }) - it('should return ValidationException for non-scalar index access in ProjectionExpression', function(done) { + it('should return ValidationException for non-scalar index access in ProjectionExpression', function (done) { async.forEach([ '#d.b.c', '#d[0]', - ], function(expr, cb) { + ], function (expr, cb) { assertValidation({ TableName: helpers.testRangeTable, - Key: {a: {S: helpers.randomString()}, b: {S: helpers.randomString()}}, + Key: { a: { S: helpers.randomString() }, b: { S: helpers.randomString() } }, ProjectionExpression: expr, - ExpressionAttributeNames: {'#d': 'd'}, + ExpressionAttributeNames: { '#d': 'd' }, }, 'Key attributes must be scalars; list random access \'[]\' and map lookup \'.\' are not allowed: IndexKey: d', cb) }, done) }) - it('should return ResourceNotFoundException if table is being created', function(done) { + it('should return ResourceNotFoundException if table is being created', function (done) { var table = { TableName: randomName(), - AttributeDefinitions: [{AttributeName: 'a', AttributeType: 'S'}], - KeySchema: [{KeyType: 'HASH', AttributeName: 'a'}], - ProvisionedThroughput: {ReadCapacityUnits: 1, WriteCapacityUnits: 1}, + AttributeDefinitions: [ { AttributeName: 'a', AttributeType: 'S' } ], + KeySchema: [ { KeyType: 'HASH', AttributeName: 'a' } ], + ProvisionedThroughput: { ReadCapacityUnits: 1, WriteCapacityUnits: 1 }, } - request(helpers.opts('CreateTable', table), function(err) { + request(helpers.opts('CreateTable', table), function (err) { if (err) return done(err) - assertNotFound({TableName: table.TableName, Key: {a: {S: 'a'}}}, + assertNotFound({ TableName: table.TableName, Key: { a: { S: 'a' } } }, 'Requested resource not found', done) helpers.deleteWhenActive(table.TableName) }) @@ -405,21 +405,21 @@ describe('getItem', function() { }) - describe('functionality', function() { + describe('functionality', function () { - var hashItem = {a: {S: helpers.randomString()}, b: {S: 'a'}, g: {N: '23'}}, - rangeItem = {a: {S: helpers.randomString()}, b: {S: helpers.randomString()}, g: {N: '23'}} + var hashItem = { a: { S: helpers.randomString() }, b: { S: 'a' }, g: { N: '23' } }, + rangeItem = { a: { S: helpers.randomString() }, b: { S: helpers.randomString() }, g: { N: '23' } } - before(function(done) { + before(function (done) { var putItems = [ - {TableName: helpers.testHashTable, Item: hashItem}, - {TableName: helpers.testRangeTable, Item: rangeItem}, + { TableName: helpers.testHashTable, Item: hashItem }, + { TableName: helpers.testRangeTable, Item: rangeItem }, ] - async.forEach(putItems, function(putItem, cb) { request(helpers.opts('PutItem', putItem), cb) }, done) + async.forEach(putItems, function (putItem, cb) { request(helpers.opts('PutItem', putItem), cb) }, done) }) - it('should return empty response if key does not exist', function(done) { - request(opts({TableName: helpers.testHashTable, Key: {a: {S: helpers.randomString()}}}), function(err, res) { + it('should return empty response if key does not exist', function (done) { + request(opts({ TableName: helpers.testHashTable, Key: { a: { S: helpers.randomString() } } }), function (err, res) { if (err) return done(err) res.statusCode.should.equal(200) res.body.should.eql({}) @@ -427,190 +427,190 @@ describe('getItem', function() { }) }) - it('should return ConsumedCapacity if specified', function(done) { - var req = {TableName: helpers.testHashTable, Key: {a: {S: helpers.randomString()}}, ReturnConsumedCapacity: 'TOTAL'} - request(opts(req), function(err, res) { + it('should return ConsumedCapacity if specified', function (done) { + var req = { TableName: helpers.testHashTable, Key: { a: { S: helpers.randomString() } }, ReturnConsumedCapacity: 'TOTAL' } + request(opts(req), function (err, res) { if (err) return done(err) res.statusCode.should.equal(200) - res.body.should.eql({ConsumedCapacity: {CapacityUnits: 0.5, TableName: helpers.testHashTable}}) + res.body.should.eql({ ConsumedCapacity: { CapacityUnits: 0.5, TableName: helpers.testHashTable } }) req.ReturnConsumedCapacity = 'INDEXES' - request(opts(req), function(err, res) { + request(opts(req), function (err, res) { if (err) return done(err) res.statusCode.should.equal(200) - res.body.should.eql({ConsumedCapacity: {CapacityUnits: 0.5, Table: {CapacityUnits: 0.5}, TableName: helpers.testHashTable}}) + res.body.should.eql({ ConsumedCapacity: { CapacityUnits: 0.5, Table: { CapacityUnits: 0.5 }, TableName: helpers.testHashTable } }) done() }) }) }) - it('should return full ConsumedCapacity if specified', function(done) { - var req = {TableName: helpers.testHashTable, Key: {a: {S: helpers.randomString()}}, ReturnConsumedCapacity: 'TOTAL', ConsistentRead: true} - request(opts(req), function(err, res) { + it('should return full ConsumedCapacity if specified', function (done) { + var req = { TableName: helpers.testHashTable, Key: { a: { S: helpers.randomString() } }, ReturnConsumedCapacity: 'TOTAL', ConsistentRead: true } + request(opts(req), function (err, res) { if (err) return done(err) res.statusCode.should.equal(200) - res.body.should.eql({ConsumedCapacity: {CapacityUnits: 1, TableName: helpers.testHashTable}}) + res.body.should.eql({ ConsumedCapacity: { CapacityUnits: 1, TableName: helpers.testHashTable } }) req.ReturnConsumedCapacity = 'INDEXES' - request(opts(req), function(err, res) { + request(opts(req), function (err, res) { if (err) return done(err) res.statusCode.should.equal(200) - res.body.should.eql({ConsumedCapacity: {CapacityUnits: 1, Table: {CapacityUnits: 1}, TableName: helpers.testHashTable}}) + res.body.should.eql({ ConsumedCapacity: { CapacityUnits: 1, Table: { CapacityUnits: 1 }, TableName: helpers.testHashTable } }) done() }) }) }) - it('should return object by hash key', function(done) { - request(opts({TableName: helpers.testHashTable, Key: {a: hashItem.a}, ConsistentRead: true}), function(err, res) { + it('should return object by hash key', function (done) { + request(opts({ TableName: helpers.testHashTable, Key: { a: hashItem.a }, ConsistentRead: true }), function (err, res) { if (err) return done(err) res.statusCode.should.equal(200) - res.body.should.eql({Item: hashItem}) + res.body.should.eql({ Item: hashItem }) done() }) }) - it('should return object by range key', function(done) { - request(opts({TableName: helpers.testRangeTable, Key: {a: rangeItem.a, b: rangeItem.b}, ConsistentRead: true}), function(err, res) { + it('should return object by range key', function (done) { + request(opts({ TableName: helpers.testRangeTable, Key: { a: rangeItem.a, b: rangeItem.b }, ConsistentRead: true }), function (err, res) { if (err) return done(err) res.statusCode.should.equal(200) - res.body.should.eql({Item: rangeItem}) + res.body.should.eql({ Item: rangeItem }) done() }) }) - it('should only return requested attributes', function(done) { + it('should only return requested attributes', function (done) { async.forEach([ - {AttributesToGet: ['b', 'g']}, - {ProjectionExpression: 'b, g'}, - {ProjectionExpression: '#b, #g', ExpressionAttributeNames: {'#b': 'b', '#g': 'g'}}, - ], function(getOpts, cb) { + { AttributesToGet: [ 'b', 'g' ] }, + { ProjectionExpression: 'b, g' }, + { ProjectionExpression: '#b, #g', ExpressionAttributeNames: { '#b': 'b', '#g': 'g' } }, + ], function (getOpts, cb) { getOpts.TableName = helpers.testHashTable - getOpts.Key = {a: hashItem.a} + getOpts.Key = { a: hashItem.a } getOpts.ConsistentRead = true - request(opts(getOpts), function(err, res) { + request(opts(getOpts), function (err, res) { if (err) return cb(err) res.statusCode.should.equal(200) - res.body.should.eql({Item: {b: hashItem.b, g: hashItem.g}}) + res.body.should.eql({ Item: { b: hashItem.b, g: hashItem.g } }) cb() }) }, done) }) - it('should only return requested nested attributes', function(done) { - var item = {a: {S: helpers.randomString()}, b: {M: {a: {S: 'a'}, b: {S: 'b'}, c: {S: 'c'}}}, c: {L: [{S: 'a'}, {S: 'b'}, {S: 'c'}]}} - request(helpers.opts('PutItem', {TableName: helpers.testHashTable, Item: item}), function(err, res) { + it('should only return requested nested attributes', function (done) { + var item = { a: { S: helpers.randomString() }, b: { M: { a: { S: 'a' }, b: { S: 'b' }, c: { S: 'c' } } }, c: { L: [ { S: 'a' }, { S: 'b' }, { S: 'c' } ] } } + request(helpers.opts('PutItem', { TableName: helpers.testHashTable, Item: item }), function (err, res) { if (err) return done(err) res.statusCode.should.equal(200) async.forEach([ - {ProjectionExpression: 'b.c,c[2],b.b,c[1],c[0].a'}, - {ProjectionExpression: '#b.#c,#c[2],#b.#b,#c[1],#c[0][1]', ExpressionAttributeNames: {'#b': 'b', '#c': 'c'}}, - ], function(getOpts, cb) { + { ProjectionExpression: 'b.c,c[2],b.b,c[1],c[0].a' }, + { ProjectionExpression: '#b.#c,#c[2],#b.#b,#c[1],#c[0][1]', ExpressionAttributeNames: { '#b': 'b', '#c': 'c' } }, + ], function (getOpts, cb) { getOpts.TableName = helpers.testHashTable - getOpts.Key = {a: item.a} + getOpts.Key = { a: item.a } getOpts.ConsistentRead = true - request(opts(getOpts), function(err, res) { + request(opts(getOpts), function (err, res) { if (err) return cb(err) res.statusCode.should.equal(200) - res.body.should.eql({Item: {b: {M: {b: item.b.M.b, c: item.b.M.c}}, c: {L: [item.c.L[1], item.c.L[2]]}}}) + res.body.should.eql({ Item: { b: { M: { b: item.b.M.b, c: item.b.M.c } }, c: { L: [ item.c.L[1], item.c.L[2] ] } } }) cb() }) }, done) }) }) - it('should return ConsumedCapacity for small item with no ConsistentRead', function(done) { + it('should return ConsumedCapacity for small item with no ConsistentRead', function (done) { var a = helpers.randomString(), b = new Array(4082 - a.length).join('b'), - item = {a: {S: a}, b: {S: b}, c: {N: '12.3456'}, d: {B: 'AQI='}, e: {BS: ['AQI=', 'Ag==', 'AQ==']}} - request(helpers.opts('PutItem', {TableName: helpers.testHashTable, Item: item}), function(err, res) { + item = { a: { S: a }, b: { S: b }, c: { N: '12.3456' }, d: { B: 'AQI=' }, e: { BS: [ 'AQI=', 'Ag==', 'AQ==' ] } } + request(helpers.opts('PutItem', { TableName: helpers.testHashTable, Item: item }), function (err, res) { if (err) return done(err) res.statusCode.should.equal(200) - request(opts({TableName: helpers.testHashTable, Key: {a: item.a}, ReturnConsumedCapacity: 'TOTAL'}), function(err, res) { + request(opts({ TableName: helpers.testHashTable, Key: { a: item.a }, ReturnConsumedCapacity: 'TOTAL' }), function (err, res) { if (err) return done(err) res.statusCode.should.equal(200) - res.body.ConsumedCapacity.should.eql({CapacityUnits: 0.5, TableName: helpers.testHashTable}) + res.body.ConsumedCapacity.should.eql({ CapacityUnits: 0.5, TableName: helpers.testHashTable }) done() }) }) }) - it('should return ConsumedCapacity for larger item with no ConsistentRead', function(done) { + it('should return ConsumedCapacity for larger item with no ConsistentRead', function (done) { var a = helpers.randomString(), b = new Array(4084 - a.length).join('b'), - item = {a: {S: a}, b: {S: b}, c: {N: '12.3456'}, d: {B: 'AQI='}, e: {BS: ['AQI=', 'Ag==']}} - request(helpers.opts('PutItem', {TableName: helpers.testHashTable, Item: item}), function(err, res) { + item = { a: { S: a }, b: { S: b }, c: { N: '12.3456' }, d: { B: 'AQI=' }, e: { BS: [ 'AQI=', 'Ag==' ] } } + request(helpers.opts('PutItem', { TableName: helpers.testHashTable, Item: item }), function (err, res) { if (err) return done(err) res.statusCode.should.equal(200) - request(opts({TableName: helpers.testHashTable, Key: {a: item.a}, ReturnConsumedCapacity: 'TOTAL'}), function(err, res) { + request(opts({ TableName: helpers.testHashTable, Key: { a: item.a }, ReturnConsumedCapacity: 'TOTAL' }), function (err, res) { if (err) return done(err) res.statusCode.should.equal(200) - res.body.ConsumedCapacity.should.eql({CapacityUnits: 1, TableName: helpers.testHashTable}) + res.body.ConsumedCapacity.should.eql({ CapacityUnits: 1, TableName: helpers.testHashTable }) done() }) }) }) - it('should return ConsumedCapacity for small item with ConsistentRead', function(done) { - var batchReq = {RequestItems: {}} - var items = [{ - a: {S: helpers.randomString()}, - bb: {S: new Array(4000).join('b')}, - ccc: {N: '12.3456'}, - dddd: {B: 'AQI='}, - eeeee: {BS: ['AQI=', 'Ag==', 'AQ==']}, - ffffff: {NULL: true}, - ggggggg: {BOOL: false}, - hhhhhhhh: {L: [{S: 'a'}, {S: 'aa'}, {S: 'bb'}, {S: 'ccc'}]}, - iiiiiiiii: {M: {aa: {S: 'aa'}, bbb: {S: 'bbb'}}}, + it('should return ConsumedCapacity for small item with ConsistentRead', function (done) { + var batchReq = { RequestItems: {} } + var items = [ { + a: { S: helpers.randomString() }, + bb: { S: new Array(4000).join('b') }, + ccc: { N: '12.3456' }, + dddd: { B: 'AQI=' }, + eeeee: { BS: [ 'AQI=', 'Ag==', 'AQ==' ] }, + ffffff: { NULL: true }, + ggggggg: { BOOL: false }, + hhhhhhhh: { L: [ { S: 'a' }, { S: 'aa' }, { S: 'bb' }, { S: 'ccc' } ] }, + iiiiiiiii: { M: { aa: { S: 'aa' }, bbb: { S: 'bbb' } } }, }, { - a: {S: helpers.randomString()}, - ab: {S: new Array(4027).join('b')}, - abc: {NULL: true}, - abcd: {BOOL: true}, - abcde: {L: [{S: 'aa'}, {N: '12.3456'}, {B: 'AQI='}]}, - abcdef: {M: {aa: {S: 'aa'}, bbb: {N: '12.3456'}, cccc: {B: 'AQI='}}}, - }] - batchReq.RequestItems[helpers.testHashTable] = items.map(function(item) { return {PutRequest: {Item: item}} }) - request(helpers.opts('BatchWriteItem', batchReq), function(err, res) { + a: { S: helpers.randomString() }, + ab: { S: new Array(4027).join('b') }, + abc: { NULL: true }, + abcd: { BOOL: true }, + abcde: { L: [ { S: 'aa' }, { N: '12.3456' }, { B: 'AQI=' } ] }, + abcdef: { M: { aa: { S: 'aa' }, bbb: { N: '12.3456' }, cccc: { B: 'AQI=' } } }, + } ] + batchReq.RequestItems[helpers.testHashTable] = items.map(function (item) { return { PutRequest: { Item: item } } }) + request(helpers.opts('BatchWriteItem', batchReq), function (err, res) { if (err) return done(err) res.statusCode.should.equal(200) - async.forEach(items, function(item, cb) { - request(opts({TableName: helpers.testHashTable, Key: {a: item.a}, ReturnConsumedCapacity: 'TOTAL', ConsistentRead: true}), function(err, res) { + async.forEach(items, function (item, cb) { + request(opts({ TableName: helpers.testHashTable, Key: { a: item.a }, ReturnConsumedCapacity: 'TOTAL', ConsistentRead: true }), function (err, res) { if (err) return cb(err) res.statusCode.should.equal(200) - res.body.ConsumedCapacity.should.eql({CapacityUnits: 1, TableName: helpers.testHashTable}) + res.body.ConsumedCapacity.should.eql({ CapacityUnits: 1, TableName: helpers.testHashTable }) cb() }) }, done) }) }) - it('should return ConsumedCapacity for larger item with ConsistentRead', function(done) { - var batchReq = {RequestItems: {}} - var items = [{ - a: {S: helpers.randomString()}, - bb: {S: new Array(4001).join('b')}, - ccc: {N: '12.3456'}, - dddd: {B: 'AQI='}, - eeeee: {BS: ['AQI=', 'Ag==', 'AQ==']}, - ffffff: {NULL: true}, - ggggggg: {BOOL: false}, - hhhhhhhh: {L: [{S: 'a'}, {S: 'aa'}, {S: 'bb'}, {S: 'ccc'}]}, - iiiiiiiii: {M: {aa: {S: 'aa'}, bbb: {S: 'bbb'}}}, + it('should return ConsumedCapacity for larger item with ConsistentRead', function (done) { + var batchReq = { RequestItems: {} } + var items = [ { + a: { S: helpers.randomString() }, + bb: { S: new Array(4001).join('b') }, + ccc: { N: '12.3456' }, + dddd: { B: 'AQI=' }, + eeeee: { BS: [ 'AQI=', 'Ag==', 'AQ==' ] }, + ffffff: { NULL: true }, + ggggggg: { BOOL: false }, + hhhhhhhh: { L: [ { S: 'a' }, { S: 'aa' }, { S: 'bb' }, { S: 'ccc' } ] }, + iiiiiiiii: { M: { aa: { S: 'aa' }, bbb: { S: 'bbb' } } }, }, { - a: {S: helpers.randomString()}, - ab: {S: new Array(4028).join('b')}, - abc: {NULL: true}, - abcd: {BOOL: true}, - abcde: {L: [{S: 'aa'}, {N: '12.3456'}, {B: 'AQI='}]}, - abcdef: {M: {aa: {S: 'aa'}, bbb: {N: '12.3456'}, cccc: {B: 'AQI='}}}, - }] - batchReq.RequestItems[helpers.testHashTable] = items.map(function(item) { return {PutRequest: {Item: item}} }) - request(helpers.opts('BatchWriteItem', batchReq), function(err, res) { + a: { S: helpers.randomString() }, + ab: { S: new Array(4028).join('b') }, + abc: { NULL: true }, + abcd: { BOOL: true }, + abcde: { L: [ { S: 'aa' }, { N: '12.3456' }, { B: 'AQI=' } ] }, + abcdef: { M: { aa: { S: 'aa' }, bbb: { N: '12.3456' }, cccc: { B: 'AQI=' } } }, + } ] + batchReq.RequestItems[helpers.testHashTable] = items.map(function (item) { return { PutRequest: { Item: item } } }) + request(helpers.opts('BatchWriteItem', batchReq), function (err, res) { if (err) return done(err) res.statusCode.should.equal(200) - async.forEach(items, function(item, cb) { - request(opts({TableName: helpers.testHashTable, Key: {a: item.a}, ReturnConsumedCapacity: 'TOTAL', ConsistentRead: true}), function(err, res) { + async.forEach(items, function (item, cb) { + request(opts({ TableName: helpers.testHashTable, Key: { a: item.a }, ReturnConsumedCapacity: 'TOTAL', ConsistentRead: true }), function (err, res) { if (err) return cb(err) res.statusCode.should.equal(200) - res.body.ConsumedCapacity.should.eql({CapacityUnits: 2, TableName: helpers.testHashTable}) + res.body.ConsumedCapacity.should.eql({ CapacityUnits: 2, TableName: helpers.testHashTable }) cb() }) }, done) diff --git a/test/helpers.js b/test/helpers.js index 80a9c6f..fbb05e4 100644 --- a/test/helpers.js +++ b/test/helpers.js @@ -1,8 +1,8 @@ var http = require('http'), - aws4 = require('aws4'), - async = require('async'), - once = require('once'), - dynalite = require('..') + aws4 = require('aws4'), + async = require('async'), + once = require('once'), + dynalite = require('..') var useRemoteDynamo = process.env.REMOTE var runSlowTests = true @@ -47,29 +47,29 @@ exports.testRangeBTable = useRemoteDynamo ? '__dynalite_test_5' : randomName() exports.runSlowTests = runSlowTests var port = 10000 + Math.round(Math.random() * 10000), - requestOpts = useRemoteDynamo ? - {host: 'dynamodb.' + exports.awsRegion + '.amazonaws.com', method: 'POST'} : - {host: '127.0.0.1', port: port, method: 'POST'} + requestOpts = useRemoteDynamo ? + { host: 'dynamodb.' + exports.awsRegion + '.amazonaws.com', method: 'POST' } : + { host: '127.0.0.1', port: port, method: 'POST' } -var dynaliteServer = dynalite({path: process.env.DYNALITE_PATH}) +var dynaliteServer = dynalite({ path: process.env.DYNALITE_PATH }) var CREATE_REMOTE_TABLES = true var DELETE_REMOTE_TABLES = true -before(function(done) { +before(function (done) { this.timeout(200000) - dynaliteServer.listen(port, function(err) { + dynaliteServer.listen(port, function (err) { if (err) return done(err) - createTestTables(function(err) { + createTestTables(function (err) { if (err) return done(err) getAccountId(done) }) }) }) -after(function(done) { +after(function (done) { this.timeout(500000) - deleteTestTables(function(err) { + deleteTestTables(function (err) { if (err) return done(err) dynaliteServer.close(done) }) @@ -77,7 +77,7 @@ after(function(done) { var MAX_RETRIES = 20 -function request(opts, cb) { +function request (opts, cb) { if (typeof opts === 'function') { cb = opts; opts = {} } opts.retries = opts.retries || 0 cb = once(cb) @@ -90,15 +90,16 @@ function request(opts, cb) { opts.noSign = true // don't sign twice if calling recursively } // console.log(opts) - http.request(opts, function(res) { + http.request(opts, function (res) { res.setEncoding('utf8') res.on('error', cb) res.rawBody = '' - res.on('data', function(chunk) { res.rawBody += chunk }) - res.on('end', function() { + res.on('data', function (chunk) { res.rawBody += chunk }) + res.on('end', function () { try { res.body = JSON.parse(res.rawBody) - } catch (e) { + } + catch (e) { res.body = res.rawBody } if (useRemoteDynamo && opts.retries <= MAX_RETRIES && @@ -109,8 +110,8 @@ function request(opts, cb) { } cb(null, res) }) - }).on('error', function(err) { - if (err && ~['ECONNRESET', 'EMFILE', 'ENOTFOUND'].indexOf(err.code) && opts.retries <= MAX_RETRIES) { + }).on('error', function (err) { + if (err && ~[ 'ECONNRESET', 'EMFILE', 'ENOTFOUND' ].indexOf(err.code) && opts.retries <= MAX_RETRIES) { opts.retries++ return setTimeout(request, Math.floor(Math.random() * 100), opts, cb) } @@ -118,7 +119,7 @@ function request(opts, cb) { }).end(opts.body) } -function opts(target, data) { +function opts (target, data) { return { headers: { 'Content-Type': 'application/x-amz-json-1.0', @@ -128,102 +129,102 @@ function opts(target, data) { } } -function randomString() { +function randomString () { return ('AAAAAAAAA' + randomNumber()).slice(-10) } -function randomNumber() { +function randomNumber () { return String(Math.random() * 0x100000000) } -function randomName() { +function randomName () { return exports.prefix + randomString() } -function createTestTables(done) { +function createTestTables (done) { if (useRemoteDynamo && !CREATE_REMOTE_TABLES) return done() var readCapacity = exports.readCapacity, writeCapacity = exports.writeCapacity - var tables = [{ + var tables = [ { TableName: exports.testHashTable, - AttributeDefinitions: [{AttributeName: 'a', AttributeType: 'S'}], - KeySchema: [{KeyType: 'HASH', AttributeName: 'a'}], - ProvisionedThroughput: {ReadCapacityUnits: readCapacity, WriteCapacityUnits: writeCapacity}, + AttributeDefinitions: [ { AttributeName: 'a', AttributeType: 'S' } ], + KeySchema: [ { KeyType: 'HASH', AttributeName: 'a' } ], + ProvisionedThroughput: { ReadCapacityUnits: readCapacity, WriteCapacityUnits: writeCapacity }, }, { TableName: exports.testHashNTable, - AttributeDefinitions: [{AttributeName: 'a', AttributeType: 'N'}], - KeySchema: [{KeyType: 'HASH', AttributeName: 'a'}], + AttributeDefinitions: [ { AttributeName: 'a', AttributeType: 'N' } ], + KeySchema: [ { KeyType: 'HASH', AttributeName: 'a' } ], BillingMode: 'PAY_PER_REQUEST', }, { TableName: exports.testRangeTable, AttributeDefinitions: [ - {AttributeName: 'a', AttributeType: 'S'}, - {AttributeName: 'b', AttributeType: 'S'}, - {AttributeName: 'c', AttributeType: 'S'}, - {AttributeName: 'd', AttributeType: 'S'}, + { AttributeName: 'a', AttributeType: 'S' }, + { AttributeName: 'b', AttributeType: 'S' }, + { AttributeName: 'c', AttributeType: 'S' }, + { AttributeName: 'd', AttributeType: 'S' }, ], - KeySchema: [{KeyType: 'HASH', AttributeName: 'a'}, {KeyType: 'RANGE', AttributeName: 'b'}], - ProvisionedThroughput: {ReadCapacityUnits: readCapacity, WriteCapacityUnits: writeCapacity}, - LocalSecondaryIndexes: [{ + KeySchema: [ { KeyType: 'HASH', AttributeName: 'a' }, { KeyType: 'RANGE', AttributeName: 'b' } ], + ProvisionedThroughput: { ReadCapacityUnits: readCapacity, WriteCapacityUnits: writeCapacity }, + LocalSecondaryIndexes: [ { IndexName: 'index1', - KeySchema: [{AttributeName: 'a', KeyType: 'HASH'}, {AttributeName: 'c', KeyType: 'RANGE'}], - Projection: {ProjectionType: 'ALL'}, + KeySchema: [ { AttributeName: 'a', KeyType: 'HASH' }, { AttributeName: 'c', KeyType: 'RANGE' } ], + Projection: { ProjectionType: 'ALL' }, }, { IndexName: 'index2', - KeySchema: [{AttributeName: 'a', KeyType: 'HASH'}, {AttributeName: 'd', KeyType: 'RANGE'}], - Projection: {ProjectionType: 'INCLUDE', NonKeyAttributes: ['c']}, - }], - GlobalSecondaryIndexes: [{ + KeySchema: [ { AttributeName: 'a', KeyType: 'HASH' }, { AttributeName: 'd', KeyType: 'RANGE' } ], + Projection: { ProjectionType: 'INCLUDE', NonKeyAttributes: [ 'c' ] }, + } ], + GlobalSecondaryIndexes: [ { IndexName: 'index3', - KeySchema: [{AttributeName: 'c', KeyType: 'HASH'}], - ProvisionedThroughput: {ReadCapacityUnits: readCapacity, WriteCapacityUnits: writeCapacity}, - Projection: {ProjectionType: 'ALL'}, + KeySchema: [ { AttributeName: 'c', KeyType: 'HASH' } ], + ProvisionedThroughput: { ReadCapacityUnits: readCapacity, WriteCapacityUnits: writeCapacity }, + Projection: { ProjectionType: 'ALL' }, }, { IndexName: 'index4', - KeySchema: [{AttributeName: 'c', KeyType: 'HASH'}, {AttributeName: 'd', KeyType: 'RANGE'}], - ProvisionedThroughput: {ReadCapacityUnits: readCapacity, WriteCapacityUnits: writeCapacity}, - Projection: {ProjectionType: 'INCLUDE', NonKeyAttributes: ['e']}, - }], + KeySchema: [ { AttributeName: 'c', KeyType: 'HASH' }, { AttributeName: 'd', KeyType: 'RANGE' } ], + ProvisionedThroughput: { ReadCapacityUnits: readCapacity, WriteCapacityUnits: writeCapacity }, + Projection: { ProjectionType: 'INCLUDE', NonKeyAttributes: [ 'e' ] }, + } ], }, { TableName: exports.testRangeNTable, - AttributeDefinitions: [{AttributeName: 'a', AttributeType: 'S'}, {AttributeName: 'b', AttributeType: 'N'}], - KeySchema: [{KeyType: 'HASH', AttributeName: 'a'}, {KeyType: 'RANGE', AttributeName: 'b'}], - ProvisionedThroughput: {ReadCapacityUnits: readCapacity, WriteCapacityUnits: writeCapacity}, + AttributeDefinitions: [ { AttributeName: 'a', AttributeType: 'S' }, { AttributeName: 'b', AttributeType: 'N' } ], + KeySchema: [ { KeyType: 'HASH', AttributeName: 'a' }, { KeyType: 'RANGE', AttributeName: 'b' } ], + ProvisionedThroughput: { ReadCapacityUnits: readCapacity, WriteCapacityUnits: writeCapacity }, }, { TableName: exports.testRangeBTable, - AttributeDefinitions: [{AttributeName: 'a', AttributeType: 'S'}, {AttributeName: 'b', AttributeType: 'B'}], - KeySchema: [{KeyType: 'HASH', AttributeName: 'a'}, {KeyType: 'RANGE', AttributeName: 'b'}], - ProvisionedThroughput: {ReadCapacityUnits: readCapacity, WriteCapacityUnits: writeCapacity}, - }] + AttributeDefinitions: [ { AttributeName: 'a', AttributeType: 'S' }, { AttributeName: 'b', AttributeType: 'B' } ], + KeySchema: [ { KeyType: 'HASH', AttributeName: 'a' }, { KeyType: 'RANGE', AttributeName: 'b' } ], + ProvisionedThroughput: { ReadCapacityUnits: readCapacity, WriteCapacityUnits: writeCapacity }, + } ] async.forEach(tables, createAndWait, done) } -function getAccountId(done) { - request(opts('DescribeTable', {TableName: exports.testHashTable}), function(err, res) { +function getAccountId (done) { + request(opts('DescribeTable', { TableName: exports.testHashTable }), function (err, res) { if (err) return done(err) exports.awsAccountId = res.body.Table.TableArn.split(':')[4] done() }) } -function deleteTestTables(done) { +function deleteTestTables (done) { if (useRemoteDynamo && !DELETE_REMOTE_TABLES) return done() - request(opts('ListTables', {}), function(err, res) { + request(opts('ListTables', {}), function (err, res) { if (err) return done(err) - var names = res.body.TableNames.filter(function(name) { return name.indexOf(exports.prefix) === 0 }) + var names = res.body.TableNames.filter(function (name) { return name.indexOf(exports.prefix) === 0 }) async.forEach(names, deleteAndWait, done) }) } -function createAndWait(table, done) { - request(opts('CreateTable', table), function(err, res) { +function createAndWait (table, done) { + request(opts('CreateTable', table), function (err, res) { if (err) return done(err) if (res.statusCode != 200) return done(new Error(res.statusCode + ': ' + JSON.stringify(res.body))) setTimeout(waitUntilActive, 1000, table.TableName, done) }) } -function deleteAndWait(name, done) { - request(opts('DeleteTable', {TableName: name}), function(err, res) { +function deleteAndWait (name, done) { + request(opts('DeleteTable', { TableName: name }), function (err, res) { if (err) return done(err) if (res.body && res.body.__type == 'com.amazonaws.dynamodb.v20120810#ResourceInUseException') return setTimeout(deleteAndWait, 1000, name, done) @@ -233,21 +234,21 @@ function deleteAndWait(name, done) { }) } -function waitUntilActive(name, done) { - request(opts('DescribeTable', {TableName: name}), function(err, res) { +function waitUntilActive (name, done) { + request(opts('DescribeTable', { TableName: name }), function (err, res) { if (err) return done(err) if (res.statusCode != 200) return done(new Error(res.statusCode + ': ' + JSON.stringify(res.body))) if (res.body.Table.TableStatus == 'ACTIVE' && (!res.body.Table.GlobalSecondaryIndexes || - res.body.Table.GlobalSecondaryIndexes.every(function(index) { return index.IndexStatus == 'ACTIVE' }))) { + res.body.Table.GlobalSecondaryIndexes.every(function (index) { return index.IndexStatus == 'ACTIVE' }))) { return done(null, res) } setTimeout(waitUntilActive, 1000, name, done) }) } -function waitUntilDeleted(name, done) { - request(opts('DescribeTable', {TableName: name}), function(err, res) { +function waitUntilDeleted (name, done) { + request(opts('DescribeTable', { TableName: name }), function (err, res) { if (err) return done(err) if (res.body && res.body.__type == 'com.amazonaws.dynamodb.v20120810#ResourceNotFoundException') return done(null, res) @@ -257,46 +258,47 @@ function waitUntilDeleted(name, done) { }) } -function waitUntilIndexesActive(name, done) { - request(opts('DescribeTable', {TableName: name}), function(err, res) { +function waitUntilIndexesActive (name, done) { + request(opts('DescribeTable', { TableName: name }), function (err, res) { if (err) return done(err) if (res.statusCode != 200) return done(new Error(res.statusCode + ': ' + JSON.stringify(res.body))) - else if (res.body.Table.GlobalSecondaryIndexes.every(function(index) { return index.IndexStatus == 'ACTIVE' })) + else if (res.body.Table.GlobalSecondaryIndexes.every(function (index) { return index.IndexStatus == 'ACTIVE' })) return done(null, res) setTimeout(waitUntilIndexesActive, 1000, name, done) }) } -function deleteWhenActive(name, done) { - if (!done) done = function() { } - waitUntilActive(name, function(err) { +function deleteWhenActive (name, done) { + if (!done) done = function () { } + waitUntilActive(name, function (err) { if (err) return done(err) - request(opts('DeleteTable', {TableName: name}), done) + request(opts('DeleteTable', { TableName: name }), done) }) } -function clearTable(name, keyNames, segments, done) { +function clearTable (name, keyNames, segments, done) { if (!done) { done = segments; segments = 2 } - if (!Array.isArray(keyNames)) keyNames = [keyNames] + if (!Array.isArray(keyNames)) keyNames = [ keyNames ] scanAndDelete(done) - function scanAndDelete(cb) { - async.times(segments, scanSegmentAndDelete, function(err, segmentsHadKeys) { + function scanAndDelete (cb) { + async.times(segments, scanSegmentAndDelete, function (err, segmentsHadKeys) { if (err) return cb(err) if (segmentsHadKeys.some(Boolean)) return scanAndDelete(cb) cb() }) } - function scanSegmentAndDelete(n, cb) { - request(opts('Scan', {TableName: name, AttributesToGet: keyNames, Segment: n, TotalSegments: segments}), function(err, res) { + function scanSegmentAndDelete (n, cb) { + request(opts('Scan', { TableName: name, AttributesToGet: keyNames, Segment: n, TotalSegments: segments }), function (err, res) { if (err) return cb(err) if (/ProvisionedThroughputExceededException/.test(res.body.__type)) { console.log('ProvisionedThroughputExceededException') // eslint-disable-line no-console return setTimeout(scanSegmentAndDelete, 2000, n, cb) - } else if (res.statusCode != 200) { + } + else if (res.statusCode != 200) { return cb(new Error(res.statusCode + ': ' + JSON.stringify(res.body))) } if (!res.body.ScannedCount) return cb(null, false) @@ -304,9 +306,9 @@ function clearTable(name, keyNames, segments, done) { var keys = res.body.Items, batchDeletes for (batchDeletes = []; keys.length; keys = keys.slice(25)) - batchDeletes.push(batchWriteUntilDone.bind(null, name, {deletes: keys.slice(0, 25)})) + batchDeletes.push(batchWriteUntilDone.bind(null, name, { deletes: keys.slice(0, 25) })) - async.parallel(batchDeletes, function(err) { + async.parallel(batchDeletes, function (err) { if (err) return cb(err) cb(null, true) }) @@ -314,47 +316,49 @@ function clearTable(name, keyNames, segments, done) { } } -function replaceTable(name, keyNames, items, segments, done) { +function replaceTable (name, keyNames, items, segments, done) { if (!done) { done = segments; segments = 2 } - clearTable(name, keyNames, segments, function(err) { + clearTable(name, keyNames, segments, function (err) { if (err) return done(err) batchBulkPut(name, items, segments, done) }) } -function batchBulkPut(name, items, segments, done) { +function batchBulkPut (name, items, segments, done) { if (!done) { done = segments; segments = 2 } var itemChunks = [], i for (i = 0; i < items.length; i += 25) itemChunks.push(items.slice(i, i + 25)) - async.eachLimit(itemChunks, segments, function(items, cb) { batchWriteUntilDone(name, {puts: items}, cb) }, done) + async.eachLimit(itemChunks, segments, function (items, cb) { batchWriteUntilDone(name, { puts: items }, cb) }, done) } -function batchWriteUntilDone(name, actions, cb) { - var batchReq = {RequestItems: {}}, batchRes = {} - batchReq.RequestItems[name] = (actions.puts || []).map(function(item) { return {PutRequest: {Item: item}} }) - .concat((actions.deletes || []).map(function(key) { return {DeleteRequest: {Key: key}} })) +function batchWriteUntilDone (name, actions, cb) { + var batchReq = { RequestItems: {} }, batchRes = {} + batchReq.RequestItems[name] = (actions.puts || []).map(function (item) { return { PutRequest: { Item: item } } }) + .concat((actions.deletes || []).map(function (key) { return { DeleteRequest: { Key: key } } })) async.doWhilst( - function(cb) { - request(opts('BatchWriteItem', batchReq), function(err, res) { + function (cb) { + request(opts('BatchWriteItem', batchReq), function (err, res) { if (err) return cb(err) batchRes = res if (res.body.UnprocessedItems && Object.keys(res.body.UnprocessedItems).length) { batchReq.RequestItems = res.body.UnprocessedItems - } else if (/ProvisionedThroughputExceededException/.test(res.body.__type)) { + } + else if (/ProvisionedThroughputExceededException/.test(res.body.__type)) { console.log('ProvisionedThroughputExceededException') // eslint-disable-line no-console return setTimeout(cb, 2000) - } else if (res.statusCode != 200) { + } + else if (res.statusCode != 200) { return cb(new Error(res.statusCode + ': ' + JSON.stringify(res.body))) } cb() }) }, - function(cb) { + function (cb) { var result = (batchRes.body.UnprocessedItems && Object.keys(batchRes.body.UnprocessedItems).length) || /ProvisionedThroughputExceededException/.test(batchRes.body.__type) cb(null, result) @@ -363,8 +367,8 @@ function batchWriteUntilDone(name, actions, cb) { ) } -function assertSerialization(target, data, msg, done) { - request(opts(target, data), function(err, res) { +function assertSerialization (target, data, msg, done) { + request(opts(target, data), function (err, res) { if (err) return done(err) res.statusCode.should.equal(400) res.body.should.eql({ @@ -375,7 +379,7 @@ function assertSerialization(target, data, msg, done) { }) } -function assertType(target, property, type, done) { +function assertType (target, property, type, done) { var msgs = [], pieces = property.split('.'), subtypeMatch = type.match(/(.+?)<(.+)>$/), subtype if (subtypeMatch != null) { type = subtypeMatch[1] @@ -383,155 +387,155 @@ function assertType(target, property, type, done) { } var castMsg = "class sun.reflect.generics.reflectiveObjects.ParameterizedTypeImpl cannot be cast to class java.lang.Class (sun.reflect.generics.reflectiveObjects.ParameterizedTypeImpl and java.lang.Class are in module java.base of loader 'bootstrap')" switch (type) { - case 'Boolean': - msgs = [ - ['23', 'Unexpected token received from parser'], - [23, 'NUMBER_VALUE cannot be converted to Boolean'], - [-2147483648, 'NUMBER_VALUE cannot be converted to Boolean'], - [2147483648, 'NUMBER_VALUE cannot be converted to Boolean'], - [34.56, 'DECIMAL_VALUE cannot be converted to Boolean'], - [[], 'Unrecognized collection type class java.lang.Boolean'], - [{}, 'Start of structure or map found where not expected'], - ] - break - case 'String': - msgs = [ - [true, 'TRUE_VALUE cannot be converted to String'], - [false, 'FALSE_VALUE cannot be converted to String'], - [23, 'NUMBER_VALUE cannot be converted to String'], - [-2147483648, 'NUMBER_VALUE cannot be converted to String'], - [2147483648, 'NUMBER_VALUE cannot be converted to String'], - [34.56, 'DECIMAL_VALUE cannot be converted to String'], - [[], 'Unrecognized collection type class java.lang.String'], - [{}, 'Start of structure or map found where not expected'], - ] - break - case 'Integer': - msgs = [ - ['23', 'STRING_VALUE cannot be converted to Integer'], - [true, 'TRUE_VALUE cannot be converted to Integer'], - [false, 'FALSE_VALUE cannot be converted to Integer'], - [[], 'Unrecognized collection type class java.lang.Integer'], - [{}, 'Start of structure or map found where not expected'], - ] - break - case 'Long': - msgs = [ - ['23', 'STRING_VALUE cannot be converted to Long'], - [true, 'TRUE_VALUE cannot be converted to Long'], - [false, 'FALSE_VALUE cannot be converted to Long'], - [[], 'Unrecognized collection type class java.lang.Long'], - [{}, 'Start of structure or map found where not expected'], - ] - break - case 'Blob': - msgs = [ - [true, 'only base-64-encoded strings are convertible to bytes'], - [23, 'only base-64-encoded strings are convertible to bytes'], - [-2147483648, 'only base-64-encoded strings are convertible to bytes'], - [2147483648, 'only base-64-encoded strings are convertible to bytes'], - [34.56, 'only base-64-encoded strings are convertible to bytes'], - [[], 'Unrecognized collection type class java.nio.ByteBuffer'], - [{}, 'Start of structure or map found where not expected'], - ['23456', 'Base64 encoded length is expected a multiple of 4 bytes but found: 5'], - ['=+/=', 'Invalid last non-pad Base64 character dectected'], - ['+/+=', 'Invalid last non-pad Base64 character dectected'], - ] - break - case 'List': - msgs = [ - ['23', 'Unexpected field type'], - [true, 'Unexpected field type'], - [23, 'Unexpected field type'], - [-2147483648, 'Unexpected field type'], - [2147483648, 'Unexpected field type'], - [34.56, 'Unexpected field type'], - [{}, 'Start of structure or map found where not expected'], - ] - break - case 'ParameterizedList': - msgs = [ - ['23', castMsg], - [true, castMsg], - [23, castMsg], - [-2147483648, castMsg], - [2147483648, castMsg], - [34.56, castMsg], - [{}, 'Start of structure or map found where not expected'], - ] - break - case 'Map': - msgs = [ - ['23', 'Unexpected field type'], - [true, 'Unexpected field type'], - [23, 'Unexpected field type'], - [-2147483648, 'Unexpected field type'], - [2147483648, 'Unexpected field type'], - [34.56, 'Unexpected field type'], - [[], 'Unrecognized collection type java.util.Map'], - ] - break - case 'ParameterizedMap': - msgs = [ - ['23', castMsg], - [true, castMsg], - [23, castMsg], - [-2147483648, castMsg], - [2147483648, castMsg], - [34.56, castMsg], - [[], 'Unrecognized collection type java.util.Map'], - ] - break - case 'ValueStruct': - msgs = [ - ['23', 'Unexpected value type in payload'], - [true, 'Unexpected value type in payload'], - [23, 'Unexpected value type in payload'], - [-2147483648, 'Unexpected value type in payload'], - [2147483648, 'Unexpected value type in payload'], - [34.56, 'Unexpected value type in payload'], - [[], 'Unrecognized collection type class com.amazonaws.dynamodb.v20120810.' + subtype], - ] - break - case 'FieldStruct': - msgs = [ - ['23', 'Unexpected field type'], - [true, 'Unexpected field type'], - [23, 'Unexpected field type'], - [-2147483648, 'Unexpected field type'], - [2147483648, 'Unexpected field type'], - [34.56, 'Unexpected field type'], - [[], 'Unrecognized collection type class com.amazonaws.dynamodb.v20120810.' + subtype], - ] - break - case 'AttrStruct': - async.forEach([ - [property, subtype + ''], - [property + '.S', 'String'], - [property + '.N', 'String'], - [property + '.B', 'Blob'], - [property + '.BOOL', 'Boolean'], - [property + '.NULL', 'Boolean'], - [property + '.SS', 'List'], - [property + '.SS.0', 'String'], - [property + '.NS', 'List'], - [property + '.NS.0', 'String'], - [property + '.BS', 'List'], - [property + '.BS.0', 'Blob'], - [property + '.L', 'List'], - [property + '.L.0', 'ValueStruct'], - [property + '.L.0.BS', 'List'], - [property + '.L.0.BS.0', 'Blob'], - [property + '.M', 'Map'], - [property + '.M.a', 'ValueStruct'], - [property + '.M.a.BS', 'List'], - [property + '.M.a.BS.0', 'Blob'], - ], function(test, cb) { assertType(target, test[0], test[1], cb) }, done) - return - default: - throw new Error('Unknown type: ' + type) + case 'Boolean': + msgs = [ + [ '23', 'Unexpected token received from parser' ], + [ 23, 'NUMBER_VALUE cannot be converted to Boolean' ], + [ -2147483648, 'NUMBER_VALUE cannot be converted to Boolean' ], + [ 2147483648, 'NUMBER_VALUE cannot be converted to Boolean' ], + [ 34.56, 'DECIMAL_VALUE cannot be converted to Boolean' ], + [ [], 'Unrecognized collection type class java.lang.Boolean' ], + [ {}, 'Start of structure or map found where not expected' ], + ] + break + case 'String': + msgs = [ + [ true, 'TRUE_VALUE cannot be converted to String' ], + [ false, 'FALSE_VALUE cannot be converted to String' ], + [ 23, 'NUMBER_VALUE cannot be converted to String' ], + [ -2147483648, 'NUMBER_VALUE cannot be converted to String' ], + [ 2147483648, 'NUMBER_VALUE cannot be converted to String' ], + [ 34.56, 'DECIMAL_VALUE cannot be converted to String' ], + [ [], 'Unrecognized collection type class java.lang.String' ], + [ {}, 'Start of structure or map found where not expected' ], + ] + break + case 'Integer': + msgs = [ + [ '23', 'STRING_VALUE cannot be converted to Integer' ], + [ true, 'TRUE_VALUE cannot be converted to Integer' ], + [ false, 'FALSE_VALUE cannot be converted to Integer' ], + [ [], 'Unrecognized collection type class java.lang.Integer' ], + [ {}, 'Start of structure or map found where not expected' ], + ] + break + case 'Long': + msgs = [ + [ '23', 'STRING_VALUE cannot be converted to Long' ], + [ true, 'TRUE_VALUE cannot be converted to Long' ], + [ false, 'FALSE_VALUE cannot be converted to Long' ], + [ [], 'Unrecognized collection type class java.lang.Long' ], + [ {}, 'Start of structure or map found where not expected' ], + ] + break + case 'Blob': + msgs = [ + [ true, 'only base-64-encoded strings are convertible to bytes' ], + [ 23, 'only base-64-encoded strings are convertible to bytes' ], + [ -2147483648, 'only base-64-encoded strings are convertible to bytes' ], + [ 2147483648, 'only base-64-encoded strings are convertible to bytes' ], + [ 34.56, 'only base-64-encoded strings are convertible to bytes' ], + [ [], 'Unrecognized collection type class java.nio.ByteBuffer' ], + [ {}, 'Start of structure or map found where not expected' ], + [ '23456', 'Base64 encoded length is expected a multiple of 4 bytes but found: 5' ], + [ '=+/=', 'Invalid last non-pad Base64 character dectected' ], + [ '+/+=', 'Invalid last non-pad Base64 character dectected' ], + ] + break + case 'List': + msgs = [ + [ '23', 'Unexpected field type' ], + [ true, 'Unexpected field type' ], + [ 23, 'Unexpected field type' ], + [ -2147483648, 'Unexpected field type' ], + [ 2147483648, 'Unexpected field type' ], + [ 34.56, 'Unexpected field type' ], + [ {}, 'Start of structure or map found where not expected' ], + ] + break + case 'ParameterizedList': + msgs = [ + [ '23', castMsg ], + [ true, castMsg ], + [ 23, castMsg ], + [ -2147483648, castMsg ], + [ 2147483648, castMsg ], + [ 34.56, castMsg ], + [ {}, 'Start of structure or map found where not expected' ], + ] + break + case 'Map': + msgs = [ + [ '23', 'Unexpected field type' ], + [ true, 'Unexpected field type' ], + [ 23, 'Unexpected field type' ], + [ -2147483648, 'Unexpected field type' ], + [ 2147483648, 'Unexpected field type' ], + [ 34.56, 'Unexpected field type' ], + [ [], 'Unrecognized collection type java.util.Map' ], + ] + break + case 'ParameterizedMap': + msgs = [ + [ '23', castMsg ], + [ true, castMsg ], + [ 23, castMsg ], + [ -2147483648, castMsg ], + [ 2147483648, castMsg ], + [ 34.56, castMsg ], + [ [], 'Unrecognized collection type java.util.Map' ], + ] + break + case 'ValueStruct': + msgs = [ + [ '23', 'Unexpected value type in payload' ], + [ true, 'Unexpected value type in payload' ], + [ 23, 'Unexpected value type in payload' ], + [ -2147483648, 'Unexpected value type in payload' ], + [ 2147483648, 'Unexpected value type in payload' ], + [ 34.56, 'Unexpected value type in payload' ], + [ [], 'Unrecognized collection type class com.amazonaws.dynamodb.v20120810.' + subtype ], + ] + break + case 'FieldStruct': + msgs = [ + [ '23', 'Unexpected field type' ], + [ true, 'Unexpected field type' ], + [ 23, 'Unexpected field type' ], + [ -2147483648, 'Unexpected field type' ], + [ 2147483648, 'Unexpected field type' ], + [ 34.56, 'Unexpected field type' ], + [ [], 'Unrecognized collection type class com.amazonaws.dynamodb.v20120810.' + subtype ], + ] + break + case 'AttrStruct': + async.forEach([ + [ property, subtype + '' ], + [ property + '.S', 'String' ], + [ property + '.N', 'String' ], + [ property + '.B', 'Blob' ], + [ property + '.BOOL', 'Boolean' ], + [ property + '.NULL', 'Boolean' ], + [ property + '.SS', 'List' ], + [ property + '.SS.0', 'String' ], + [ property + '.NS', 'List' ], + [ property + '.NS.0', 'String' ], + [ property + '.BS', 'List' ], + [ property + '.BS.0', 'Blob' ], + [ property + '.L', 'List' ], + [ property + '.L.0', 'ValueStruct' ], + [ property + '.L.0.BS', 'List' ], + [ property + '.L.0.BS.0', 'Blob' ], + [ property + '.M', 'Map' ], + [ property + '.M.a', 'ValueStruct' ], + [ property + '.M.a.BS', 'List' ], + [ property + '.M.a.BS.0', 'Blob' ], + ], function (test, cb) { assertType(target, test[0], test[1], cb) }, done) + return + default: + throw new Error('Unknown type: ' + type) } - async.forEach(msgs, function(msg, cb) { + async.forEach(msgs, function (msg, cb) { var data = {}, child = data, i, ix for (i = 0; i < pieces.length - 1; i++) { ix = Array.isArray(child) ? 0 : pieces[i] @@ -543,8 +547,8 @@ function assertType(target, property, type, done) { }, done) } -function assertAccessDenied(target, data, msg, done) { - request(opts(target, data), function(err, res) { +function assertAccessDenied (target, data, msg, done) { + request(opts(target, data), function (err, res) { if (err) return done(err) res.statusCode.should.equal(400) if (typeof res.body !== 'object') { @@ -553,15 +557,16 @@ function assertAccessDenied(target, data, msg, done) { res.body.__type.should.equal('com.amazon.coral.service#AccessDeniedException') if (msg instanceof RegExp) { res.body.Message.should.match(msg) - } else { + } + else { res.body.Message.should.equal(msg) } done() }) } -function assertValidation(target, data, msg, done) { - request(opts(target, data), function(err, res) { +function assertValidation (target, data, msg, done) { + request(opts(target, data), function (err, res) { if (err) return done(err) if (typeof res.body !== 'object') { return done(new Error('Not JSON: ' + res.body)) @@ -569,14 +574,16 @@ function assertValidation(target, data, msg, done) { res.body.__type.should.equal('com.amazon.coral.validate#ValidationException') if (msg instanceof RegExp) { res.body.message.should.match(msg) - } else if (Array.isArray(msg)) { + } + else if (Array.isArray(msg)) { var prefix = msg.length + ' validation error' + (msg.length === 1 ? '' : 's') + ' detected: ' res.body.message.should.startWith(prefix) var errors = res.body.message.slice(prefix.length).split('; ') for (var i = 0; i < msg.length; i++) { errors.should.matchAny(msg[i]) } - } else { + } + else { res.body.message.should.equal(msg) } res.statusCode.should.equal(400) @@ -584,8 +591,8 @@ function assertValidation(target, data, msg, done) { }) } -function assertNotFound(target, data, msg, done) { - request(opts(target, data), function(err, res) { +function assertNotFound (target, data, msg, done) { + request(opts(target, data), function (err, res) { if (err) return done(err) res.statusCode.should.equal(400) res.body.should.eql({ @@ -596,8 +603,8 @@ function assertNotFound(target, data, msg, done) { }) } -function assertInUse(target, data, msg, done) { - request(opts(target, data), function(err, res) { +function assertInUse (target, data, msg, done) { + request(opts(target, data), function (err, res) { if (err) return done(err) res.statusCode.should.equal(400) res.body.should.eql({ @@ -608,8 +615,8 @@ function assertInUse(target, data, msg, done) { }) } -function assertConditional(target, data, done) { - request(opts(target, data), function(err, res) { +function assertConditional (target, data, done) { + request(opts(target, data), function (err, res) { if (err) return done(err) res.statusCode.should.equal(400) res.body.should.eql({ @@ -620,7 +627,7 @@ function assertConditional(target, data, done) { }) } -function strDecrement(str, regex, length) { +function strDecrement (str, regex, length) { regex = regex || /.?/ length = length || 255 var lastIx = str.length - 1, lastChar = str.charCodeAt(lastIx) - 1, prefix = str.slice(0, lastIx), finalChar = 255 diff --git a/test/listTables.js b/test/listTables.js index 4753d07..813e270 100644 --- a/test/listTables.js +++ b/test/listTables.js @@ -1,42 +1,42 @@ var should = require('should'), - async = require('async'), - helpers = require('./helpers') + async = require('async'), + helpers = require('./helpers') var target = 'ListTables', - request = helpers.request, - randomName = helpers.randomName, - opts = helpers.opts.bind(null, target), - assertType = helpers.assertType.bind(null, target), - assertValidation = helpers.assertValidation.bind(null, target) + request = helpers.request, + randomName = helpers.randomName, + opts = helpers.opts.bind(null, target), + assertType = helpers.assertType.bind(null, target), + assertValidation = helpers.assertValidation.bind(null, target) -describe('listTables', function() { +describe('listTables', function () { - describe('serializations', function() { + describe('serializations', function () { - it('should return 400 if no body', function(done) { - request({headers: {'x-amz-target': helpers.version + '.' + target}}, function(err, res) { + it('should return 400 if no body', function (done) { + request({ headers: { 'x-amz-target': helpers.version + '.' + target } }, function (err, res) { if (err) return done(err) res.statusCode.should.equal(400) - res.body.should.eql({__type: 'com.amazon.coral.service#SerializationException'}) + res.body.should.eql({ __type: 'com.amazon.coral.service#SerializationException' }) done() }) }) // it should not include ExclusiveStartTableName value in output - it('should return SerializationException when ExclusiveStartTableName is not a string', function(done) { + it('should return SerializationException when ExclusiveStartTableName is not a string', function (done) { assertType('ExclusiveStartTableName', 'String', done) }) - it('should return SerializationException when Limit is not an integer', function(done) { + it('should return SerializationException when Limit is not an integer', function (done) { assertType('Limit', 'Integer', done) }) }) - describe('validations', function() { + describe('validations', function () { - it('should return ValidationException for empty ExclusiveStartTableName', function(done) { - assertValidation({ExclusiveStartTableName: ''}, [ + it('should return ValidationException for empty ExclusiveStartTableName', function (done) { + assertValidation({ ExclusiveStartTableName: '' }, [ 'Value \'\' at \'exclusiveStartTableName\' failed to satisfy constraint: ' + 'Member must satisfy regular expression pattern: [a-zA-Z0-9_.-]+', 'Value \'\' at \'exclusiveStartTableName\' failed to satisfy constraint: ' + @@ -44,8 +44,8 @@ describe('listTables', function() { ], done) }) - it('should return ValidationExceptions for short ExclusiveStartTableName', function(done) { - assertValidation({ExclusiveStartTableName: 'a;', Limit: 500}, [ + it('should return ValidationExceptions for short ExclusiveStartTableName', function (done) { + assertValidation({ ExclusiveStartTableName: 'a;', Limit: 500 }, [ 'Value \'a;\' at \'exclusiveStartTableName\' failed to satisfy constraint: ' + 'Member must satisfy regular expression pattern: [a-zA-Z0-9_.-]+', 'Value \'a;\' at \'exclusiveStartTableName\' failed to satisfy constraint: ' + @@ -55,24 +55,24 @@ describe('listTables', function() { ], done) }) - it('should return ValidationException for long ExclusiveStartTableName', function(done) { + it('should return ValidationException for long ExclusiveStartTableName', function (done) { var name = '', i for (i = 0; i < 256; i++) name += 'a' - assertValidation({ExclusiveStartTableName: name}, + assertValidation({ ExclusiveStartTableName: name }, '1 validation error detected: ' + 'Value \'' + name + '\' at \'exclusiveStartTableName\' failed to satisfy constraint: ' + 'Member must have length less than or equal to 255', done) }) - it('should return ValidationException for low Limit', function(done) { - assertValidation({Limit: 0}, + it('should return ValidationException for low Limit', function (done) { + assertValidation({ Limit: 0 }, '1 validation error detected: ' + 'Value \'0\' at \'limit\' failed to satisfy constraint: ' + 'Member must have value greater than or equal to 1', done) }) - it('should return ValidationException for high Limit', function(done) { - assertValidation({Limit: 101}, + it('should return ValidationException for high Limit', function (done) { + assertValidation({ Limit: 101 }, '1 validation error detected: ' + 'Value \'101\' at \'limit\' failed to satisfy constraint: ' + 'Member must have value less than or equal to 100', done) @@ -80,12 +80,12 @@ describe('listTables', function() { }) - describe('functionality', function() { + describe('functionality', function () { - it('should return 200 if no params and application/json', function(done) { + it('should return 200 if no params and application/json', function (done) { var requestOpts = opts({}) requestOpts.headers['Content-Type'] = 'application/json' - request(requestOpts, function(err, res) { + request(requestOpts, function (err, res) { if (err) return done(err) res.statusCode.should.equal(200) res.body.TableNames.should.be.an.instanceOf(Array) @@ -97,8 +97,8 @@ describe('listTables', function() { }) }) - it('should return 200 if no params and application/x-amz-json-1.0', function(done) { - request(opts({}), function(err, res) { + it('should return 200 if no params and application/x-amz-json-1.0', function (done) { + request(opts({}), function (err, res) { if (err) return done(err) res.statusCode.should.equal(200) res.body.TableNames.should.be.an.instanceOf(Array) @@ -110,10 +110,10 @@ describe('listTables', function() { }) }) - it('should return 200 and CORS if Origin specified', function(done) { + it('should return 200 and CORS if Origin specified', function (done) { var requestOpts = opts({}) requestOpts.headers.Origin = 'whatever' - request(requestOpts, function(err, res) { + request(requestOpts, function (err, res) { if (err) return done(err) res.statusCode.should.equal(200) res.headers['access-control-allow-origin'].should.equal('*') @@ -122,8 +122,8 @@ describe('listTables', function() { }) }) - it('should return 200 if random attributes are supplied', function(done) { - request(opts({hi: 'yo', stuff: 'things'}), function(err, res) { + it('should return 200 if random attributes are supplied', function (done) { + request(opts({ hi: 'yo', stuff: 'things' }), function (err, res) { if (err) return done(err) res.statusCode.should.equal(200) res.body.TableNames.should.be.an.instanceOf(Array) @@ -131,8 +131,8 @@ describe('listTables', function() { }) }) - it('should return 200 if null attributes are supplied', function(done) { - request(opts({ExclusiveStartTableName: null, Limit: null}), function(err, res) { + it('should return 200 if null attributes are supplied', function (done) { + request(opts({ ExclusiveStartTableName: null, Limit: null }), function (err, res) { if (err) return done(err) res.statusCode.should.equal(200) res.body.TableNames.should.be.an.instanceOf(Array) @@ -140,8 +140,8 @@ describe('listTables', function() { }) }) - it('should return 200 if correct types are supplied', function(done) { - request(opts({ExclusiveStartTableName: 'aaa', Limit: 100}), function(err, res) { + it('should return 200 if correct types are supplied', function (done) { + request(opts({ ExclusiveStartTableName: 'aaa', Limit: 100 }), function (err, res) { if (err) return done(err) res.statusCode.should.equal(200) res.body.TableNames.should.be.an.instanceOf(Array) @@ -149,29 +149,29 @@ describe('listTables', function() { }) }) - it('should return 200 if using query string signing', function(done) { + it('should return 200 if using query string signing', function (done) { var requestOpts = opts({}) requestOpts.signQuery = true - request(requestOpts, function(err, res) { + request(requestOpts, function (err, res) { if (err) return done(err) res.statusCode.should.equal(200) res.body.TableNames.should.be.an.instanceOf(Array) - Object.keys(requestOpts.headers).sort().should.eql(['Content-Type', 'Host', 'X-Amz-Target']) + Object.keys(requestOpts.headers).sort().should.eql([ 'Content-Type', 'Host', 'X-Amz-Target' ]) done() }) }) - it('should return list with new table in it', function(done) { + it('should return list with new table in it', function (done) { var name = randomName(), table = { TableName: name, - AttributeDefinitions: [{AttributeName: 'a', AttributeType: 'S'}], - KeySchema: [{KeyType: 'HASH', AttributeName: 'a'}], - ProvisionedThroughput: {ReadCapacityUnits: 1, WriteCapacityUnits: 1}, + AttributeDefinitions: [ { AttributeName: 'a', AttributeType: 'S' } ], + KeySchema: [ { KeyType: 'HASH', AttributeName: 'a' } ], + ProvisionedThroughput: { ReadCapacityUnits: 1, WriteCapacityUnits: 1 }, } - request(helpers.opts('CreateTable', table), function(err, res) { + request(helpers.opts('CreateTable', table), function (err, res) { if (err) return done(err) res.statusCode.should.equal(200) - request(opts({}), function(err, res) { + request(opts({}), function (err, res) { if (err) return done(err) res.statusCode.should.equal(200) res.body.TableNames.should.containEql(name) @@ -181,31 +181,31 @@ describe('listTables', function() { }) }) - it('should return list using ExclusiveStartTableName and Limit', function(done) { - var names = [randomName(), randomName()].sort(), - beforeName = helpers.strDecrement(names[0], /[a-zA-Z0-9_.-]+/, 255), - table1 = { - TableName: names[0], - AttributeDefinitions: [{AttributeName: 'a', AttributeType: 'S'}], - KeySchema: [{KeyType: 'HASH', AttributeName: 'a'}], - ProvisionedThroughput: {ReadCapacityUnits: 1, WriteCapacityUnits: 1}, - }, - table2 = { - TableName: names[1], - AttributeDefinitions: [{AttributeName: 'a', AttributeType: 'S'}], - KeySchema: [{KeyType: 'HASH', AttributeName: 'a'}], - ProvisionedThroughput: {ReadCapacityUnits: 1, WriteCapacityUnits: 1}, - } + it('should return list using ExclusiveStartTableName and Limit', function (done) { + var names = [ randomName(), randomName() ].sort(), + beforeName = helpers.strDecrement(names[0], /[a-zA-Z0-9_.-]+/, 255), + table1 = { + TableName: names[0], + AttributeDefinitions: [ { AttributeName: 'a', AttributeType: 'S' } ], + KeySchema: [ { KeyType: 'HASH', AttributeName: 'a' } ], + ProvisionedThroughput: { ReadCapacityUnits: 1, WriteCapacityUnits: 1 }, + }, + table2 = { + TableName: names[1], + AttributeDefinitions: [ { AttributeName: 'a', AttributeType: 'S' } ], + KeySchema: [ { KeyType: 'HASH', AttributeName: 'a' } ], + ProvisionedThroughput: { ReadCapacityUnits: 1, WriteCapacityUnits: 1 }, + } async.parallel([ request.bind(null, helpers.opts('CreateTable', table1)), request.bind(null, helpers.opts('CreateTable', table2)), - ], function(err) { + ], function (err) { if (err) return done(err) async.parallel([ - function(done) { - request(opts({ExclusiveStartTableName: names[0]}), function(err, res) { + function (done) { + request(opts({ ExclusiveStartTableName: names[0] }), function (err, res) { if (err) return done(err) res.statusCode.should.equal(200) res.body.TableNames.should.not.containEql(names[0]) @@ -213,8 +213,8 @@ describe('listTables', function() { done() }) }, - function(done) { - request(opts({ExclusiveStartTableName: beforeName}), function(err, res) { + function (done) { + request(opts({ ExclusiveStartTableName: beforeName }), function (err, res) { if (err) return done(err) res.statusCode.should.equal(200) res.body.TableNames.should.containEql(names[0]) @@ -222,24 +222,24 @@ describe('listTables', function() { done() }) }, - function(done) { - request(opts({Limit: 1}), function(err, res) { + function (done) { + request(opts({ Limit: 1 }), function (err, res) { if (err) return done(err) res.statusCode.should.equal(200) res.body.TableNames.should.have.length(1) done() }) }, - function(done) { - request(opts({ExclusiveStartTableName: beforeName, Limit: 1}), function(err, res) { + function (done) { + request(opts({ ExclusiveStartTableName: beforeName, Limit: 1 }), function (err, res) { if (err) return done(err) res.statusCode.should.equal(200) - res.body.TableNames.should.eql([names[0]]) + res.body.TableNames.should.eql([ names[0] ]) res.body.LastEvaluatedTableName.should.eql(names[0]) done() }) }, - ], function(err) { + ], function (err) { helpers.deleteWhenActive(names[0]) helpers.deleteWhenActive(names[1]) done(err) @@ -248,13 +248,13 @@ describe('listTables', function() { }) }) - it('should have no LastEvaluatedTableName if the limit is large enough', function(done) { - request(opts({Limit: 100}), function(err, res) { + it('should have no LastEvaluatedTableName if the limit is large enough', function (done) { + request(opts({ Limit: 100 }), function (err, res) { if (err) return done(err) res.statusCode.should.equal(200) res.body.TableNames.length.should.be.above(0) should.not.exist(res.body.LastEvaluatedTableName) - request(opts({Limit: res.body.TableNames.length}), function(err, res) { + request(opts({ Limit: res.body.TableNames.length }), function (err, res) { if (err) return done(err) res.statusCode.should.equal(200) should.not.exist(res.body.LastEvaluatedTableName) diff --git a/test/listTagsOfResource.js b/test/listTagsOfResource.js index 3cee081..a9af529 100644 --- a/test/listTagsOfResource.js +++ b/test/listTagsOfResource.js @@ -1,116 +1,116 @@ var helpers = require('./helpers') var target = 'ListTagsOfResource', - request = helpers.request, - opts = helpers.opts.bind(null, target), - assertType = helpers.assertType.bind(null, target), - assertAccessDenied = helpers.assertAccessDenied.bind(null, target), - assertNotFound = helpers.assertNotFound.bind(null, target), - assertValidation = helpers.assertValidation.bind(null, target) + request = helpers.request, + opts = helpers.opts.bind(null, target), + assertType = helpers.assertType.bind(null, target), + assertAccessDenied = helpers.assertAccessDenied.bind(null, target), + assertNotFound = helpers.assertNotFound.bind(null, target), + assertValidation = helpers.assertValidation.bind(null, target) -describe('listTagsOfResource', function() { +describe('listTagsOfResource', function () { - describe('serializations', function() { + describe('serializations', function () { - it('should return SerializationException when ResourceArn is not a string', function(done) { + it('should return SerializationException when ResourceArn is not a string', function (done) { assertType('ResourceArn', 'String', done) }) }) - describe('validations', function() { + describe('validations', function () { - it('should return ValidationException for no ResourceArn', function(done) { + it('should return ValidationException for no ResourceArn', function (done) { assertValidation({}, 'Invalid TableArn', done) }) - it('should return AccessDeniedException for empty ResourceArn', function(done) { - assertAccessDenied({ResourceArn: ''}, + it('should return AccessDeniedException for empty ResourceArn', function (done) { + assertAccessDenied({ ResourceArn: '' }, /^User: arn:aws:iam::\d+:.+ is not authorized to perform: dynamodb:ListTagsOfResource on resource: \*$/, done) }) - it('should return AccessDeniedException for unauthorized ResourceArn', function(done) { - assertAccessDenied({ResourceArn: 'abcd'}, + it('should return AccessDeniedException for unauthorized ResourceArn', function (done) { + assertAccessDenied({ ResourceArn: 'abcd' }, /^User: arn:aws:iam::\d+:.+ is not authorized to perform: dynamodb:ListTagsOfResource on resource: abcd$/, done) }) - it('should return AccessDeniedException for no ResourceArn', function(done) { - assertAccessDenied({ResourceArn: 'a:b:c:d:e:f'}, + it('should return AccessDeniedException for no ResourceArn', function (done) { + assertAccessDenied({ ResourceArn: 'a:b:c:d:e:f' }, /^User: arn:aws:iam::\d+:.+ is not authorized to perform: dynamodb:ListTagsOfResource on resource: a:b:c:d:e:f$/, done) }) - it('should return AccessDeniedException for no ResourceArn', function(done) { - assertAccessDenied({ResourceArn: 'a:b:c:d:e/f'}, + it('should return AccessDeniedException for no ResourceArn', function (done) { + assertAccessDenied({ ResourceArn: 'a:b:c:d:e/f' }, /^User: arn:aws:iam::\d+:.+ is not authorized to perform: dynamodb:ListTagsOfResource on resource: a:b:c:d:e\/f$/, done) }) - it('should return ValidationException for no ResourceArn', function(done) { - assertValidation({ResourceArn: 'a:b:c:d:e:f/g'}, + it('should return ValidationException for no ResourceArn', function (done) { + assertValidation({ ResourceArn: 'a:b:c:d:e:f/g' }, 'Invalid TableArn: Invalid ResourceArn provided as input a:b:c:d:e:f/g', done) }) - it('should return ValidationException for short table name', function(done) { + it('should return ValidationException for short table name', function (done) { var resourceArn = 'arn:aws:dynamodb:' + helpers.awsRegion + ':' + helpers.awsAccountId + ':table/ab' - assertValidation({ResourceArn: resourceArn}, + assertValidation({ ResourceArn: resourceArn }, 'Invalid TableArn: Invalid ResourceArn provided as input ' + resourceArn, done) }) - it('should return ResourceNotFoundException if ResourceArn does not exist', function(done) { + it('should return ResourceNotFoundException if ResourceArn does not exist', function (done) { var resourceArn = 'arn:aws:dynamodb:' + helpers.awsRegion + ':' + helpers.awsAccountId + ':table/' + helpers.randomString() - assertNotFound({ResourceArn: resourceArn}, + assertNotFound({ ResourceArn: resourceArn }, 'Requested resource not found: ResourcArn: ' + resourceArn + ' not found', done) }) }) - describe('functionality', function() { + describe('functionality', function () { - it('should succeed if valid resource and has no tags', function(done) { + it('should succeed if valid resource and has no tags', function (done) { var resourceArn = 'arn:aws:dynamodb:' + helpers.awsRegion + ':' + helpers.awsAccountId + ':table/' + helpers.testHashTable - request(opts({ResourceArn: resourceArn}), function(err, res) { + request(opts({ ResourceArn: resourceArn }), function (err, res) { if (err) return done(err) res.statusCode.should.equal(200) - res.body.should.eql({Tags: []}) + res.body.should.eql({ Tags: [] }) done() }) }) - it('should succeed if valid resource and has multiple tags', function(done) { + it('should succeed if valid resource and has multiple tags', function (done) { var resourceArn = 'arn:aws:dynamodb:' + helpers.awsRegion + ':' + helpers.awsAccountId + ':table/' + helpers.testHashTable - request(opts({ResourceArn: resourceArn}), function(err, res) { + request(opts({ ResourceArn: resourceArn }), function (err, res) { if (err) return done(err) res.statusCode.should.equal(200) - res.body.should.eql({Tags: []}) + res.body.should.eql({ Tags: [] }) - var tags = [{Key: 't1', Value: 'v1'}, {Key: 't2', Value: 'v2'}] + var tags = [ { Key: 't1', Value: 'v1' }, { Key: 't2', Value: 'v2' } ] - request(helpers.opts('TagResource', {ResourceArn: resourceArn, Tags: tags}), function(err, res) { + request(helpers.opts('TagResource', { ResourceArn: resourceArn, Tags: tags }), function (err, res) { if (err) return done(err) res.statusCode.should.equal(200) - request(opts({ResourceArn: resourceArn}), function(err, res) { + request(opts({ ResourceArn: resourceArn }), function (err, res) { if (err) return done(err) res.statusCode.should.equal(200) res.body.Tags.should.not.be.null() res.body.Tags.length.should.equal(tags.length) - res.body.Tags.forEach(function(tag) { tags.should.containEql(tag) }) + res.body.Tags.forEach(function (tag) { tags.should.containEql(tag) }) - var tagKeys = tags.map(function(tag) { return tag.Key }) + var tagKeys = tags.map(function (tag) { return tag.Key }) - request(helpers.opts('UntagResource', {ResourceArn: resourceArn, TagKeys: tagKeys}), function(err, res) { + request(helpers.opts('UntagResource', { ResourceArn: resourceArn, TagKeys: tagKeys }), function (err, res) { if (err) return done(err) res.statusCode.should.equal(200) - request(opts({ResourceArn: resourceArn}), function(err, res) { + request(opts({ ResourceArn: resourceArn }), function (err, res) { if (err) return done(err) res.statusCode.should.equal(200) - res.body.should.eql({Tags: []}) + res.body.should.eql({ Tags: [] }) done() }) diff --git a/test/putItem.js b/test/putItem.js index 63ed204..f1ed585 100644 --- a/test/putItem.js +++ b/test/putItem.js @@ -1,87 +1,87 @@ var async = require('async'), - helpers = require('./helpers') + helpers = require('./helpers') var target = 'PutItem', - request = helpers.request, - randomName = helpers.randomName, - opts = helpers.opts.bind(null, target), - assertType = helpers.assertType.bind(null, target), - assertValidation = helpers.assertValidation.bind(null, target), - assertNotFound = helpers.assertNotFound.bind(null, target), - assertConditional = helpers.assertConditional.bind(null, target) + request = helpers.request, + randomName = helpers.randomName, + opts = helpers.opts.bind(null, target), + assertType = helpers.assertType.bind(null, target), + assertValidation = helpers.assertValidation.bind(null, target), + assertNotFound = helpers.assertNotFound.bind(null, target), + assertConditional = helpers.assertConditional.bind(null, target) -describe('putItem', function() { +describe('putItem', function () { - describe('serializations', function() { + describe('serializations', function () { - it('should return SerializationException when TableName is not a string', function(done) { + it('should return SerializationException when TableName is not a string', function (done) { assertType('TableName', 'String', done) }) - it('should return SerializationException when Item is not a map', function(done) { + it('should return SerializationException when Item is not a map', function (done) { assertType('Item', 'Map', done) }) - it('should return SerializationException when Item.Attr is not an attr struct', function(done) { + it('should return SerializationException when Item.Attr is not an attr struct', function (done) { this.timeout(60000) assertType('Item.Attr', 'AttrStruct', done) }) - it('should return SerializationException when Expected is not a map', function(done) { + it('should return SerializationException when Expected is not a map', function (done) { assertType('Expected', 'Map', done) }) - it('should return SerializationException when Expected.Attr is not a struct', function(done) { + it('should return SerializationException when Expected.Attr is not a struct', function (done) { assertType('Expected.Attr', 'ValueStruct', done) }) - it('should return SerializationException when Expected.Attr.Exists is not a boolean', function(done) { + it('should return SerializationException when Expected.Attr.Exists is not a boolean', function (done) { assertType('Expected.Attr.Exists', 'Boolean', done) }) - it('should return SerializationException when Expected.Attr.Value is not an attr struct', function(done) { + it('should return SerializationException when Expected.Attr.Value is not an attr struct', function (done) { this.timeout(60000) assertType('Expected.Attr.Value', 'AttrStruct', done) }) - it('should return SerializationException when ReturnConsumedCapacity is not a string', function(done) { + it('should return SerializationException when ReturnConsumedCapacity is not a string', function (done) { assertType('ReturnConsumedCapacity', 'String', done) }) - it('should return SerializationException when ReturnItemCollectionMetrics is not a string', function(done) { + it('should return SerializationException when ReturnItemCollectionMetrics is not a string', function (done) { assertType('ReturnItemCollectionMetrics', 'String', done) }) - it('should return SerializationException when ReturnValues is not a string', function(done) { + it('should return SerializationException when ReturnValues is not a string', function (done) { assertType('ReturnValues', 'String', done) }) - it('should return SerializationException when ConditionExpression is not a string', function(done) { + it('should return SerializationException when ConditionExpression is not a string', function (done) { assertType('ConditionExpression', 'String', done) }) - it('should return SerializationException when ExpressionAttributeValues is not a map', function(done) { + it('should return SerializationException when ExpressionAttributeValues is not a map', function (done) { assertType('ExpressionAttributeValues', 'Map', done) }) - it('should return SerializationException when ExpressionAttributeValues.Attr is not an attr struct', function(done) { + it('should return SerializationException when ExpressionAttributeValues.Attr is not an attr struct', function (done) { this.timeout(60000) assertType('ExpressionAttributeValues.Attr', 'AttrStruct', done) }) - it('should return SerializationException when ExpressionAttributeNames is not a map', function(done) { + it('should return SerializationException when ExpressionAttributeNames is not a map', function (done) { assertType('ExpressionAttributeNames', 'Map', done) }) - it('should return SerializationException when ExpressionAttributeNames.Attr is not a string', function(done) { + it('should return SerializationException when ExpressionAttributeNames.Attr is not a string', function (done) { assertType('ExpressionAttributeNames.Attr', 'String', done) }) }) - describe('validations', function() { + describe('validations', function () { - it('should return ValidationException for no TableName', function(done) { + it('should return ValidationException for no TableName', function (done) { assertValidation({}, [ 'Value null at \'tableName\' failed to satisfy constraint: ' + 'Member must not be null', @@ -90,8 +90,8 @@ describe('putItem', function() { ], done) }) - it('should return ValidationException for empty TableName', function(done) { - assertValidation({TableName: ''}, [ + it('should return ValidationException for empty TableName', function (done) { + assertValidation({ TableName: '' }, [ 'Value \'\' at \'tableName\' failed to satisfy constraint: ' + 'Member must satisfy regular expression pattern: [a-zA-Z0-9_.-]+', 'Value \'\' at \'tableName\' failed to satisfy constraint: ' + @@ -101,8 +101,8 @@ describe('putItem', function() { ], done) }) - it('should return ValidationException for short TableName', function(done) { - assertValidation({TableName: 'a;'}, [ + it('should return ValidationException for short TableName', function (done) { + assertValidation({ TableName: 'a;' }, [ 'Value \'a;\' at \'tableName\' failed to satisfy constraint: ' + 'Member must satisfy regular expression pattern: [a-zA-Z0-9_.-]+', 'Value \'a;\' at \'tableName\' failed to satisfy constraint: ' + @@ -112,9 +112,9 @@ describe('putItem', function() { ], done) }) - it('should return ValidationException for long TableName', function(done) { + it('should return ValidationException for long TableName', function (done) { var name = new Array(256 + 1).join('a') - assertValidation({TableName: name}, [ + assertValidation({ TableName: name }, [ 'Value \'' + name + '\' at \'tableName\' failed to satisfy constraint: ' + 'Member must have length less than or equal to 255', 'Value null at \'item\' failed to satisfy constraint: ' + @@ -122,27 +122,27 @@ describe('putItem', function() { ], done) }) - it('should return ValidationException for incorrect attributes', function(done) { - assertValidation({TableName: 'abc;', ReturnConsumedCapacity: 'hi', - ReturnItemCollectionMetrics: 'hi', ReturnValues: 'hi'}, [ - 'Value \'hi\' at \'returnConsumedCapacity\' failed to satisfy constraint: ' + + it('should return ValidationException for incorrect attributes', function (done) { + assertValidation({ TableName: 'abc;', ReturnConsumedCapacity: 'hi', + ReturnItemCollectionMetrics: 'hi', ReturnValues: 'hi' }, [ + 'Value \'hi\' at \'returnConsumedCapacity\' failed to satisfy constraint: ' + 'Member must satisfy enum value set: [INDEXES, TOTAL, NONE]', - 'Value \'abc;\' at \'tableName\' failed to satisfy constraint: ' + + 'Value \'abc;\' at \'tableName\' failed to satisfy constraint: ' + 'Member must satisfy regular expression pattern: [a-zA-Z0-9_.-]+', - 'Value null at \'item\' failed to satisfy constraint: ' + + 'Value null at \'item\' failed to satisfy constraint: ' + 'Member must not be null', - 'Value \'hi\' at \'returnValues\' failed to satisfy constraint: ' + + 'Value \'hi\' at \'returnValues\' failed to satisfy constraint: ' + 'Member must satisfy enum value set: [ALL_NEW, UPDATED_OLD, ALL_OLD, NONE, UPDATED_NEW]', - 'Value \'hi\' at \'returnItemCollectionMetrics\' failed to satisfy constraint: ' + + 'Value \'hi\' at \'returnItemCollectionMetrics\' failed to satisfy constraint: ' + 'Member must satisfy enum value set: [SIZE, NONE]', - ], done) + ], done) }) - it('should return ValidationException if expression and non-expression', function(done) { + it('should return ValidationException if expression and non-expression', function (done) { assertValidation({ TableName: 'abc', - Item: {a: {}}, - Expected: {a: {}}, + Item: { a: {} }, + Expected: { a: {} }, ExpressionAttributeNames: {}, ExpressionAttributeValues: {}, ConditionExpression: '', @@ -150,50 +150,50 @@ describe('putItem', function() { 'Non-expression parameters: {Expected} Expression parameters: {ConditionExpression}', done) }) - it('should return ValidationException if ExpressionAttributeNames but no ConditionExpression', function(done) { + it('should return ValidationException if ExpressionAttributeNames but no ConditionExpression', function (done) { assertValidation({ TableName: 'abc', - Item: {a: {}}, - Expected: {a: {}}, + Item: { a: {} }, + Expected: { a: {} }, ExpressionAttributeNames: {}, ExpressionAttributeValues: {}, }, 'ExpressionAttributeNames can only be specified when using expressions', done) }) - it('should return ValidationException if ExpressionAttributeValues but no ConditionExpression', function(done) { + it('should return ValidationException if ExpressionAttributeValues but no ConditionExpression', function (done) { assertValidation({ TableName: 'abc', - Item: {a: {}}, - Expected: {a: {}}, + Item: { a: {} }, + Expected: { a: {} }, ExpressionAttributeValues: {}, }, 'ExpressionAttributeValues can only be specified when using expressions: ConditionExpression is null', done) }) - it('should return ValidationException for unsupported datatype in Item', function(done) { + it('should return ValidationException for unsupported datatype in Item', function (done) { async.forEach([ {}, - {a: ''}, - {M: {a: {}}}, - {L: [{}]}, - {L: [{a: {}}]}, - ], function(expr, cb) { - assertValidation({TableName: 'abc', Item: {a: expr}, Expected: {a: {}}}, + { a: '' }, + { M: { a: {} } }, + { L: [ {} ] }, + { L: [ { a: {} } ] }, + ], function (expr, cb) { + assertValidation({ TableName: 'abc', Item: { a: expr }, Expected: { a: {} } }, 'Supplied AttributeValue is empty, must contain exactly one of the supported datatypes', cb) }, done) }) - it('should return ValidationException for invalid values in Item', function(done) { + it('should return ValidationException for invalid values in Item', function (done) { async.forEach([ - [{NULL: 'no'}, 'Null attribute value types must have the value of true'], - [{SS: []}, 'An string set may not be empty'], - [{NS: []}, 'An number set may not be empty'], - [{BS: []}, 'Binary sets should not be empty'], - [{SS: ['a', 'a']}, 'Input collection [a, a] contains duplicates.'], - [{BS: ['Yg==', 'Yg==']}, 'Input collection [Yg==, Yg==]of type BS contains duplicates.'], - ], function(expr, cb) { + [ { NULL: 'no' }, 'Null attribute value types must have the value of true' ], + [ { SS: [] }, 'An string set may not be empty' ], + [ { NS: [] }, 'An number set may not be empty' ], + [ { BS: [] }, 'Binary sets should not be empty' ], + [ { SS: [ 'a', 'a' ] }, 'Input collection [a, a] contains duplicates.' ], + [ { BS: [ 'Yg==', 'Yg==' ] }, 'Input collection [Yg==, Yg==]of type BS contains duplicates.' ], + ], function (expr, cb) { assertValidation({ TableName: 'abc', - Item: {a: expr[0]}, + Item: { a: expr[0] }, ExpressionAttributeNames: {}, ExpressionAttributeValues: {}, ConditionExpression: '', @@ -201,229 +201,229 @@ describe('putItem', function() { }, done) }) - it('should return ValidationException for empty/invalid numbers in Item', function(done) { + it('should return ValidationException for empty/invalid numbers in Item', function (done) { async.forEach([ - [{S: '', N: ''}, 'The parameter cannot be converted to a numeric value'], - [{S: 'a', N: ''}, 'The parameter cannot be converted to a numeric value'], - [{S: 'a', N: 'b'}, 'The parameter cannot be converted to a numeric value: b'], - [{NS: ['1', '']}, 'The parameter cannot be converted to a numeric value'], - [{NS: ['1', 'b']}, 'The parameter cannot be converted to a numeric value: b'], - [{NS: ['1', '1']}, 'Input collection contains duplicates'], - [{N: '123456789012345678901234567890123456789'}, 'Attempting to store more than 38 significant digits in a Number'], - [{N: '-1.23456789012345678901234567890123456789'}, 'Attempting to store more than 38 significant digits in a Number'], - [{N: '1e126'}, 'Number overflow. Attempting to store a number with magnitude larger than supported range'], - [{N: '-1e126'}, 'Number overflow. Attempting to store a number with magnitude larger than supported range'], - [{N: '1e-131'}, 'Number underflow. Attempting to store a number with magnitude smaller than supported range'], - [{N: '-1e-131'}, 'Number underflow. Attempting to store a number with magnitude smaller than supported range'], - ], function(expr, cb) { - assertValidation({TableName: 'abc', Item: {a: expr[0]}}, expr[1], cb) + [ { S: '', N: '' }, 'The parameter cannot be converted to a numeric value' ], + [ { S: 'a', N: '' }, 'The parameter cannot be converted to a numeric value' ], + [ { S: 'a', N: 'b' }, 'The parameter cannot be converted to a numeric value: b' ], + [ { NS: [ '1', '' ] }, 'The parameter cannot be converted to a numeric value' ], + [ { NS: [ '1', 'b' ] }, 'The parameter cannot be converted to a numeric value: b' ], + [ { NS: [ '1', '1' ] }, 'Input collection contains duplicates' ], + [ { N: '123456789012345678901234567890123456789' }, 'Attempting to store more than 38 significant digits in a Number' ], + [ { N: '-1.23456789012345678901234567890123456789' }, 'Attempting to store more than 38 significant digits in a Number' ], + [ { N: '1e126' }, 'Number overflow. Attempting to store a number with magnitude larger than supported range' ], + [ { N: '-1e126' }, 'Number overflow. Attempting to store a number with magnitude larger than supported range' ], + [ { N: '1e-131' }, 'Number underflow. Attempting to store a number with magnitude smaller than supported range' ], + [ { N: '-1e-131' }, 'Number underflow. Attempting to store a number with magnitude smaller than supported range' ], + ], function (expr, cb) { + assertValidation({ TableName: 'abc', Item: { a: expr[0] } }, expr[1], cb) }, done) }) - it('should return ValidationException for multiple datatypes in Item', function(done) { - assertValidation({TableName: 'abc', Item: {'a': {S: 'a', N: '1'}}}, + it('should return ValidationException for multiple datatypes in Item', function (done) { + assertValidation({ TableName: 'abc', Item: { 'a': { S: 'a', N: '1' } } }, 'Supplied AttributeValue has more than one datatypes set, must contain exactly one of the supported datatypes', done) }) - it('should return ValidationException if item is too big with small attribute', function(done) { + it('should return ValidationException if item is too big with small attribute', function (done) { var keyStr = helpers.randomString(), b = new Array(helpers.MAX_SIZE + 1 - keyStr.length - 1).join('a') - assertValidation({TableName: 'aaa', Item: {a: {S: keyStr}, b: {S: b}}, Expected: {a: {}}}, + assertValidation({ TableName: 'aaa', Item: { a: { S: keyStr }, b: { S: b } }, Expected: { a: {} } }, 'Item size has exceeded the maximum allowed size', done) }) - it('should return ResourceNotFoundException if item is just small enough with small attribute', function(done) { + it('should return ResourceNotFoundException if item is just small enough with small attribute', function (done) { var keyStr = helpers.randomString(), b = new Array(helpers.MAX_SIZE + 1 - keyStr.length - 2).join('a') - assertNotFound({TableName: 'aaa', Item: {a: {S: keyStr}, b: {S: b}}}, + assertNotFound({ TableName: 'aaa', Item: { a: { S: keyStr }, b: { S: b } } }, 'Requested resource not found', done) }) - it('should return ValidationException if item is too big with larger attribute', function(done) { + it('should return ValidationException if item is too big with larger attribute', function (done) { var keyStr = helpers.randomString(), b = new Array(helpers.MAX_SIZE + 1 - keyStr.length - 27).join('a') - assertValidation({TableName: 'aaa', Item: {a: {S: keyStr}, bbbbbbbbbbbbbbbbbbbbbbbbbbb: {S: b}}}, + assertValidation({ TableName: 'aaa', Item: { a: { S: keyStr }, bbbbbbbbbbbbbbbbbbbbbbbbbbb: { S: b } } }, 'Item size has exceeded the maximum allowed size', done) }) - it('should return ResourceNotFoundException if item is just small enough with larger attribute', function(done) { + it('should return ResourceNotFoundException if item is just small enough with larger attribute', function (done) { var keyStr = helpers.randomString(), b = new Array(helpers.MAX_SIZE + 1 - keyStr.length - 28).join('a') - assertNotFound({TableName: 'aaa', Item: {a: {S: keyStr}, bbbbbbbbbbbbbbbbbbbbbbbbbbb: {S: b}}}, + assertNotFound({ TableName: 'aaa', Item: { a: { S: keyStr }, bbbbbbbbbbbbbbbbbbbbbbbbbbb: { S: b } } }, 'Requested resource not found', done) }) - it('should return ValidationException if item is too big with multi attributes', function(done) { + it('should return ValidationException if item is too big with multi attributes', function (done) { var keyStr = helpers.randomString(), b = new Array(helpers.MAX_SIZE + 1 - keyStr.length - 7).join('a') - assertValidation({TableName: 'aaa', Item: {a: {S: keyStr}, bb: {S: b}, ccc: {S: 'cc'}}}, + assertValidation({ TableName: 'aaa', Item: { a: { S: keyStr }, bb: { S: b }, ccc: { S: 'cc' } } }, 'Item size has exceeded the maximum allowed size', done) }) - it('should return ResourceNotFoundException if item is just small enough with multi attributes', function(done) { + it('should return ResourceNotFoundException if item is just small enough with multi attributes', function (done) { var keyStr = helpers.randomString(), b = new Array(helpers.MAX_SIZE + 1 - keyStr.length - 8).join('a') - assertNotFound({TableName: 'aaa', Item: {a: {S: keyStr}, bb: {S: b}, ccc: {S: 'cc'}}}, + assertNotFound({ TableName: 'aaa', Item: { a: { S: keyStr }, bb: { S: b }, ccc: { S: 'cc' } } }, 'Requested resource not found', done) }) - it('should return ValidationException if item is too big with big number attribute', function(done) { + it('should return ValidationException if item is too big with big number attribute', function (done) { var keyStr = helpers.randomString(), b = new Array(helpers.MAX_SIZE + 1 - keyStr.length - 1 - 1 - 20).join('a'), c = new Array(38 + 1).join('1') + new Array(89).join('0') - assertValidation({TableName: 'aaa', Item: {a: {S: keyStr}, b: {S: b}, c: {N: c}}}, + assertValidation({ TableName: 'aaa', Item: { a: { S: keyStr }, b: { S: b }, c: { N: c } } }, 'Item size has exceeded the maximum allowed size', done) }) - it('should return ValidationException if item is too big with smallest number attribute', function(done) { + it('should return ValidationException if item is too big with smallest number attribute', function (done) { var keyStr = helpers.randomString(), b = new Array(helpers.MAX_SIZE + 1 - keyStr.length - 1 - 1 - 2).join('a'), c = '1' + new Array(126).join('0') - assertValidation({TableName: 'aaa', Item: {a: {S: keyStr}, b: {S: b}, c: {N: c}}}, + assertValidation({ TableName: 'aaa', Item: { a: { S: keyStr }, b: { S: b }, c: { N: c } } }, 'Item size has exceeded the maximum allowed size', done) }) - it('should return ValidationException if item is too big with smaller number attribute', function(done) { + it('should return ValidationException if item is too big with smaller number attribute', function (done) { var keyStr = helpers.randomString(), b = new Array(helpers.MAX_SIZE + 1 - keyStr.length - 1 - 1 - 2).join('a'), c = '11' + new Array(125).join('0') - assertValidation({TableName: 'aaa', Item: {a: {S: keyStr}, b: {S: b}, c: {N: c}}}, + assertValidation({ TableName: 'aaa', Item: { a: { S: keyStr }, b: { S: b }, c: { N: c } } }, 'Item size has exceeded the maximum allowed size', done) }) - it('should return ValidationException if item is too big with medium number attribute', function(done) { + it('should return ValidationException if item is too big with medium number attribute', function (done) { var keyStr = helpers.randomString(), b = new Array(helpers.MAX_SIZE + 1 - keyStr.length - 1 - 1 - 4).join('a'), c = '11111' + new Array(122).join('0') - assertValidation({TableName: 'aaa', Item: {a: {S: keyStr}, b: {S: b}, c: {N: c}}}, + assertValidation({ TableName: 'aaa', Item: { a: { S: keyStr }, b: { S: b }, c: { N: c } } }, 'Item size has exceeded the maximum allowed size', done) }) - it('should return ValidationException if item is too big with medium number attribute', function(done) { + it('should return ValidationException if item is too big with medium number attribute', function (done) { var keyStr = helpers.randomString(), b = new Array(helpers.MAX_SIZE + 1 - keyStr.length - 1 - 1 - 4).join('a'), c = '111111' + new Array(121).join('0') - assertValidation({TableName: 'aaa', Item: {a: {S: keyStr}, b: {S: b}, c: {N: c}}}, + assertValidation({ TableName: 'aaa', Item: { a: { S: keyStr }, b: { S: b }, c: { N: c } } }, 'Item size has exceeded the maximum allowed size', done) }) - it('should return ValidationException if item is too big with medium number attribute', function(done) { + it('should return ValidationException if item is too big with medium number attribute', function (done) { var keyStr = helpers.randomString(), b = new Array(helpers.MAX_SIZE + 1 - keyStr.length - 1 - 1 - 5).join('a'), c = '1111111' + new Array(120).join('0') - assertValidation({TableName: 'aaa', Item: {a: {S: keyStr}, b: {S: b}, c: {N: c}}}, + assertValidation({ TableName: 'aaa', Item: { a: { S: keyStr }, b: { S: b }, c: { N: c } } }, 'Item size has exceeded the maximum allowed size', done) }) - it('should return ValidationException if item is too big with multi number attribute', function(done) { + it('should return ValidationException if item is too big with multi number attribute', function (done) { var keyStr = helpers.randomString(), b = new Array(helpers.MAX_SIZE + 1 - keyStr.length - 1 - 1 - 5 - 1 - 5).join('a'), c = '1111111' + new Array(120).join('0'), d = '1111111' + new Array(120).join('0') - assertValidation({TableName: 'aaa', Item: {a: {S: keyStr}, b: {S: b}, c: {N: c}, d: {N: d}}}, + assertValidation({ TableName: 'aaa', Item: { a: { S: keyStr }, b: { S: b }, c: { N: c }, d: { N: d } } }, 'Item size has exceeded the maximum allowed size', done) }) - it('should return ResourceNotFoundException if item is just small enough with multi number attribute', function(done) { + it('should return ResourceNotFoundException if item is just small enough with multi number attribute', function (done) { var keyStr = helpers.randomString(), b = new Array(helpers.MAX_SIZE + 1 - keyStr.length - 1 - 1 - 5 - 1 - 6).join('a'), c = '1111111' + new Array(120).join('0'), d = '1111111' + new Array(120).join('0') - assertNotFound({TableName: 'aaa', Item: {a: {S: keyStr}, b: {S: b}, c: {N: c}, d: {N: d}}}, + assertNotFound({ TableName: 'aaa', Item: { a: { S: keyStr }, b: { S: b }, c: { N: c }, d: { N: d } } }, 'Requested resource not found', done) }) - it('should return ValidationException if no value and no exists', function(done) { - assertValidation({TableName: 'abc', Item: {}, Expected: {a: {}}}, + it('should return ValidationException if no value and no exists', function (done) { + assertValidation({ TableName: 'abc', Item: {}, Expected: { a: {} } }, 'One or more parameter values were invalid: Value must be provided when Exists is null for Attribute: a', done) }) - it('should return ValidationException for Exists true with no value', function(done) { - assertValidation({TableName: 'abc', Item: {}, Expected: {a: {Exists: true}}}, + it('should return ValidationException for Exists true with no value', function (done) { + assertValidation({ TableName: 'abc', Item: {}, Expected: { a: { Exists: true } } }, 'One or more parameter values were invalid: Value must be provided when Exists is true for Attribute: a', done) }) - it('should return ValidationException for Exists false with value', function(done) { - assertValidation({TableName: 'abc', Item: {}, Expected: {a: {Exists: false, Value: {S: 'a'}}}}, + it('should return ValidationException for Exists false with value', function (done) { + assertValidation({ TableName: 'abc', Item: {}, Expected: { a: { Exists: false, Value: { S: 'a' } } } }, 'One or more parameter values were invalid: Value cannot be used when Exists is false for Attribute: a', done) }) - it('should return ValidationException for incorrect ReturnValues', function(done) { - async.forEach(['UPDATED_OLD', 'ALL_NEW', 'UPDATED_NEW'], function(returnValues, cb) { - assertValidation({TableName: 'abc', Item: {}, ReturnValues: returnValues}, + it('should return ValidationException for incorrect ReturnValues', function (done) { + async.forEach([ 'UPDATED_OLD', 'ALL_NEW', 'UPDATED_NEW' ], function (returnValues, cb) { + assertValidation({ TableName: 'abc', Item: {}, ReturnValues: returnValues }, 'ReturnValues can only be ALL_OLD or NONE', cb) }, done) }) - it('should return ValidationException if ComparisonOperator used alone', function(done) { - assertValidation({TableName: 'aaa', Item: {}, Expected: {a: {ComparisonOperator: 'LT'}}}, + it('should return ValidationException if ComparisonOperator used alone', function (done) { + assertValidation({ TableName: 'aaa', Item: {}, Expected: { a: { ComparisonOperator: 'LT' } } }, 'One or more parameter values were invalid: Value or AttributeValueList must be used with ComparisonOperator: LT for Attribute: a', done) }) - it('should return ValidationException if ComparisonOperator and Exists are used together', function(done) { - assertValidation({TableName: 'aaa', Item: {}, Expected: {a: {Exists: true, ComparisonOperator: 'LT'}}}, + it('should return ValidationException if ComparisonOperator and Exists are used together', function (done) { + assertValidation({ TableName: 'aaa', Item: {}, Expected: { a: { Exists: true, ComparisonOperator: 'LT' } } }, 'One or more parameter values were invalid: Exists and ComparisonOperator cannot be used together for Attribute: a', done) }) - it('should return ValidationException if AttributeValueList and Value are used together', function(done) { - var expected = {a: { - AttributeValueList: [{S: 'a'}], - Value: {S: 'a'}, + it('should return ValidationException if AttributeValueList and Value are used together', function (done) { + var expected = { a: { + AttributeValueList: [ { S: 'a' } ], + Value: { S: 'a' }, ComparisonOperator: 'LT', - }} - assertValidation({TableName: 'aaa', Item: {}, Expected: expected}, + } } + assertValidation({ TableName: 'aaa', Item: {}, Expected: expected }, 'One or more parameter values were invalid: Value and AttributeValueList cannot be used together for Attribute: a', done) }) - it('should return ValidationException if AttributeValueList used without ComparisonOperator', function(done) { - assertValidation({TableName: 'aaa', Item: {}, Expected: {a: {AttributeValueList: [{S: 'a'}]}}}, + it('should return ValidationException if AttributeValueList used without ComparisonOperator', function (done) { + assertValidation({ TableName: 'aaa', Item: {}, Expected: { a: { AttributeValueList: [ { S: 'a' } ] } } }, 'One or more parameter values were invalid: AttributeValueList can only be used with a ComparisonOperator for Attribute: a', done) }) - it('should return ValidationException if AttributeValueList used with Exists', function(done) { - assertValidation({TableName: 'aaa', Item: {}, Expected: {a: {Exists: true, AttributeValueList: [{S: 'a'}]}}}, + it('should return ValidationException if AttributeValueList used with Exists', function (done) { + assertValidation({ TableName: 'aaa', Item: {}, Expected: { a: { Exists: true, AttributeValueList: [ { S: 'a' } ] } } }, 'One or more parameter values were invalid: AttributeValueList can only be used with a ComparisonOperator for Attribute: a', done) }) - it('should return ValidationException if AttributeValueList is incorrect length: EQ', function(done) { - var expected = {a: { + it('should return ValidationException if AttributeValueList is incorrect length: EQ', function (done) { + var expected = { a: { AttributeValueList: [], ComparisonOperator: 'EQ', - }} - assertValidation({TableName: 'aaa', Item: {}, Expected: expected}, + } } + assertValidation({ TableName: 'aaa', Item: {}, Expected: expected }, 'One or more parameter values were invalid: Invalid number of argument(s) for the EQ ComparisonOperator', done) }) - it('should return ValidationException if AttributeValueList is incorrect length: NULL', function(done) { - var expected = {a: { - AttributeValueList: [{S: 'a'}], + it('should return ValidationException if AttributeValueList is incorrect length: NULL', function (done) { + var expected = { a: { + AttributeValueList: [ { S: 'a' } ], ComparisonOperator: 'NULL', - }} - assertValidation({TableName: 'aaa', Item: {}, Expected: expected}, + } } + assertValidation({ TableName: 'aaa', Item: {}, Expected: expected }, 'One or more parameter values were invalid: Invalid number of argument(s) for the NULL ComparisonOperator', done) }) - it('should return ValidationException if AttributeValueList is incorrect length: IN', function(done) { - var expected = {a: { + it('should return ValidationException if AttributeValueList is incorrect length: IN', function (done) { + var expected = { a: { AttributeValueList: [], ComparisonOperator: 'IN', - }} - assertValidation({TableName: 'aaa', Item: {}, Expected: expected}, + } } + assertValidation({ TableName: 'aaa', Item: {}, Expected: expected }, 'One or more parameter values were invalid: Invalid number of argument(s) for the IN ComparisonOperator', done) }) - it('should return ValidationException if AttributeValueList is incorrect length: BETWEEN', function(done) { - var expected = {a: { - AttributeValueList: [{N: '1'}, {N: '10'}, {N: '12'}], + it('should return ValidationException if AttributeValueList is incorrect length: BETWEEN', function (done) { + var expected = { a: { + AttributeValueList: [ { N: '1' }, { N: '10' }, { N: '12' } ], ComparisonOperator: 'BETWEEN', - }} - assertValidation({TableName: 'aaa', Item: {}, Expected: expected}, + } } + assertValidation({ TableName: 'aaa', Item: {}, Expected: expected }, 'One or more parameter values were invalid: Invalid number of argument(s) for the BETWEEN ComparisonOperator', done) }) - it('should return ValidationException if Value provides incorrect number of attributes: NULL', function(done) { - var expected = {a: { - Value: {S: 'a'}, + it('should return ValidationException if Value provides incorrect number of attributes: NULL', function (done) { + var expected = { a: { + Value: { S: 'a' }, ComparisonOperator: 'NULL', - }} - assertValidation({TableName: 'aaa', Item: {}, Expected: expected}, + } } + assertValidation({ TableName: 'aaa', Item: {}, Expected: expected }, 'One or more parameter values were invalid: Invalid number of argument(s) for the NULL ComparisonOperator', done) }) - it('should return ValidationException if Value provides incorrect number of attributes: BETWEEN', function(done) { - var expected = {a: { - Value: {S: 'a'}, + it('should return ValidationException if Value provides incorrect number of attributes: BETWEEN', function (done) { + var expected = { a: { + Value: { S: 'a' }, ComparisonOperator: 'BETWEEN', - }} - assertValidation({TableName: 'aaa', Item: {}, Expected: expected}, + } } + assertValidation({ TableName: 'aaa', Item: {}, Expected: expected }, 'One or more parameter values were invalid: Invalid number of argument(s) for the BETWEEN ComparisonOperator', done) }) - it('should return ValidationException for empty ExpressionAttributeNames', function(done) { + it('should return ValidationException for empty ExpressionAttributeNames', function (done) { assertValidation({ TableName: 'abc', Item: {}, @@ -433,17 +433,17 @@ describe('putItem', function() { }, 'ExpressionAttributeNames must not be empty', done) }) - it('should return ValidationException for invalid ExpressionAttributeNames', function(done) { + it('should return ValidationException for invalid ExpressionAttributeNames', function (done) { assertValidation({ TableName: 'abc', Item: {}, - ExpressionAttributeNames: {'a': 'a'}, + ExpressionAttributeNames: { 'a': 'a' }, ExpressionAttributeValues: {}, ConditionExpression: '', }, 'ExpressionAttributeNames contains invalid key: Syntax error; key: "a"', done) }) - it('should return ValidationException for empty ExpressionAttributeValues', function(done) { + it('should return ValidationException for empty ExpressionAttributeValues', function (done) { assertValidation({ TableName: 'abc', Item: {}, @@ -452,16 +452,16 @@ describe('putItem', function() { }, 'ExpressionAttributeValues must not be empty', done) }) - it('should return ValidationException for invalid ExpressionAttributeValues', function(done) { + it('should return ValidationException for invalid ExpressionAttributeValues', function (done) { assertValidation({ TableName: 'abc', Item: {}, - ExpressionAttributeValues: {'a': {S: 'a'}}, + ExpressionAttributeValues: { 'a': { S: 'a' } }, ConditionExpression: '', }, 'ExpressionAttributeValues contains invalid key: Syntax error; key: "a"', done) }) - it('should return ValidationException for empty ConditionExpression', function(done) { + it('should return ValidationException for empty ConditionExpression', function (done) { assertValidation({ TableName: 'abc', Item: {}, @@ -469,84 +469,84 @@ describe('putItem', function() { }, 'Invalid ConditionExpression: The expression can not be empty;', done) }) - it('should return ResourceNotFoundException if key is empty and table does not exist', function(done) { - assertNotFound({TableName: helpers.randomString(), Item: {}}, + it('should return ResourceNotFoundException if key is empty and table does not exist', function (done) { + assertNotFound({ TableName: helpers.randomString(), Item: {} }, 'Requested resource not found', done) }) - it('should return ValidationException if missing key', function(done) { + it('should return ValidationException if missing key', function (done) { async.forEach([ {}, - {b: {S: 'a'}}, - ], function(expr, cb) { - assertValidation({TableName: helpers.testHashTable, Item: expr}, + { b: { S: 'a' } }, + ], function (expr, cb) { + assertValidation({ TableName: helpers.testHashTable, Item: expr }, 'One or more parameter values were invalid: Missing the key a in the item', cb) }, done) }) - it('should return ValidationException if type mismatch for key', function(done) { + it('should return ValidationException if type mismatch for key', function (done) { async.forEach([ - {a: {B: 'abcd'}}, - {a: {N: '1'}}, - {a: {BOOL: true}}, - {a: {NULL: true}}, - {a: {SS: ['a']}}, - {a: {NS: ['1']}}, - {a: {BS: ['aaaa']}}, - {a: {M: {}}}, - {a: {L: []}}, - ], function(expr, cb) { - assertValidation({TableName: helpers.testHashTable, Item: expr}, + { a: { B: 'abcd' } }, + { a: { N: '1' } }, + { a: { BOOL: true } }, + { a: { NULL: true } }, + { a: { SS: [ 'a' ] } }, + { a: { NS: [ '1' ] } }, + { a: { BS: [ 'aaaa' ] } }, + { a: { M: {} } }, + { a: { L: [] } }, + ], function (expr, cb) { + assertValidation({ TableName: helpers.testHashTable, Item: expr }, 'One or more parameter values were invalid: Type mismatch for key a expected: S actual: ' + Object.keys(expr.a)[0], cb) }, done) }) - it('should return ValidationException if empty string key', function(done) { - assertValidation({TableName: helpers.testHashTable, Item: {a: {S: ''}}}, + it('should return ValidationException if empty string key', function (done) { + assertValidation({ TableName: helpers.testHashTable, Item: { a: { S: '' } } }, 'One or more parameter values are not valid. The AttributeValue for a key attribute cannot contain an empty string value. Key: a', done) }) - it('should return ValidationException if empty binary key', function(done) { - assertValidation({TableName: helpers.testRangeBTable, Item: {a: {S: 'a'}, b: {B: ''}}}, + it('should return ValidationException if empty binary key', function (done) { + assertValidation({ TableName: helpers.testRangeBTable, Item: { a: { S: 'a' }, b: { B: '' } } }, 'One or more parameter values are not valid. The AttributeValue for a key attribute cannot contain an empty binary value. Key: b', done) }) - it('should return ValidationException if missing range key', function(done) { - assertValidation({TableName: helpers.testRangeTable, Item: {a: {S: 'a'}}}, + it('should return ValidationException if missing range key', function (done) { + assertValidation({ TableName: helpers.testRangeTable, Item: { a: { S: 'a' } } }, 'One or more parameter values were invalid: Missing the key b in the item', done) }) - it('should return ValidationException if secondary index key is incorrect type', function(done) { - assertValidation({TableName: helpers.testRangeTable, Item: {a: {S: 'a'}, b: {S: 'a'}, c: {N: '1'}}}, + it('should return ValidationException if secondary index key is incorrect type', function (done) { + assertValidation({ TableName: helpers.testRangeTable, Item: { a: { S: 'a' }, b: { S: 'a' }, c: { N: '1' } } }, new RegExp('^One or more parameter values were invalid: ' + 'Type mismatch for Index Key c Expected: S Actual: N IndexName: index\\d$'), done) }) - it('should return ValidationException if hash key is too big', function(done) { + it('should return ValidationException if hash key is too big', function (done) { var keyStr = (helpers.randomString() + new Array(2048).join('a')).slice(0, 2049) - assertValidation({TableName: helpers.testHashTable, Item: {a: {S: keyStr}}}, + assertValidation({ TableName: helpers.testHashTable, Item: { a: { S: keyStr } } }, 'One or more parameter values were invalid: ' + 'Size of hashkey has exceeded the maximum size limit of2048 bytes', done) }) - it('should return ValidationException if range key is too big', function(done) { + it('should return ValidationException if range key is too big', function (done) { var keyStr = (helpers.randomString() + new Array(1024).join('a')).slice(0, 1025) - assertValidation({TableName: helpers.testRangeTable, Item: {a: {S: 'a'}, b: {S: keyStr}}}, + assertValidation({ TableName: helpers.testRangeTable, Item: { a: { S: 'a' }, b: { S: keyStr } } }, 'One or more parameter values were invalid: ' + 'Aggregated size of all range keys has exceeded the size limit of 1024 bytes', done) }) - it('should return ResourceNotFoundException if table is being created', function(done) { + it('should return ResourceNotFoundException if table is being created', function (done) { var table = { TableName: randomName(), - AttributeDefinitions: [{AttributeName: 'a', AttributeType: 'S'}], - KeySchema: [{KeyType: 'HASH', AttributeName: 'a'}], - ProvisionedThroughput: {ReadCapacityUnits: 1, WriteCapacityUnits: 1}, + AttributeDefinitions: [ { AttributeName: 'a', AttributeType: 'S' } ], + KeySchema: [ { KeyType: 'HASH', AttributeName: 'a' } ], + ProvisionedThroughput: { ReadCapacityUnits: 1, WriteCapacityUnits: 1 }, } - request(helpers.opts('CreateTable', table), function(err, res) { + request(helpers.opts('CreateTable', table), function (err, res) { if (err) return done(err) res.statusCode.should.equal(200) - assertNotFound({TableName: table.TableName, Item: {a: {S: 'a'}}}, + assertNotFound({ TableName: table.TableName, Item: { a: { S: 'a' } } }, 'Requested resource not found', done) helpers.deleteWhenActive(table.TableName) }) @@ -555,128 +555,128 @@ describe('putItem', function() { // A number can have up to 38 digits precision and can be between 10^-128 to 10^+126 - describe('functionality', function() { + describe('functionality', function () { - it('should put basic item', function(done) { - var item = {a: {S: helpers.randomString()}} - request(opts({TableName: helpers.testHashTable, Item: item}), function(err, res) { + it('should put basic item', function (done) { + var item = { a: { S: helpers.randomString() } } + request(opts({ TableName: helpers.testHashTable, Item: item }), function (err, res) { if (err) return done(err) res.statusCode.should.equal(200) res.body.should.eql({}) - request(helpers.opts('GetItem', {TableName: helpers.testHashTable, Key: {a: item.a}, ConsistentRead: true}), function(err, res) { + request(helpers.opts('GetItem', { TableName: helpers.testHashTable, Key: { a: item.a }, ConsistentRead: true }), function (err, res) { if (err) return done(err) res.statusCode.should.equal(200) - res.body.should.eql({Item: item}) + res.body.should.eql({ Item: item }) done() }) }) }) - it('should put empty values', function(done) { + it('should put empty values', function (done) { var item = { - a: {S: helpers.randomString()}, - b: {S: ''}, - c: {B: ''}, - d: {SS: ['']}, - e: {BS: ['']}, + a: { S: helpers.randomString() }, + b: { S: '' }, + c: { B: '' }, + d: { SS: [ '' ] }, + e: { BS: [ '' ] }, } - request(opts({TableName: helpers.testHashTable, Item: item}), function(err, res) { + request(opts({ TableName: helpers.testHashTable, Item: item }), function (err, res) { if (err) return done(err) res.body.should.eql({}) res.statusCode.should.equal(200) - request(helpers.opts('GetItem', {TableName: helpers.testHashTable, Key: {a: item.a}, ConsistentRead: true}), function(err, res) { + request(helpers.opts('GetItem', { TableName: helpers.testHashTable, Key: { a: item.a }, ConsistentRead: true }), function (err, res) { if (err) return done(err) res.statusCode.should.equal(200) - item.b = {S: ''} - item.c = {B: ''} - item.d = {SS: ['']} - item.e = {BS: ['']} - res.body.should.eql({Item: item}) + item.b = { S: '' } + item.c = { B: '' } + item.d = { SS: [ '' ] } + item.e = { BS: [ '' ] } + res.body.should.eql({ Item: item }) done() }) }) }) - it('should put really long numbers', function(done) { + it('should put really long numbers', function (done) { var item = { - a: {S: helpers.randomString()}, - b: {N: '0000012345678901234567890123456789012345678'}, - c: {N: '-00001.23456789012345678901234567890123456780000'}, - d: {N: '0009.99999999999999999999999999999999999990000e125'}, - e: {N: '-0009.99999999999999999999999999999999999990000e125'}, - f: {N: '0001.000e-130'}, - g: {N: '-0001.000e-130'}, + a: { S: helpers.randomString() }, + b: { N: '0000012345678901234567890123456789012345678' }, + c: { N: '-00001.23456789012345678901234567890123456780000' }, + d: { N: '0009.99999999999999999999999999999999999990000e125' }, + e: { N: '-0009.99999999999999999999999999999999999990000e125' }, + f: { N: '0001.000e-130' }, + g: { N: '-0001.000e-130' }, } - request(opts({TableName: helpers.testHashTable, Item: item}), function(err, res) { + request(opts({ TableName: helpers.testHashTable, Item: item }), function (err, res) { if (err) return done(err) res.statusCode.should.equal(200) res.body.should.eql({}) - request(helpers.opts('GetItem', {TableName: helpers.testHashTable, Key: {a: item.a}, ConsistentRead: true}), function(err, res) { + request(helpers.opts('GetItem', { TableName: helpers.testHashTable, Key: { a: item.a }, ConsistentRead: true }), function (err, res) { if (err) return done(err) res.statusCode.should.equal(200) - item.b = {N: '12345678901234567890123456789012345678'} - item.c = {N: '-1.2345678901234567890123456789012345678'} - item.d = {N: Array(39).join('9') + Array(89).join('0')} - item.e = {N: '-' + Array(39).join('9') + Array(89).join('0')} - item.f = {N: '0.' + Array(130).join('0') + '1'} - item.g = {N: '-0.' + Array(130).join('0') + '1'} - res.body.should.eql({Item: item}) + item.b = { N: '12345678901234567890123456789012345678' } + item.c = { N: '-1.2345678901234567890123456789012345678' } + item.d = { N: Array(39).join('9') + Array(89).join('0') } + item.e = { N: '-' + Array(39).join('9') + Array(89).join('0') } + item.f = { N: '0.' + Array(130).join('0') + '1' } + item.g = { N: '-0.' + Array(130).join('0') + '1' } + res.body.should.eql({ Item: item }) done() }) }) }) - it('should put multi attribute item', function(done) { + it('should put multi attribute item', function (done) { var item = { - a: {S: helpers.randomString()}, - b: {N: '-56.789'}, - c: {B: 'Yg=='}, - d: {BOOL: false}, - e: {NULL: true}, - f: {SS: ['a']}, - g: {NS: ['-56.789']}, - h: {BS: ['Yg==']}, - i: {L: [ - {S: 'a'}, - {N: '-56.789'}, - {B: 'Yg=='}, - {BOOL: true}, - {NULL: true}, - {SS: ['a']}, - {NS: ['-56.789']}, - {BS: ['Yg==']}, - {L: []}, - {M: {}}, - ]}, - j: {M: { - a: {S: 'a'}, - b: {N: '-56.789'}, - c: {B: 'Yg=='}, - d: {BOOL: true}, - e: {NULL: true}, - f: {SS: ['a']}, - g: {NS: ['-56.789']}, - h: {BS: ['Yg==']}, - i: {L: []}, - j: {M: {a: {M: {}}, b: {L: []}}}, - }}, + a: { S: helpers.randomString() }, + b: { N: '-56.789' }, + c: { B: 'Yg==' }, + d: { BOOL: false }, + e: { NULL: true }, + f: { SS: [ 'a' ] }, + g: { NS: [ '-56.789' ] }, + h: { BS: [ 'Yg==' ] }, + i: { L: [ + { S: 'a' }, + { N: '-56.789' }, + { B: 'Yg==' }, + { BOOL: true }, + { NULL: true }, + { SS: [ 'a' ] }, + { NS: [ '-56.789' ] }, + { BS: [ 'Yg==' ] }, + { L: [] }, + { M: {} }, + ] }, + j: { M: { + a: { S: 'a' }, + b: { N: '-56.789' }, + c: { B: 'Yg==' }, + d: { BOOL: true }, + e: { NULL: true }, + f: { SS: [ 'a' ] }, + g: { NS: [ '-56.789' ] }, + h: { BS: [ 'Yg==' ] }, + i: { L: [] }, + j: { M: { a: { M: {} }, b: { L: [] } } }, + } }, } - request(opts({TableName: helpers.testHashTable, Item: item}), function(err, res) { + request(opts({ TableName: helpers.testHashTable, Item: item }), function (err, res) { if (err) return done(err) res.statusCode.should.equal(200) res.body.should.eql({}) - request(helpers.opts('GetItem', {TableName: helpers.testHashTable, Key: {a: item.a}, ConsistentRead: true}), function(err, res) { + request(helpers.opts('GetItem', { TableName: helpers.testHashTable, Key: { a: item.a }, ConsistentRead: true }), function (err, res) { if (err) return done(err) res.statusCode.should.equal(200) - res.body.should.eql({Item: item}) + res.body.should.eql({ Item: item }) done() }) }) }) - it('should return empty when there are no old values', function(done) { - var item = {a: {S: helpers.randomString()}, b: {S: 'a'}, c: {S: 'a'}} - request(opts({TableName: helpers.testHashTable, Item: item, ReturnValues: 'ALL_OLD'}), function(err, res) { + it('should return empty when there are no old values', function (done) { + var item = { a: { S: helpers.randomString() }, b: { S: 'a' }, c: { S: 'a' } } + request(opts({ TableName: helpers.testHashTable, Item: item, ReturnValues: 'ALL_OLD' }), function (err, res) { if (err) return done(err) res.statusCode.should.equal(200) res.body.should.eql({}) @@ -684,68 +684,68 @@ describe('putItem', function() { }) }) - it('should return correct old values when they exist', function(done) { - var item = {a: {S: helpers.randomString()}, b: {N: '-0015.789e6'}, c: {S: 'a'}} - request(opts({TableName: helpers.testHashTable, Item: item}), function(err, res) { + it('should return correct old values when they exist', function (done) { + var item = { a: { S: helpers.randomString() }, b: { N: '-0015.789e6' }, c: { S: 'a' } } + request(opts({ TableName: helpers.testHashTable, Item: item }), function (err, res) { if (err) return done(err) res.statusCode.should.equal(200) - item.b = {S: 'b'} - request(opts({TableName: helpers.testHashTable, Item: item, ReturnValues: 'ALL_OLD'}), function(err, res) { + item.b = { S: 'b' } + request(opts({ TableName: helpers.testHashTable, Item: item, ReturnValues: 'ALL_OLD' }), function (err, res) { if (err) return done(err) res.statusCode.should.equal(200) - item.b = {N: '-15789000'} - res.body.should.eql({Attributes: item}) + item.b = { N: '-15789000' } + res.body.should.eql({ Attributes: item }) done() }) }) }) - it('should put basic range item', function(done) { - var item = {a: {S: helpers.randomString()}, b: {S: 'a'}, c: {S: 'a'}} - request(opts({TableName: helpers.testRangeTable, Item: item}), function(err, res) { + it('should put basic range item', function (done) { + var item = { a: { S: helpers.randomString() }, b: { S: 'a' }, c: { S: 'a' } } + request(opts({ TableName: helpers.testRangeTable, Item: item }), function (err, res) { if (err) return done(err) res.statusCode.should.equal(200) res.body.should.eql({}) // Put another item with the same hash key to prove we're retrieving the correct one - request(opts({TableName: helpers.testRangeTable, Item: {a: item.a, b: {S: 'b'}}}), function(err, res) { + request(opts({ TableName: helpers.testRangeTable, Item: { a: item.a, b: { S: 'b' } } }), function (err, res) { if (err) return done(err) res.statusCode.should.equal(200) - request(helpers.opts('GetItem', {TableName: helpers.testRangeTable, Key: {a: item.a, b: item.b}, ConsistentRead: true}), function(err, res) { + request(helpers.opts('GetItem', { TableName: helpers.testRangeTable, Key: { a: item.a, b: item.b }, ConsistentRead: true }), function (err, res) { if (err) return done(err) res.statusCode.should.equal(200) - res.body.should.eql({Item: item}) + res.body.should.eql({ Item: item }) done() }) }) }) }) - it('should return ConditionalCheckFailedException if expecting non-existent key to exist', function(done) { + it('should return ConditionalCheckFailedException if expecting non-existent key to exist', function (done) { async.forEach([ - {Expected: {a: {Value: {S: helpers.randomString()}}}}, - {Expected: {a: {ComparisonOperator: 'NOT_NULL'}}}, - {ConditionExpression: 'a = :a', ExpressionAttributeValues: {':a': {S: helpers.randomString()}}}, - {ConditionExpression: '#a = :a', ExpressionAttributeNames: {'#a': 'a'}, ExpressionAttributeValues: {':a': {S: helpers.randomString()}}}, - {ConditionExpression: 'attribute_exists(a)'}, - {ConditionExpression: 'attribute_exists(#a)', ExpressionAttributeNames: {'#a': 'a'}}, - ], function(putOpts, cb) { + { Expected: { a: { Value: { S: helpers.randomString() } } } }, + { Expected: { a: { ComparisonOperator: 'NOT_NULL' } } }, + { ConditionExpression: 'a = :a', ExpressionAttributeValues: { ':a': { S: helpers.randomString() } } }, + { ConditionExpression: '#a = :a', ExpressionAttributeNames: { '#a': 'a' }, ExpressionAttributeValues: { ':a': { S: helpers.randomString() } } }, + { ConditionExpression: 'attribute_exists(a)' }, + { ConditionExpression: 'attribute_exists(#a)', ExpressionAttributeNames: { '#a': 'a' } }, + ], function (putOpts, cb) { putOpts.TableName = helpers.testHashTable - putOpts.Item = {a: {S: helpers.randomString()}} + putOpts.Item = { a: { S: helpers.randomString() } } assertConditional(putOpts, cb) }, done) }) - it('should return ConditionalCheckFailedException if expecting existing key to not exist', function(done) { - var item = {a: {S: helpers.randomString()}} - request(opts({TableName: helpers.testHashTable, Item: item}), function(err, res) { + it('should return ConditionalCheckFailedException if expecting existing key to not exist', function (done) { + var item = { a: { S: helpers.randomString() } } + request(opts({ TableName: helpers.testHashTable, Item: item }), function (err, res) { if (err) return done(err) res.statusCode.should.equal(200) async.forEach([ - {Expected: {a: {Exists: false}}}, - {Expected: {a: {ComparisonOperator: 'NULL'}}}, - {ConditionExpression: 'attribute_not_exists(a)'}, - {ConditionExpression: 'attribute_not_exists(#a)', ExpressionAttributeNames: {'#a': 'a'}}, - ], function(putOpts, cb) { + { Expected: { a: { Exists: false } } }, + { Expected: { a: { ComparisonOperator: 'NULL' } } }, + { ConditionExpression: 'attribute_not_exists(a)' }, + { ConditionExpression: 'attribute_not_exists(#a)', ExpressionAttributeNames: { '#a': 'a' } }, + ], function (putOpts, cb) { putOpts.TableName = helpers.testHashTable putOpts.Item = item assertConditional(putOpts, cb) @@ -753,20 +753,20 @@ describe('putItem', function() { }) }) - it('should succeed if conditional key is different and exists is false', function(done) { - var item = {a: {S: helpers.randomString()}} - request(opts({TableName: helpers.testHashTable, Item: item}), function(err, res) { + it('should succeed if conditional key is different and exists is false', function (done) { + var item = { a: { S: helpers.randomString() } } + request(opts({ TableName: helpers.testHashTable, Item: item }), function (err, res) { if (err) return done(err) res.statusCode.should.equal(200) async.forEach([ - {Expected: {a: {Exists: false}}}, - {Expected: {a: {ComparisonOperator: 'NULL'}}}, - {ConditionExpression: 'attribute_not_exists(a)'}, - {ConditionExpression: 'attribute_not_exists(#a)', ExpressionAttributeNames: {'#a': 'a'}}, - ], function(putOpts, cb) { + { Expected: { a: { Exists: false } } }, + { Expected: { a: { ComparisonOperator: 'NULL' } } }, + { ConditionExpression: 'attribute_not_exists(a)' }, + { ConditionExpression: 'attribute_not_exists(#a)', ExpressionAttributeNames: { '#a': 'a' } }, + ], function (putOpts, cb) { putOpts.TableName = helpers.testHashTable - putOpts.Item = {a: {S: helpers.randomString()}} - request(opts(putOpts), function(err, res) { + putOpts.Item = { a: { S: helpers.randomString() } } + request(opts(putOpts), function (err, res) { if (err) return cb(err) res.statusCode.should.equal(200) res.body.should.eql({}) @@ -776,25 +776,25 @@ describe('putItem', function() { }) }) - it('should succeed if conditional key is same', function(done) { - var item = {a: {S: helpers.randomString()}} - request(opts({TableName: helpers.testHashTable, Item: item}), function(err, res) { + it('should succeed if conditional key is same', function (done) { + var item = { a: { S: helpers.randomString() } } + request(opts({ TableName: helpers.testHashTable, Item: item }), function (err, res) { if (err) return done(err) res.statusCode.should.equal(200) async.forEach([ - {Expected: {a: {Value: item.a}}}, - {Expected: {a: {ComparisonOperator: 'EQ', AttributeValueList: [item.a]}}}, - {Expected: {a: {Value: item.a, ComparisonOperator: 'EQ'}}}, - {Expected: {b: {Exists: false}}}, - {Expected: {b: {ComparisonOperator: 'NULL'}}}, - {ConditionExpression: 'a = :a', ExpressionAttributeValues: {':a': item.a}}, - {ConditionExpression: '#a = :a', ExpressionAttributeNames: {'#a': 'a'}, ExpressionAttributeValues: {':a': item.a}}, - {ConditionExpression: 'attribute_not_exists(b)'}, - {ConditionExpression: 'attribute_not_exists(#b)', ExpressionAttributeNames: {'#b': 'b'}}, - ], function(putOpts, cb) { + { Expected: { a: { Value: item.a } } }, + { Expected: { a: { ComparisonOperator: 'EQ', AttributeValueList: [ item.a ] } } }, + { Expected: { a: { Value: item.a, ComparisonOperator: 'EQ' } } }, + { Expected: { b: { Exists: false } } }, + { Expected: { b: { ComparisonOperator: 'NULL' } } }, + { ConditionExpression: 'a = :a', ExpressionAttributeValues: { ':a': item.a } }, + { ConditionExpression: '#a = :a', ExpressionAttributeNames: { '#a': 'a' }, ExpressionAttributeValues: { ':a': item.a } }, + { ConditionExpression: 'attribute_not_exists(b)' }, + { ConditionExpression: 'attribute_not_exists(#b)', ExpressionAttributeNames: { '#b': 'b' } }, + ], function (putOpts, cb) { putOpts.TableName = helpers.testHashTable putOpts.Item = item - request(opts(putOpts), function(err, res) { + request(opts(putOpts), function (err, res) { if (err) return cb(err) res.statusCode.should.equal(200) res.body.should.eql({}) @@ -804,53 +804,53 @@ describe('putItem', function() { }) }) - it('should return ConditionalCheckFailedException if expecting existing value to not exist if different value specified', function(done) { - var item = {a: {S: helpers.randomString()}, b: {S: helpers.randomString()}} - request(opts({TableName: helpers.testHashTable, Item: item}), function(err, res) { + it('should return ConditionalCheckFailedException if expecting existing value to not exist if different value specified', function (done) { + var item = { a: { S: helpers.randomString() }, b: { S: helpers.randomString() } } + request(opts({ TableName: helpers.testHashTable, Item: item }), function (err, res) { if (err) return done(err) res.statusCode.should.equal(200) async.forEach([ - {Expected: {b: {Exists: false}}}, - {Expected: {b: {ComparisonOperator: 'NULL'}}}, - {ConditionExpression: 'attribute_not_exists(b)'}, - {ConditionExpression: 'attribute_not_exists(#b)', ExpressionAttributeNames: {'#b': 'b'}}, - ], function(putOpts, cb) { + { Expected: { b: { Exists: false } } }, + { Expected: { b: { ComparisonOperator: 'NULL' } } }, + { ConditionExpression: 'attribute_not_exists(b)' }, + { ConditionExpression: 'attribute_not_exists(#b)', ExpressionAttributeNames: { '#b': 'b' } }, + ], function (putOpts, cb) { putOpts.TableName = helpers.testHashTable - putOpts.Item = {a: item.a, b: {S: helpers.randomString()}} + putOpts.Item = { a: item.a, b: { S: helpers.randomString() } } assertConditional(putOpts, cb) }, done) }) }) - it('should return ConditionalCheckFailedException if expecting existing value to not exist if value not specified', function(done) { - var item = {a: {S: helpers.randomString()}, b: {S: helpers.randomString()}} - request(opts({TableName: helpers.testHashTable, Item: item}), function(err, res) { + it('should return ConditionalCheckFailedException if expecting existing value to not exist if value not specified', function (done) { + var item = { a: { S: helpers.randomString() }, b: { S: helpers.randomString() } } + request(opts({ TableName: helpers.testHashTable, Item: item }), function (err, res) { if (err) return done(err) res.statusCode.should.equal(200) async.forEach([ - {Expected: {b: {Exists: false}}}, - {Expected: {b: {ComparisonOperator: 'NULL'}}}, - {ConditionExpression: 'attribute_not_exists(b)'}, - {ConditionExpression: 'attribute_not_exists(#b)', ExpressionAttributeNames: {'#b': 'b'}}, - ], function(putOpts, cb) { + { Expected: { b: { Exists: false } } }, + { Expected: { b: { ComparisonOperator: 'NULL' } } }, + { ConditionExpression: 'attribute_not_exists(b)' }, + { ConditionExpression: 'attribute_not_exists(#b)', ExpressionAttributeNames: { '#b': 'b' } }, + ], function (putOpts, cb) { putOpts.TableName = helpers.testHashTable - putOpts.Item = {a: item.a} + putOpts.Item = { a: item.a } assertConditional(putOpts, cb) }, done) }) }) - it('should return ConditionalCheckFailedException if expecting existing value to not exist if same value specified', function(done) { - var item = {a: {S: helpers.randomString()}, b: {S: helpers.randomString()}} - request(opts({TableName: helpers.testHashTable, Item: item}), function(err, res) { + it('should return ConditionalCheckFailedException if expecting existing value to not exist if same value specified', function (done) { + var item = { a: { S: helpers.randomString() }, b: { S: helpers.randomString() } } + request(opts({ TableName: helpers.testHashTable, Item: item }), function (err, res) { if (err) return done(err) res.statusCode.should.equal(200) async.forEach([ - {Expected: {b: {Exists: false}}}, - {Expected: {b: {ComparisonOperator: 'NULL'}}}, - {ConditionExpression: 'attribute_not_exists(b)'}, - {ConditionExpression: 'attribute_not_exists(#b)', ExpressionAttributeNames: {'#b': 'b'}}, - ], function(putOpts, cb) { + { Expected: { b: { Exists: false } } }, + { Expected: { b: { ComparisonOperator: 'NULL' } } }, + { ConditionExpression: 'attribute_not_exists(b)' }, + { ConditionExpression: 'attribute_not_exists(#b)', ExpressionAttributeNames: { '#b': 'b' } }, + ], function (putOpts, cb) { putOpts.TableName = helpers.testHashTable putOpts.Item = item assertConditional(putOpts, cb) @@ -858,27 +858,27 @@ describe('putItem', function() { }) }) - it('should succeed for multiple conditional checks if all are valid', function(done) { - var item = {a: {S: helpers.randomString()}, c: {S: helpers.randomString()}} - request(opts({TableName: helpers.testHashTable, Item: item}), function(err, res) { + it('should succeed for multiple conditional checks if all are valid', function (done) { + var item = { a: { S: helpers.randomString() }, c: { S: helpers.randomString() } } + request(opts({ TableName: helpers.testHashTable, Item: item }), function (err, res) { if (err) return done(err) res.statusCode.should.equal(200) async.forEach([ - {Expected: {a: {Value: item.a}, b: {Exists: false}, c: {ComparisonOperator: 'GE', Value: item.c}}}, - {Expected: { - a: {ComparisonOperator: 'EQ', AttributeValueList: [item.a]}, - b: {ComparisonOperator: 'NULL'}, - c: {ComparisonOperator: 'GE', AttributeValueList: [item.c]}, - }}, + { Expected: { a: { Value: item.a }, b: { Exists: false }, c: { ComparisonOperator: 'GE', Value: item.c } } }, + { Expected: { + a: { ComparisonOperator: 'EQ', AttributeValueList: [ item.a ] }, + b: { ComparisonOperator: 'NULL' }, + c: { ComparisonOperator: 'GE', AttributeValueList: [ item.c ] }, + } }, { ConditionExpression: 'a = :a AND attribute_not_exists(#b) AND c >= :c', - ExpressionAttributeValues: {':a': item.a, ':c': item.c}, - ExpressionAttributeNames: {'#b': 'b'}, + ExpressionAttributeValues: { ':a': item.a, ':c': item.c }, + ExpressionAttributeNames: { '#b': 'b' }, }, - ], function(putOpts, cb) { + ], function (putOpts, cb) { putOpts.TableName = helpers.testHashTable putOpts.Item = item - request(opts(putOpts), function(err, res) { + request(opts(putOpts), function (err, res) { if (err) return cb(err) res.statusCode.should.equal(200) res.body.should.eql({}) @@ -888,24 +888,24 @@ describe('putItem', function() { }) }) - it('should return ConditionalCheckFailedException for multiple conditional checks if one is invalid', function(done) { - var item = {a: {S: helpers.randomString()}, c: {S: helpers.randomString()}} - request(opts({TableName: helpers.testHashTable, Item: item}), function(err, res) { + it('should return ConditionalCheckFailedException for multiple conditional checks if one is invalid', function (done) { + var item = { a: { S: helpers.randomString() }, c: { S: helpers.randomString() } } + request(opts({ TableName: helpers.testHashTable, Item: item }), function (err, res) { if (err) return done(err) res.statusCode.should.equal(200) async.forEach([ - {Expected: {a: {Value: item.a}, b: {Exists: false}, c: {Value: {S: helpers.randomString()}}}}, - {Expected: { - a: {AttributeValueList: [item.a], ComparisonOperator: 'EQ'}, - b: {ComparisonOperator: 'NULL'}, - c: {AttributeValueList: [{S: helpers.randomString()}], ComparisonOperator: 'EQ'}, - }}, + { Expected: { a: { Value: item.a }, b: { Exists: false }, c: { Value: { S: helpers.randomString() } } } }, + { Expected: { + a: { AttributeValueList: [ item.a ], ComparisonOperator: 'EQ' }, + b: { ComparisonOperator: 'NULL' }, + c: { AttributeValueList: [ { S: helpers.randomString() } ], ComparisonOperator: 'EQ' }, + } }, { ConditionExpression: 'a = :a AND attribute_not_exists(#b) AND c = :c', - ExpressionAttributeValues: {':a': item.a, ':c': {S: helpers.randomString()}}, - ExpressionAttributeNames: {'#b': 'b'}, + ExpressionAttributeValues: { ':a': item.a, ':c': { S: helpers.randomString() } }, + ExpressionAttributeNames: { '#b': 'b' }, }, - ], function(putOpts, cb) { + ], function (putOpts, cb) { putOpts.TableName = helpers.testHashTable putOpts.Item = item assertConditional(putOpts, cb) @@ -913,26 +913,26 @@ describe('putItem', function() { }) }) - it('should succeed for multiple conditional checks if one is invalid and OR is specified', function(done) { - var item = {a: {S: helpers.randomString()}, c: {S: helpers.randomString()}} - request(opts({TableName: helpers.testHashTable, Item: item}), function(err, res) { + it('should succeed for multiple conditional checks if one is invalid and OR is specified', function (done) { + var item = { a: { S: helpers.randomString() }, c: { S: helpers.randomString() } } + request(opts({ TableName: helpers.testHashTable, Item: item }), function (err, res) { if (err) return done(err) res.statusCode.should.equal(200) async.forEach([ - {Expected: { - a: {ComparisonOperator: 'EQ', AttributeValueList: [item.a]}, - b: {ComparisonOperator: 'NULL'}, - c: {ComparisonOperator: 'EQ', AttributeValueList: [{S: helpers.randomString()}]}, - }, ConditionalOperator: 'OR'}, + { Expected: { + a: { ComparisonOperator: 'EQ', AttributeValueList: [ item.a ] }, + b: { ComparisonOperator: 'NULL' }, + c: { ComparisonOperator: 'EQ', AttributeValueList: [ { S: helpers.randomString() } ] }, + }, ConditionalOperator: 'OR' }, { ConditionExpression: 'a = :a OR attribute_not_exists(#b) OR c = :c', - ExpressionAttributeValues: {':a': item.a, ':c': {S: helpers.randomString()}}, - ExpressionAttributeNames: {'#b': 'b'}, + ExpressionAttributeValues: { ':a': item.a, ':c': { S: helpers.randomString() } }, + ExpressionAttributeNames: { '#b': 'b' }, }, - ], function(putOpts, cb) { + ], function (putOpts, cb) { putOpts.TableName = helpers.testHashTable putOpts.Item = item - request(opts(putOpts), function(err, res) { + request(opts(putOpts), function (err, res) { if (err) return cb(err) res.statusCode.should.equal(200) res.body.should.eql({}) @@ -942,26 +942,26 @@ describe('putItem', function() { }) }) - it('should succeed if condition is valid: NE', function(done) { - var item = {a: {S: helpers.randomString()}} - request(opts({TableName: helpers.testHashTable, Item: item}), function(err, res) { + it('should succeed if condition is valid: NE', function (done) { + var item = { a: { S: helpers.randomString() } } + request(opts({ TableName: helpers.testHashTable, Item: item }), function (err, res) { if (err) return done(err) res.statusCode.should.equal(200) async.forEach([ - {Expected: {a: {ComparisonOperator: 'NE', AttributeValueList: [{S: helpers.randomString()}]}}}, + { Expected: { a: { ComparisonOperator: 'NE', AttributeValueList: [ { S: helpers.randomString() } ] } } }, { ConditionExpression: 'a <> :a', - ExpressionAttributeValues: {':a': {S: helpers.randomString()}}, + ExpressionAttributeValues: { ':a': { S: helpers.randomString() } }, }, { ConditionExpression: '#a <> :a', - ExpressionAttributeValues: {':a': {S: helpers.randomString()}}, - ExpressionAttributeNames: {'#a': 'a'}, + ExpressionAttributeValues: { ':a': { S: helpers.randomString() } }, + ExpressionAttributeNames: { '#a': 'a' }, }, - ], function(putOpts, cb) { + ], function (putOpts, cb) { putOpts.TableName = helpers.testHashTable putOpts.Item = item - request(opts(putOpts), function(err, res) { + request(opts(putOpts), function (err, res) { if (err) return cb(err) res.statusCode.should.equal(200) res.body.should.eql({}) @@ -971,23 +971,23 @@ describe('putItem', function() { }) }) - it('should fail if condition is invalid: NE', function(done) { - var item = {a: {S: helpers.randomString()}} - request(opts({TableName: helpers.testHashTable, Item: item}), function(err, res) { + it('should fail if condition is invalid: NE', function (done) { + var item = { a: { S: helpers.randomString() } } + request(opts({ TableName: helpers.testHashTable, Item: item }), function (err, res) { if (err) return done(err) res.statusCode.should.equal(200) async.forEach([ - {Expected: {a: {ComparisonOperator: 'NE', AttributeValueList: [item.a]}}}, + { Expected: { a: { ComparisonOperator: 'NE', AttributeValueList: [ item.a ] } } }, { ConditionExpression: 'a <> :a', - ExpressionAttributeValues: {':a': item.a}, + ExpressionAttributeValues: { ':a': item.a }, }, { ConditionExpression: '#a <> :a', - ExpressionAttributeValues: {':a': item.a}, - ExpressionAttributeNames: {'#a': 'a'}, + ExpressionAttributeValues: { ':a': item.a }, + ExpressionAttributeNames: { '#a': 'a' }, }, - ], function(putOpts, cb) { + ], function (putOpts, cb) { putOpts.TableName = helpers.testHashTable putOpts.Item = item assertConditional(putOpts, cb) @@ -995,26 +995,26 @@ describe('putItem', function() { }) }) - it('should succeed if condition is valid: LE', function(done) { - var item = {a: {S: 'b'}} - request(opts({TableName: helpers.testHashTable, Item: item}), function(err, res) { + it('should succeed if condition is valid: LE', function (done) { + var item = { a: { S: 'b' } } + request(opts({ TableName: helpers.testHashTable, Item: item }), function (err, res) { if (err) return done(err) res.statusCode.should.equal(200) async.forEach([ - {Expected: {a: {ComparisonOperator: 'LE', AttributeValueList: [{S: 'c'}]}}}, + { Expected: { a: { ComparisonOperator: 'LE', AttributeValueList: [ { S: 'c' } ] } } }, { ConditionExpression: 'a <= :a', - ExpressionAttributeValues: {':a': {S: 'c'}}, + ExpressionAttributeValues: { ':a': { S: 'c' } }, }, { ConditionExpression: '#a <= :a', - ExpressionAttributeValues: {':a': {S: 'c'}}, - ExpressionAttributeNames: {'#a': 'a'}, + ExpressionAttributeValues: { ':a': { S: 'c' } }, + ExpressionAttributeNames: { '#a': 'a' }, }, - ], function(putOpts, cb) { + ], function (putOpts, cb) { putOpts.TableName = helpers.testHashTable putOpts.Item = item - request(opts(putOpts), function(err, res) { + request(opts(putOpts), function (err, res) { if (err) return cb(err) res.statusCode.should.equal(200) res.body.should.eql({}) @@ -1024,23 +1024,23 @@ describe('putItem', function() { }) }) - it('should fail if condition is invalid: LE', function(done) { - var item = {a: {S: 'd'}} - request(opts({TableName: helpers.testHashTable, Item: item}), function(err, res) { + it('should fail if condition is invalid: LE', function (done) { + var item = { a: { S: 'd' } } + request(opts({ TableName: helpers.testHashTable, Item: item }), function (err, res) { if (err) return done(err) res.statusCode.should.equal(200) async.forEach([ - {Expected: {a: {ComparisonOperator: 'LE', AttributeValueList: [{S: 'c'}]}}}, + { Expected: { a: { ComparisonOperator: 'LE', AttributeValueList: [ { S: 'c' } ] } } }, { ConditionExpression: 'a <= :a', - ExpressionAttributeValues: {':a': {S: 'c'}}, + ExpressionAttributeValues: { ':a': { S: 'c' } }, }, { ConditionExpression: '#a <= :a', - ExpressionAttributeValues: {':a': {S: 'c'}}, - ExpressionAttributeNames: {'#a': 'a'}, + ExpressionAttributeValues: { ':a': { S: 'c' } }, + ExpressionAttributeNames: { '#a': 'a' }, }, - ], function(putOpts, cb) { + ], function (putOpts, cb) { putOpts.TableName = helpers.testHashTable putOpts.Item = item assertConditional(putOpts, cb) @@ -1048,26 +1048,26 @@ describe('putItem', function() { }) }) - it('should succeed if condition is valid: LT', function(done) { - var item = {a: {S: 'b'}} - request(opts({TableName: helpers.testHashTable, Item: item}), function(err, res) { + it('should succeed if condition is valid: LT', function (done) { + var item = { a: { S: 'b' } } + request(opts({ TableName: helpers.testHashTable, Item: item }), function (err, res) { if (err) return done(err) res.statusCode.should.equal(200) async.forEach([ - {Expected: {a: {ComparisonOperator: 'LT', AttributeValueList: [{S: 'c'}]}}}, + { Expected: { a: { ComparisonOperator: 'LT', AttributeValueList: [ { S: 'c' } ] } } }, { ConditionExpression: 'a < :a', - ExpressionAttributeValues: {':a': {S: 'c'}}, + ExpressionAttributeValues: { ':a': { S: 'c' } }, }, { ConditionExpression: '#a < :a', - ExpressionAttributeValues: {':a': {S: 'c'}}, - ExpressionAttributeNames: {'#a': 'a'}, + ExpressionAttributeValues: { ':a': { S: 'c' } }, + ExpressionAttributeNames: { '#a': 'a' }, }, - ], function(putOpts, cb) { + ], function (putOpts, cb) { putOpts.TableName = helpers.testHashTable putOpts.Item = item - request(opts(putOpts), function(err, res) { + request(opts(putOpts), function (err, res) { if (err) return cb(err) res.statusCode.should.equal(200) res.body.should.eql({}) @@ -1077,23 +1077,23 @@ describe('putItem', function() { }) }) - it('should fail if condition is invalid: LT', function(done) { - var item = {a: {S: 'd'}} - request(opts({TableName: helpers.testHashTable, Item: item}), function(err, res) { + it('should fail if condition is invalid: LT', function (done) { + var item = { a: { S: 'd' } } + request(opts({ TableName: helpers.testHashTable, Item: item }), function (err, res) { if (err) return done(err) res.statusCode.should.equal(200) async.forEach([ - {Expected: {a: {ComparisonOperator: 'LT', AttributeValueList: [{S: 'c'}]}}}, + { Expected: { a: { ComparisonOperator: 'LT', AttributeValueList: [ { S: 'c' } ] } } }, { ConditionExpression: 'a < :a', - ExpressionAttributeValues: {':a': {S: 'c'}}, + ExpressionAttributeValues: { ':a': { S: 'c' } }, }, { ConditionExpression: '#a < :a', - ExpressionAttributeValues: {':a': {S: 'c'}}, - ExpressionAttributeNames: {'#a': 'a'}, + ExpressionAttributeValues: { ':a': { S: 'c' } }, + ExpressionAttributeNames: { '#a': 'a' }, }, - ], function(putOpts, cb) { + ], function (putOpts, cb) { putOpts.TableName = helpers.testHashTable putOpts.Item = item assertConditional(putOpts, cb) @@ -1101,26 +1101,26 @@ describe('putItem', function() { }) }) - it('should succeed if condition is valid: GE', function(done) { - var item = {a: {S: 'b'}} - request(opts({TableName: helpers.testHashTable, Item: item}), function(err, res) { + it('should succeed if condition is valid: GE', function (done) { + var item = { a: { S: 'b' } } + request(opts({ TableName: helpers.testHashTable, Item: item }), function (err, res) { if (err) return done(err) res.statusCode.should.equal(200) async.forEach([ - {Expected: {a: {ComparisonOperator: 'GE', AttributeValueList: [{S: 'a'}]}}}, + { Expected: { a: { ComparisonOperator: 'GE', AttributeValueList: [ { S: 'a' } ] } } }, { ConditionExpression: 'a >= :a', - ExpressionAttributeValues: {':a': {S: 'a'}}, + ExpressionAttributeValues: { ':a': { S: 'a' } }, }, { ConditionExpression: '#a >= :a', - ExpressionAttributeValues: {':a': {S: 'a'}}, - ExpressionAttributeNames: {'#a': 'a'}, + ExpressionAttributeValues: { ':a': { S: 'a' } }, + ExpressionAttributeNames: { '#a': 'a' }, }, - ], function(putOpts, cb) { + ], function (putOpts, cb) { putOpts.TableName = helpers.testHashTable putOpts.Item = item - request(opts(putOpts), function(err, res) { + request(opts(putOpts), function (err, res) { if (err) return cb(err) res.statusCode.should.equal(200) res.body.should.eql({}) @@ -1130,23 +1130,23 @@ describe('putItem', function() { }) }) - it('should fail if condition is invalid: GE', function(done) { - var item = {a: {S: 'b'}} - request(opts({TableName: helpers.testHashTable, Item: item}), function(err, res) { + it('should fail if condition is invalid: GE', function (done) { + var item = { a: { S: 'b' } } + request(opts({ TableName: helpers.testHashTable, Item: item }), function (err, res) { if (err) return done(err) res.statusCode.should.equal(200) async.forEach([ - {Expected: {a: {ComparisonOperator: 'GE', AttributeValueList: [{S: 'c'}]}}}, + { Expected: { a: { ComparisonOperator: 'GE', AttributeValueList: [ { S: 'c' } ] } } }, { ConditionExpression: 'a >= :a', - ExpressionAttributeValues: {':a': {S: 'c'}}, + ExpressionAttributeValues: { ':a': { S: 'c' } }, }, { ConditionExpression: '#a >= :a', - ExpressionAttributeValues: {':a': {S: 'c'}}, - ExpressionAttributeNames: {'#a': 'a'}, + ExpressionAttributeValues: { ':a': { S: 'c' } }, + ExpressionAttributeNames: { '#a': 'a' }, }, - ], function(putOpts, cb) { + ], function (putOpts, cb) { putOpts.TableName = helpers.testHashTable putOpts.Item = item assertConditional(putOpts, cb) @@ -1154,26 +1154,26 @@ describe('putItem', function() { }) }) - it('should succeed if condition is valid: GT', function(done) { - var item = {a: {S: 'b'}} - request(opts({TableName: helpers.testHashTable, Item: item}), function(err, res) { + it('should succeed if condition is valid: GT', function (done) { + var item = { a: { S: 'b' } } + request(opts({ TableName: helpers.testHashTable, Item: item }), function (err, res) { if (err) return done(err) res.statusCode.should.equal(200) async.forEach([ - {Expected: {a: {ComparisonOperator: 'GT', AttributeValueList: [{S: 'a'}]}}}, + { Expected: { a: { ComparisonOperator: 'GT', AttributeValueList: [ { S: 'a' } ] } } }, { ConditionExpression: 'a > :a', - ExpressionAttributeValues: {':a': {S: 'a'}}, + ExpressionAttributeValues: { ':a': { S: 'a' } }, }, { ConditionExpression: '#a > :a', - ExpressionAttributeValues: {':a': {S: 'a'}}, - ExpressionAttributeNames: {'#a': 'a'}, + ExpressionAttributeValues: { ':a': { S: 'a' } }, + ExpressionAttributeNames: { '#a': 'a' }, }, - ], function(putOpts, cb) { + ], function (putOpts, cb) { putOpts.TableName = helpers.testHashTable putOpts.Item = item - request(opts(putOpts), function(err, res) { + request(opts(putOpts), function (err, res) { if (err) return cb(err) res.statusCode.should.equal(200) res.body.should.eql({}) @@ -1183,23 +1183,23 @@ describe('putItem', function() { }) }) - it('should fail if condition is invalid: GT', function(done) { - var item = {a: {S: 'a'}} - request(opts({TableName: helpers.testHashTable, Item: item}), function(err, res) { + it('should fail if condition is invalid: GT', function (done) { + var item = { a: { S: 'a' } } + request(opts({ TableName: helpers.testHashTable, Item: item }), function (err, res) { if (err) return done(err) res.statusCode.should.equal(200) async.forEach([ - {Expected: {a: {ComparisonOperator: 'GT', AttributeValueList: [{S: 'c'}]}}}, + { Expected: { a: { ComparisonOperator: 'GT', AttributeValueList: [ { S: 'c' } ] } } }, { ConditionExpression: 'a > :a', - ExpressionAttributeValues: {':a': {S: 'c'}}, + ExpressionAttributeValues: { ':a': { S: 'c' } }, }, { ConditionExpression: '#a > :a', - ExpressionAttributeValues: {':a': {S: 'c'}}, - ExpressionAttributeNames: {'#a': 'a'}, + ExpressionAttributeValues: { ':a': { S: 'c' } }, + ExpressionAttributeNames: { '#a': 'a' }, }, - ], function(putOpts, cb) { + ], function (putOpts, cb) { putOpts.TableName = helpers.testHashTable putOpts.Item = item assertConditional(putOpts, cb) @@ -1207,26 +1207,26 @@ describe('putItem', function() { }) }) - it('should succeed if condition is valid: CONTAINS', function(done) { - var item = {a: {S: 'hello'}} - request(opts({TableName: helpers.testHashTable, Item: item}), function(err, res) { + it('should succeed if condition is valid: CONTAINS', function (done) { + var item = { a: { S: 'hello' } } + request(opts({ TableName: helpers.testHashTable, Item: item }), function (err, res) { if (err) return done(err) res.statusCode.should.equal(200) async.forEach([ - {Expected: {a: {ComparisonOperator: 'CONTAINS', AttributeValueList: [{S: 'ell'}]}}}, + { Expected: { a: { ComparisonOperator: 'CONTAINS', AttributeValueList: [ { S: 'ell' } ] } } }, { ConditionExpression: 'contains(a, :a)', - ExpressionAttributeValues: {':a': {S: 'ell'}}, + ExpressionAttributeValues: { ':a': { S: 'ell' } }, }, { ConditionExpression: 'contains(#a, :a)', - ExpressionAttributeValues: {':a': {S: 'ell'}}, - ExpressionAttributeNames: {'#a': 'a'}, + ExpressionAttributeValues: { ':a': { S: 'ell' } }, + ExpressionAttributeNames: { '#a': 'a' }, }, - ], function(putOpts, cb) { + ], function (putOpts, cb) { putOpts.TableName = helpers.testHashTable putOpts.Item = item - request(opts(putOpts), function(err, res) { + request(opts(putOpts), function (err, res) { if (err) return cb(err) res.statusCode.should.equal(200) res.body.should.eql({}) @@ -1236,23 +1236,23 @@ describe('putItem', function() { }) }) - it('should fail if condition is invalid: CONTAINS', function(done) { - var item = {a: {S: 'hello'}} - request(opts({TableName: helpers.testHashTable, Item: item}), function(err, res) { + it('should fail if condition is invalid: CONTAINS', function (done) { + var item = { a: { S: 'hello' } } + request(opts({ TableName: helpers.testHashTable, Item: item }), function (err, res) { if (err) return done(err) res.statusCode.should.equal(200) async.forEach([ - {Expected: {a: {ComparisonOperator: 'CONTAINS', AttributeValueList: [{S: 'goodbye'}]}}}, + { Expected: { a: { ComparisonOperator: 'CONTAINS', AttributeValueList: [ { S: 'goodbye' } ] } } }, { ConditionExpression: 'contains(a, :a)', - ExpressionAttributeValues: {':a': {S: 'goodbye'}}, + ExpressionAttributeValues: { ':a': { S: 'goodbye' } }, }, { ConditionExpression: 'contains(#a, :a)', - ExpressionAttributeValues: {':a': {S: 'goodbye'}}, - ExpressionAttributeNames: {'#a': 'a'}, + ExpressionAttributeValues: { ':a': { S: 'goodbye' } }, + ExpressionAttributeNames: { '#a': 'a' }, }, - ], function(putOpts, cb) { + ], function (putOpts, cb) { putOpts.TableName = helpers.testHashTable putOpts.Item = item assertConditional(putOpts, cb) @@ -1260,26 +1260,26 @@ describe('putItem', function() { }) }) - it('should succeed if condition is valid: BEGINS_WITH', function(done) { - var item = {a: {S: 'hello'}} - request(opts({TableName: helpers.testHashTable, Item: item}), function(err, res) { + it('should succeed if condition is valid: BEGINS_WITH', function (done) { + var item = { a: { S: 'hello' } } + request(opts({ TableName: helpers.testHashTable, Item: item }), function (err, res) { if (err) return done(err) res.statusCode.should.equal(200) async.forEach([ - {Expected: {a: {ComparisonOperator: 'BEGINS_WITH', AttributeValueList: [{S: 'he'}]}}}, + { Expected: { a: { ComparisonOperator: 'BEGINS_WITH', AttributeValueList: [ { S: 'he' } ] } } }, { ConditionExpression: 'begins_with(a, :a)', - ExpressionAttributeValues: {':a': {S: 'he'}}, + ExpressionAttributeValues: { ':a': { S: 'he' } }, }, { ConditionExpression: 'begins_with(#a, :a)', - ExpressionAttributeValues: {':a': {S: 'he'}}, - ExpressionAttributeNames: {'#a': 'a'}, + ExpressionAttributeValues: { ':a': { S: 'he' } }, + ExpressionAttributeNames: { '#a': 'a' }, }, - ], function(putOpts, cb) { + ], function (putOpts, cb) { putOpts.TableName = helpers.testHashTable putOpts.Item = item - request(opts(putOpts), function(err, res) { + request(opts(putOpts), function (err, res) { if (err) return cb(err) res.statusCode.should.equal(200) res.body.should.eql({}) @@ -1289,23 +1289,23 @@ describe('putItem', function() { }) }) - it('should fail if condition is invalid: BEGINS_WITH', function(done) { - var item = {a: {S: 'hello'}} - request(opts({TableName: helpers.testHashTable, Item: item}), function(err, res) { + it('should fail if condition is invalid: BEGINS_WITH', function (done) { + var item = { a: { S: 'hello' } } + request(opts({ TableName: helpers.testHashTable, Item: item }), function (err, res) { if (err) return done(err) res.statusCode.should.equal(200) async.forEach([ - {Expected: {a: {ComparisonOperator: 'BEGINS_WITH', AttributeValueList: [{S: 'goodbye'}]}}}, + { Expected: { a: { ComparisonOperator: 'BEGINS_WITH', AttributeValueList: [ { S: 'goodbye' } ] } } }, { ConditionExpression: 'begins_with(a, :a)', - ExpressionAttributeValues: {':a': {S: 'goodbye'}}, + ExpressionAttributeValues: { ':a': { S: 'goodbye' } }, }, { ConditionExpression: 'begins_with(#a, :a)', - ExpressionAttributeValues: {':a': {S: 'goodbye'}}, - ExpressionAttributeNames: {'#a': 'a'}, + ExpressionAttributeValues: { ':a': { S: 'goodbye' } }, + ExpressionAttributeNames: { '#a': 'a' }, }, - ], function(putOpts, cb) { + ], function (putOpts, cb) { putOpts.TableName = helpers.testHashTable putOpts.Item = item assertConditional(putOpts, cb) @@ -1313,26 +1313,26 @@ describe('putItem', function() { }) }) - it('should succeed if condition is valid: NOT_CONTAINS', function(done) { - var item = {a: {S: 'hello'}} - request(opts({TableName: helpers.testHashTable, Item: item}), function(err, res) { + it('should succeed if condition is valid: NOT_CONTAINS', function (done) { + var item = { a: { S: 'hello' } } + request(opts({ TableName: helpers.testHashTable, Item: item }), function (err, res) { if (err) return done(err) res.statusCode.should.equal(200) async.forEach([ - {Expected: {a: {ComparisonOperator: 'NOT_CONTAINS', AttributeValueList: [{S: 'goodbye'}]}}}, + { Expected: { a: { ComparisonOperator: 'NOT_CONTAINS', AttributeValueList: [ { S: 'goodbye' } ] } } }, { ConditionExpression: 'not contains(a, :a)', - ExpressionAttributeValues: {':a': {S: 'goodbye'}}, + ExpressionAttributeValues: { ':a': { S: 'goodbye' } }, }, { ConditionExpression: 'not contains(#a, :a)', - ExpressionAttributeValues: {':a': {S: 'goodbye'}}, - ExpressionAttributeNames: {'#a': 'a'}, + ExpressionAttributeValues: { ':a': { S: 'goodbye' } }, + ExpressionAttributeNames: { '#a': 'a' }, }, - ], function(putOpts, cb) { + ], function (putOpts, cb) { putOpts.TableName = helpers.testHashTable putOpts.Item = item - request(opts(putOpts), function(err, res) { + request(opts(putOpts), function (err, res) { if (err) return cb(err) res.statusCode.should.equal(200) res.body.should.eql({}) @@ -1342,23 +1342,23 @@ describe('putItem', function() { }) }) - it('should fail if condition is invalid: NOT_CONTAINS', function(done) { - var item = {a: {S: 'hello'}} - request(opts({TableName: helpers.testHashTable, Item: item}), function(err, res) { + it('should fail if condition is invalid: NOT_CONTAINS', function (done) { + var item = { a: { S: 'hello' } } + request(opts({ TableName: helpers.testHashTable, Item: item }), function (err, res) { if (err) return done(err) res.statusCode.should.equal(200) async.forEach([ - {Expected: {a: {ComparisonOperator: 'NOT_CONTAINS', AttributeValueList: [{S: 'ell'}]}}}, + { Expected: { a: { ComparisonOperator: 'NOT_CONTAINS', AttributeValueList: [ { S: 'ell' } ] } } }, { ConditionExpression: 'not contains(a, :a)', - ExpressionAttributeValues: {':a': {S: 'ell'}}, + ExpressionAttributeValues: { ':a': { S: 'ell' } }, }, { ConditionExpression: 'not contains(#a, :a)', - ExpressionAttributeValues: {':a': {S: 'ell'}}, - ExpressionAttributeNames: {'#a': 'a'}, + ExpressionAttributeValues: { ':a': { S: 'ell' } }, + ExpressionAttributeNames: { '#a': 'a' }, }, - ], function(putOpts, cb) { + ], function (putOpts, cb) { putOpts.TableName = helpers.testHashTable putOpts.Item = item assertConditional(putOpts, cb) @@ -1366,26 +1366,26 @@ describe('putItem', function() { }) }) - it('should succeed if condition is valid: IN', function(done) { - var item = {a: {S: 'b'}} - request(opts({TableName: helpers.testHashTable, Item: item}), function(err, res) { + it('should succeed if condition is valid: IN', function (done) { + var item = { a: { S: 'b' } } + request(opts({ TableName: helpers.testHashTable, Item: item }), function (err, res) { if (err) return done(err) res.statusCode.should.equal(200) async.forEach([ - {Expected: {a: {ComparisonOperator: 'IN', AttributeValueList: [{S: 'c'}, {S: 'b'}]}}}, + { Expected: { a: { ComparisonOperator: 'IN', AttributeValueList: [ { S: 'c' }, { S: 'b' } ] } } }, { ConditionExpression: 'a in (:a, :b)', - ExpressionAttributeValues: {':a': {S: 'c'}, ':b': {S: 'b'}}, + ExpressionAttributeValues: { ':a': { S: 'c' }, ':b': { S: 'b' } }, }, { ConditionExpression: '#a in (:a, :b)', - ExpressionAttributeValues: {':a': {S: 'c'}, ':b': {S: 'b'}}, - ExpressionAttributeNames: {'#a': 'a'}, + ExpressionAttributeValues: { ':a': { S: 'c' }, ':b': { S: 'b' } }, + ExpressionAttributeNames: { '#a': 'a' }, }, - ], function(putOpts, cb) { + ], function (putOpts, cb) { putOpts.TableName = helpers.testHashTable putOpts.Item = item - request(opts(putOpts), function(err, res) { + request(opts(putOpts), function (err, res) { if (err) return cb(err) res.statusCode.should.equal(200) res.body.should.eql({}) @@ -1395,23 +1395,23 @@ describe('putItem', function() { }) }) - it('should fail if condition is invalid: IN', function(done) { - var item = {a: {S: 'd'}} - request(opts({TableName: helpers.testHashTable, Item: item}), function(err, res) { + it('should fail if condition is invalid: IN', function (done) { + var item = { a: { S: 'd' } } + request(opts({ TableName: helpers.testHashTable, Item: item }), function (err, res) { if (err) return done(err) res.statusCode.should.equal(200) async.forEach([ - {Expected: {a: {ComparisonOperator: 'IN', AttributeValueList: [{S: 'c'}]}}}, + { Expected: { a: { ComparisonOperator: 'IN', AttributeValueList: [ { S: 'c' } ] } } }, { ConditionExpression: 'a in (:a)', - ExpressionAttributeValues: {':a': {S: 'c'}}, + ExpressionAttributeValues: { ':a': { S: 'c' } }, }, { ConditionExpression: '#a in (:a)', - ExpressionAttributeValues: {':a': {S: 'c'}}, - ExpressionAttributeNames: {'#a': 'a'}, + ExpressionAttributeValues: { ':a': { S: 'c' } }, + ExpressionAttributeNames: { '#a': 'a' }, }, - ], function(putOpts, cb) { + ], function (putOpts, cb) { putOpts.TableName = helpers.testHashTable putOpts.Item = item assertConditional(putOpts, cb) @@ -1419,26 +1419,26 @@ describe('putItem', function() { }) }) - it('should succeed if condition is valid: BETWEEN', function(done) { - var item = {a: {S: 'b'}} - request(opts({TableName: helpers.testHashTable, Item: item}), function(err, res) { + it('should succeed if condition is valid: BETWEEN', function (done) { + var item = { a: { S: 'b' } } + request(opts({ TableName: helpers.testHashTable, Item: item }), function (err, res) { if (err) return done(err) res.statusCode.should.equal(200) async.forEach([ - {Expected: {a: {ComparisonOperator: 'BETWEEN', AttributeValueList: [{S: 'a'}, {S: 'c'}]}}}, + { Expected: { a: { ComparisonOperator: 'BETWEEN', AttributeValueList: [ { S: 'a' }, { S: 'c' } ] } } }, { ConditionExpression: 'a between :a and :b', - ExpressionAttributeValues: {':a': {S: 'a'}, ':b': {S: 'c'}}, + ExpressionAttributeValues: { ':a': { S: 'a' }, ':b': { S: 'c' } }, }, { ConditionExpression: '#a between :a and :b', - ExpressionAttributeValues: {':a': {S: 'a'}, ':b': {S: 'c'}}, - ExpressionAttributeNames: {'#a': 'a'}, + ExpressionAttributeValues: { ':a': { S: 'a' }, ':b': { S: 'c' } }, + ExpressionAttributeNames: { '#a': 'a' }, }, - ], function(putOpts, cb) { + ], function (putOpts, cb) { putOpts.TableName = helpers.testHashTable putOpts.Item = item - request(opts(putOpts), function(err, res) { + request(opts(putOpts), function (err, res) { if (err) return cb(err) res.statusCode.should.equal(200) res.body.should.eql({}) @@ -1448,23 +1448,23 @@ describe('putItem', function() { }) }) - it('should fail if condition is invalid: BETWEEN', function(done) { - var item = {a: {S: 'b'}} - request(opts({TableName: helpers.testHashTable, Item: item}), function(err, res) { + it('should fail if condition is invalid: BETWEEN', function (done) { + var item = { a: { S: 'b' } } + request(opts({ TableName: helpers.testHashTable, Item: item }), function (err, res) { if (err) return done(err) res.statusCode.should.equal(200) async.forEach([ - {Expected: {a: {ComparisonOperator: 'BETWEEN', AttributeValueList: [{S: 'c'}, {S: 'd'}]}}}, + { Expected: { a: { ComparisonOperator: 'BETWEEN', AttributeValueList: [ { S: 'c' }, { S: 'd' } ] } } }, { ConditionExpression: 'a between :a and :b', - ExpressionAttributeValues: {':a': {S: 'c'}, ':b': {S: 'd'}}, + ExpressionAttributeValues: { ':a': { S: 'c' }, ':b': { S: 'd' } }, }, { ConditionExpression: '#a between :a and :b', - ExpressionAttributeValues: {':a': {S: 'c'}, ':b': {S: 'd'}}, - ExpressionAttributeNames: {'#a': 'a'}, + ExpressionAttributeValues: { ':a': { S: 'c' }, ':b': { S: 'd' } }, + ExpressionAttributeNames: { '#a': 'a' }, }, - ], function(putOpts, cb) { + ], function (putOpts, cb) { putOpts.TableName = helpers.testHashTable putOpts.Item = item assertConditional(putOpts, cb) @@ -1472,46 +1472,46 @@ describe('putItem', function() { }) }) - it('should return ConsumedCapacity for small item', function(done) { + it('should return ConsumedCapacity for small item', function (done) { var a = helpers.randomString(), b = new Array(1010 - a.length).join('b'), - item = {a: {S: a}, b: {S: b}, c: {N: '12.3456'}, d: {B: 'AQI='}, e: {BS: ['AQI=', 'Ag==', 'AQ==']}}, - req = {TableName: helpers.testHashTable, Item: item, ReturnConsumedCapacity: 'TOTAL'} - request(opts(req), function(err, res) { + item = { a: { S: a }, b: { S: b }, c: { N: '12.3456' }, d: { B: 'AQI=' }, e: { BS: [ 'AQI=', 'Ag==', 'AQ==' ] } }, + req = { TableName: helpers.testHashTable, Item: item, ReturnConsumedCapacity: 'TOTAL' } + request(opts(req), function (err, res) { if (err) return done(err) res.statusCode.should.equal(200) - res.body.should.eql({ConsumedCapacity: {CapacityUnits: 1, TableName: helpers.testHashTable}}) + res.body.should.eql({ ConsumedCapacity: { CapacityUnits: 1, TableName: helpers.testHashTable } }) req.ReturnConsumedCapacity = 'INDEXES' - request(opts(req), function(err, res) { + request(opts(req), function (err, res) { if (err) return done(err) res.statusCode.should.equal(200) - res.body.should.eql({ConsumedCapacity: {CapacityUnits: 1, Table: {CapacityUnits: 1}, TableName: helpers.testHashTable}}) + res.body.should.eql({ ConsumedCapacity: { CapacityUnits: 1, Table: { CapacityUnits: 1 }, TableName: helpers.testHashTable } }) done() }) }) }) - it('should return ConsumedCapacity for larger item', function(done) { + it('should return ConsumedCapacity for larger item', function (done) { var a = helpers.randomString(), b = new Array(1012 - a.length).join('b'), - item = {a: {S: a}, b: {S: b}, c: {N: '12.3456'}, d: {B: 'AQI='}, e: {BS: ['AQI=', 'Ag==']}}, - req = {TableName: helpers.testHashTable, Item: item, ReturnConsumedCapacity: 'TOTAL'} - request(opts(req), function(err, res) { + item = { a: { S: a }, b: { S: b }, c: { N: '12.3456' }, d: { B: 'AQI=' }, e: { BS: [ 'AQI=', 'Ag==' ] } }, + req = { TableName: helpers.testHashTable, Item: item, ReturnConsumedCapacity: 'TOTAL' } + request(opts(req), function (err, res) { if (err) return done(err) res.statusCode.should.equal(200) - res.body.should.eql({ConsumedCapacity: {CapacityUnits: 2, TableName: helpers.testHashTable}}) + res.body.should.eql({ ConsumedCapacity: { CapacityUnits: 2, TableName: helpers.testHashTable } }) req.ReturnConsumedCapacity = 'INDEXES' - request(opts(req), function(err, res) { + request(opts(req), function (err, res) { if (err) return done(err) res.statusCode.should.equal(200) - res.body.should.eql({ConsumedCapacity: {CapacityUnits: 2, Table: {CapacityUnits: 2}, TableName: helpers.testHashTable}}) - req.Item = {a: item.a} - request(opts(req), function(err, res) { + res.body.should.eql({ ConsumedCapacity: { CapacityUnits: 2, Table: { CapacityUnits: 2 }, TableName: helpers.testHashTable } }) + req.Item = { a: item.a } + request(opts(req), function (err, res) { if (err) return done(err) res.statusCode.should.equal(200) - res.body.should.eql({ConsumedCapacity: {CapacityUnits: 2, Table: {CapacityUnits: 2}, TableName: helpers.testHashTable}}) - request(opts(req), function(err, res) { + res.body.should.eql({ ConsumedCapacity: { CapacityUnits: 2, Table: { CapacityUnits: 2 }, TableName: helpers.testHashTable } }) + request(opts(req), function (err, res) { if (err) return done(err) res.statusCode.should.equal(200) - res.body.should.eql({ConsumedCapacity: {CapacityUnits: 1, Table: {CapacityUnits: 1}, TableName: helpers.testHashTable}}) + res.body.should.eql({ ConsumedCapacity: { CapacityUnits: 1, Table: { CapacityUnits: 1 }, TableName: helpers.testHashTable } }) done() }) }) diff --git a/test/query.js b/test/query.js index 5678e9a..59c6b15 100644 --- a/test/query.js +++ b/test/query.js @@ -1,148 +1,148 @@ var helpers = require('./helpers'), - should = require('should'), - async = require('async') + should = require('should'), + async = require('async') var target = 'Query', - request = helpers.request, - opts = helpers.opts.bind(null, target), - assertType = helpers.assertType.bind(null, target), - assertValidation = helpers.assertValidation.bind(null, target), - assertNotFound = helpers.assertNotFound.bind(null, target), - runSlowTests = helpers.runSlowTests + request = helpers.request, + opts = helpers.opts.bind(null, target), + assertType = helpers.assertType.bind(null, target), + assertValidation = helpers.assertValidation.bind(null, target), + assertNotFound = helpers.assertNotFound.bind(null, target), + runSlowTests = helpers.runSlowTests -describe('query', function() { +describe('query', function () { - describe('serializations', function() { + describe('serializations', function () { - it('should return SerializationException when TableName is not a string', function(done) { + it('should return SerializationException when TableName is not a string', function (done) { assertType('TableName', 'String', done) }) - it('should return SerializationException when ExclusiveStartKey is not a map', function(done) { + it('should return SerializationException when ExclusiveStartKey is not a map', function (done) { assertType('ExclusiveStartKey', 'Map', done) }) - it('should return SerializationException when ExclusiveStartKey.Attr is not an attr struct', function(done) { + it('should return SerializationException when ExclusiveStartKey.Attr is not an attr struct', function (done) { this.timeout(60000) assertType('ExclusiveStartKey.Attr', 'AttrStruct', done) }) - it('should return SerializationException when AttributesToGet is not a list', function(done) { + it('should return SerializationException when AttributesToGet is not a list', function (done) { assertType('AttributesToGet', 'List', done) }) - it('should return SerializationException when ConsistentRead is not a boolean', function(done) { + it('should return SerializationException when ConsistentRead is not a boolean', function (done) { assertType('ConsistentRead', 'Boolean', done) }) - it('should return SerializationException when ReturnConsumedCapacity is not a string', function(done) { + it('should return SerializationException when ReturnConsumedCapacity is not a string', function (done) { assertType('ReturnConsumedCapacity', 'String', done) }) - it('should return SerializationException when QueryFilter is not a map', function(done) { + it('should return SerializationException when QueryFilter is not a map', function (done) { assertType('QueryFilter', 'Map', done) }) - it('should return SerializationException when QueryFilter.Attr is not a struct', function(done) { + it('should return SerializationException when QueryFilter.Attr is not a struct', function (done) { assertType('QueryFilter.Attr', 'ValueStruct', done) }) - it('should return SerializationException when QueryFilter.Attr.ComparisonOperator is not a string', function(done) { + it('should return SerializationException when QueryFilter.Attr.ComparisonOperator is not a string', function (done) { assertType('QueryFilter.Attr.ComparisonOperator', 'String', done) }) - it('should return SerializationException when QueryFilter.Attr.AttributeValueList is not a list', function(done) { + it('should return SerializationException when QueryFilter.Attr.AttributeValueList is not a list', function (done) { assertType('QueryFilter.Attr.AttributeValueList', 'List', done) }) - it('should return SerializationException when QueryFilter.Attr.AttributeValueList.0 is not an attr struct', function(done) { + it('should return SerializationException when QueryFilter.Attr.AttributeValueList.0 is not an attr struct', function (done) { this.timeout(60000) assertType('QueryFilter.Attr.AttributeValueList.0', 'AttrStruct', done) }) - it('should return SerializationException when IndexName is not a string', function(done) { + it('should return SerializationException when IndexName is not a string', function (done) { assertType('IndexName', 'String', done) }) - it('should return SerializationException when ScanIndexForward is not a boolean', function(done) { + it('should return SerializationException when ScanIndexForward is not a boolean', function (done) { assertType('ScanIndexForward', 'Boolean', done) }) - it('should return SerializationException when Select is not a string', function(done) { + it('should return SerializationException when Select is not a string', function (done) { assertType('Select', 'String', done) }) - it('should return SerializationException when Limit is not an integer', function(done) { + it('should return SerializationException when Limit is not an integer', function (done) { assertType('Limit', 'Integer', done) }) - it('should return SerializationException when ConditionalOperator is not a string', function(done) { + it('should return SerializationException when ConditionalOperator is not a string', function (done) { assertType('ConditionalOperator', 'String', done) }) - it('should return SerializationException when KeyConditions is not a map', function(done) { + it('should return SerializationException when KeyConditions is not a map', function (done) { assertType('KeyConditions', 'Map', done) }) - it('should return SerializationException when KeyConditions.Attr is not a struct', function(done) { + it('should return SerializationException when KeyConditions.Attr is not a struct', function (done) { assertType('KeyConditions.Attr', 'ValueStruct', done) }) - it('should return SerializationException when KeyConditions.Attr.ComparisonOperator is not a string', function(done) { + it('should return SerializationException when KeyConditions.Attr.ComparisonOperator is not a string', function (done) { assertType('KeyConditions.Attr.ComparisonOperator', 'String', done) }) - it('should return SerializationException when KeyConditions.Attr.AttributeValueList is not a list', function(done) { + it('should return SerializationException when KeyConditions.Attr.AttributeValueList is not a list', function (done) { assertType('KeyConditions.Attr.AttributeValueList', 'List', done) }) - it('should return SerializationException when KeyConditions.Attr.AttributeValueList.0 is not an attr struct', function(done) { + it('should return SerializationException when KeyConditions.Attr.AttributeValueList.0 is not an attr struct', function (done) { this.timeout(60000) assertType('KeyConditions.Attr.AttributeValueList.0', 'AttrStruct', done) }) - it('should return SerializationException when KeyConditionExpression is not a string', function(done) { + it('should return SerializationException when KeyConditionExpression is not a string', function (done) { assertType('KeyConditionExpression', 'String', done) }) - it('should return SerializationException when FilterExpression is not a string', function(done) { + it('should return SerializationException when FilterExpression is not a string', function (done) { assertType('FilterExpression', 'String', done) }) - it('should return SerializationException when ExpressionAttributeValues is not a map', function(done) { + it('should return SerializationException when ExpressionAttributeValues is not a map', function (done) { assertType('ExpressionAttributeValues', 'Map', done) }) - it('should return SerializationException when ExpressionAttributeValues.Attr is not an attr struct', function(done) { + it('should return SerializationException when ExpressionAttributeValues.Attr is not an attr struct', function (done) { this.timeout(60000) assertType('ExpressionAttributeValues.Attr', 'AttrStruct', done) }) - it('should return SerializationException when ExpressionAttributeNames is not a map', function(done) { + it('should return SerializationException when ExpressionAttributeNames is not a map', function (done) { assertType('ExpressionAttributeNames', 'Map', done) }) - it('should return SerializationException when ExpressionAttributeNames.Attr is not a string', function(done) { + it('should return SerializationException when ExpressionAttributeNames.Attr is not a string', function (done) { assertType('ExpressionAttributeNames.Attr', 'String', done) }) - it('should return SerializationException when ProjectionExpression is not a string', function(done) { + it('should return SerializationException when ProjectionExpression is not a string', function (done) { assertType('ProjectionExpression', 'String', done) }) }) - describe('validations', function() { + describe('validations', function () { - it('should return ValidationException for no TableName', function(done) { + it('should return ValidationException for no TableName', function (done) { assertValidation({}, '1 validation error detected: ' + 'Value null at \'tableName\' failed to satisfy constraint: ' + 'Member must not be null', done) }) - it('should return ValidationException for empty TableName', function(done) { - assertValidation({TableName: ''}, [ + it('should return ValidationException for empty TableName', function (done) { + assertValidation({ TableName: '' }, [ 'Value \'\' at \'tableName\' failed to satisfy constraint: ' + 'Member must satisfy regular expression pattern: [a-zA-Z0-9_.-]+', 'Value \'\' at \'tableName\' failed to satisfy constraint: ' + @@ -150,8 +150,8 @@ describe('query', function() { ], done) }) - it('should return ValidationException for short TableName', function(done) { - assertValidation({TableName: 'a;'}, [ + it('should return ValidationException for short TableName', function (done) { + assertValidation({ TableName: 'a;' }, [ 'Value \'a;\' at \'tableName\' failed to satisfy constraint: ' + 'Member must satisfy regular expression pattern: [a-zA-Z0-9_.-]+', 'Value \'a;\' at \'tableName\' failed to satisfy constraint: ' + @@ -159,16 +159,16 @@ describe('query', function() { ], done) }) - it('should return ValidationException for long TableName', function(done) { + it('should return ValidationException for long TableName', function (done) { var name = new Array(256 + 1).join('a') - assertValidation({TableName: name}, + assertValidation({ TableName: name }, '1 validation error detected: ' + 'Value \'' + name + '\' at \'tableName\' failed to satisfy constraint: ' + 'Member must have length less than or equal to 255', done) }) - it('should return ValidationException for empty IndexName', function(done) { - assertValidation({TableName: 'abc', IndexName: ''}, [ + it('should return ValidationException for empty IndexName', function (done) { + assertValidation({ TableName: 'abc', IndexName: '' }, [ 'Value \'\' at \'indexName\' failed to satisfy constraint: ' + 'Member must satisfy regular expression pattern: [a-zA-Z0-9_.-]+', 'Value \'\' at \'indexName\' failed to satisfy constraint: ' + @@ -176,8 +176,8 @@ describe('query', function() { ], done) }) - it('should return ValidationException for short IndexName', function(done) { - assertValidation({TableName: 'abc', IndexName: 'a;'}, [ + it('should return ValidationException for short IndexName', function (done) { + assertValidation({ TableName: 'abc', IndexName: 'a;' }, [ 'Value \'a;\' at \'indexName\' failed to satisfy constraint: ' + 'Member must satisfy regular expression pattern: [a-zA-Z0-9_.-]+', 'Value \'a;\' at \'indexName\' failed to satisfy constraint: ' + @@ -185,51 +185,51 @@ describe('query', function() { ], done) }) - it('should return ValidationException for long IndexName', function(done) { + it('should return ValidationException for long IndexName', function (done) { var name = '', i for (i = 0; i < 256; i++) name += 'a' - assertValidation({TableName: 'abc', IndexName: name}, + assertValidation({ TableName: 'abc', IndexName: name }, '1 validation error detected: ' + 'Value \'' + name + '\' at \'indexName\' failed to satisfy constraint: ' + 'Member must have length less than or equal to 255', done) }) - it('should return ValidationException for incorrect attributes', function(done) { - assertValidation({TableName: 'abc;', ReturnConsumedCapacity: 'hi', AttributesToGet: [], - IndexName: 'abc;', Select: 'hi', Limit: -1, KeyConditions: {a: {}, b: {ComparisonOperator: ''}}, - ConditionalOperator: 'AN', QueryFilter: {a: {}, b: {ComparisonOperator: ''}}}, [ - 'Value \'hi\' at \'select\' failed to satisfy constraint: ' + + it('should return ValidationException for incorrect attributes', function (done) { + assertValidation({ TableName: 'abc;', ReturnConsumedCapacity: 'hi', AttributesToGet: [], + IndexName: 'abc;', Select: 'hi', Limit: -1, KeyConditions: { a: {}, b: { ComparisonOperator: '' } }, + ConditionalOperator: 'AN', QueryFilter: { a: {}, b: { ComparisonOperator: '' } } }, [ + 'Value \'hi\' at \'select\' failed to satisfy constraint: ' + 'Member must satisfy enum value set: [SPECIFIC_ATTRIBUTES, COUNT, ALL_ATTRIBUTES, ALL_PROJECTED_ATTRIBUTES]', - 'Value \'abc;\' at \'indexName\' failed to satisfy constraint: ' + + 'Value \'abc;\' at \'indexName\' failed to satisfy constraint: ' + 'Member must satisfy regular expression pattern: [a-zA-Z0-9_.-]+', - 'Value \'hi\' at \'returnConsumedCapacity\' failed to satisfy constraint: ' + + 'Value \'hi\' at \'returnConsumedCapacity\' failed to satisfy constraint: ' + 'Member must satisfy enum value set: [INDEXES, TOTAL, NONE]', - 'Value null at \'queryFilter.a.member.comparisonOperator\' failed to satisfy constraint: ' + + 'Value null at \'queryFilter.a.member.comparisonOperator\' failed to satisfy constraint: ' + 'Member must not be null', - 'Value \'\' at \'queryFilter.b.member.comparisonOperator\' failed to satisfy constraint: ' + + 'Value \'\' at \'queryFilter.b.member.comparisonOperator\' failed to satisfy constraint: ' + 'Member must satisfy enum value set: [IN, NULL, BETWEEN, LT, NOT_CONTAINS, EQ, GT, NOT_NULL, NE, LE, BEGINS_WITH, GE, CONTAINS]', - 'Value \'abc;\' at \'tableName\' failed to satisfy constraint: ' + + 'Value \'abc;\' at \'tableName\' failed to satisfy constraint: ' + 'Member must satisfy regular expression pattern: [a-zA-Z0-9_.-]+', - 'Value \'AN\' at \'conditionalOperator\' failed to satisfy constraint: ' + + 'Value \'AN\' at \'conditionalOperator\' failed to satisfy constraint: ' + 'Member must satisfy enum value set: [OR, AND]', - 'Value \'[]\' at \'attributesToGet\' failed to satisfy constraint: ' + + 'Value \'[]\' at \'attributesToGet\' failed to satisfy constraint: ' + 'Member must have length greater than or equal to 1', - 'Value \'-1\' at \'limit\' failed to satisfy constraint: ' + + 'Value \'-1\' at \'limit\' failed to satisfy constraint: ' + 'Member must have value greater than or equal to 1', - 'Value null at \'keyConditions.a.member.comparisonOperator\' failed to satisfy constraint: ' + + 'Value null at \'keyConditions.a.member.comparisonOperator\' failed to satisfy constraint: ' + 'Member must not be null', - ], done) + ], done) }) - it('should return ValidationException if all expressions and non-expression', function(done) { + it('should return ValidationException if all expressions and non-expression', function (done) { assertValidation({ TableName: 'abc', - ExclusiveStartKey: {a: {}}, + ExclusiveStartKey: { a: {} }, Select: 'SPECIFIC_ATTRIBUTES', - AttributesToGet: ['a', 'a'], - QueryFilter: {a: {ComparisonOperator: 'EQ', AttributeValueList: [{}]}}, + AttributesToGet: [ 'a', 'a' ], + QueryFilter: { a: { ComparisonOperator: 'EQ', AttributeValueList: [ {} ] } }, ConditionalOperator: 'OR', - KeyConditions: {a: {ComparisonOperator: 'EQ', AttributeValueList: [{}]}}, + KeyConditions: { a: { ComparisonOperator: 'EQ', AttributeValueList: [ {} ] } }, ProjectionExpression: '', FilterExpression: '', KeyConditionExpression: '', @@ -240,13 +240,13 @@ describe('query', function() { 'Expression parameters: {ProjectionExpression, FilterExpression, KeyConditionExpression}', done) }) - it('should return ValidationException if all expressions and non-expression without KeyConditionExpression', function(done) { + it('should return ValidationException if all expressions and non-expression without KeyConditionExpression', function (done) { assertValidation({ TableName: 'abc', - QueryFilter: {a: {ComparisonOperator: 'EQ', AttributeValueList: [{}]}}, - AttributesToGet: ['a', 'a'], - ExclusiveStartKey: {a: {}}, - KeyConditions: {a: {ComparisonOperator: 'EQ', AttributeValueList: [{}]}}, + QueryFilter: { a: { ComparisonOperator: 'EQ', AttributeValueList: [ {} ] } }, + AttributesToGet: [ 'a', 'a' ], + ExclusiveStartKey: { a: {} }, + KeyConditions: { a: { ComparisonOperator: 'EQ', AttributeValueList: [ {} ] } }, ConditionalOperator: 'OR', Select: 'SPECIFIC_ATTRIBUTES', FilterExpression: '', @@ -258,12 +258,12 @@ describe('query', function() { 'Expression parameters: {ProjectionExpression, FilterExpression}', done) }) - it('should return ValidationException if all expressions and non-expression without KeyConditions', function(done) { + it('should return ValidationException if all expressions and non-expression without KeyConditions', function (done) { assertValidation({ TableName: 'abc', - QueryFilter: {a: {ComparisonOperator: 'EQ', AttributeValueList: [{}]}}, - AttributesToGet: ['a', 'a'], - ExclusiveStartKey: {a: {}}, + QueryFilter: { a: { ComparisonOperator: 'EQ', AttributeValueList: [ {} ] } }, + AttributesToGet: [ 'a', 'a' ], + ExclusiveStartKey: { a: {} }, ConditionalOperator: 'OR', Select: 'SPECIFIC_ATTRIBUTES', KeyConditionExpression: '', @@ -276,12 +276,12 @@ describe('query', function() { 'Expression parameters: {ProjectionExpression, FilterExpression, KeyConditionExpression}', done) }) - it('should return ValidationException if ExpressionAttributeNames but no expressions', function(done) { + it('should return ValidationException if ExpressionAttributeNames but no expressions', function (done) { assertValidation({ TableName: 'abc', - QueryFilter: {a: {ComparisonOperator: 'EQ', AttributeValueList: [{}]}}, - AttributesToGet: ['a', 'a'], - ExclusiveStartKey: {a: {}}, + QueryFilter: { a: { ComparisonOperator: 'EQ', AttributeValueList: [ {} ] } }, + AttributesToGet: [ 'a', 'a' ], + ExclusiveStartKey: { a: {} }, ConditionalOperator: 'OR', Select: 'SPECIFIC_ATTRIBUTES', ExpressionAttributeNames: {}, @@ -289,331 +289,331 @@ describe('query', function() { }, 'ExpressionAttributeNames can only be specified when using expressions', done) }) - it('should return ValidationException if ExpressionAttributeValues but no expressions', function(done) { + it('should return ValidationException if ExpressionAttributeValues but no expressions', function (done) { assertValidation({ TableName: 'abc', - QueryFilter: {a: {ComparisonOperator: 'EQ', AttributeValueList: [{}]}}, - AttributesToGet: ['a', 'a'], - ExclusiveStartKey: {a: {}}, + QueryFilter: { a: { ComparisonOperator: 'EQ', AttributeValueList: [ {} ] } }, + AttributesToGet: [ 'a', 'a' ], + ExclusiveStartKey: { a: {} }, ConditionalOperator: 'OR', Select: 'SPECIFIC_ATTRIBUTES', ExpressionAttributeValues: {}, }, 'ExpressionAttributeValues can only be specified when using expressions: FilterExpression and KeyConditionExpression are null', done) }) - it('should return ValidationException for bad attribute values in QueryFilter', function(done) { + it('should return ValidationException for bad attribute values in QueryFilter', function (done) { async.forEach([ {}, - {a: ''}, - ], function(expr, cb) { + { a: '' }, + ], function (expr, cb) { assertValidation({ TableName: 'abc', - ExclusiveStartKey: {a: {}}, - AttributesToGet: ['a', 'a'], - KeyConditions: {a: {ComparisonOperator: 'EQ', AttributeValueList: [{}]}}, - QueryFilter: {a: {ComparisonOperator: 'EQ', AttributeValueList: [expr, {S: ''}]}}, + ExclusiveStartKey: { a: {} }, + AttributesToGet: [ 'a', 'a' ], + KeyConditions: { a: { ComparisonOperator: 'EQ', AttributeValueList: [ {} ] } }, + QueryFilter: { a: { ComparisonOperator: 'EQ', AttributeValueList: [ expr, { S: '' } ] } }, }, 'Supplied AttributeValue is empty, must contain exactly one of the supported datatypes', cb) }, done) }) - it('should return ValidationException for invalid values in QueryFilter', function(done) { + it('should return ValidationException for invalid values in QueryFilter', function (done) { async.forEach([ - [{NULL: 'no'}, 'Null attribute value types must have the value of true'], - [{SS: []}, 'An string set may not be empty'], - [{NS: []}, 'An number set may not be empty'], - [{BS: []}, 'Binary sets should not be empty'], - [{SS: ['a', 'a']}, 'Input collection [a, a] contains duplicates.'], - [{BS: ['Yg==', 'Yg==']}, 'Input collection [Yg==, Yg==]of type BS contains duplicates.'], - ], function(expr, cb) { + [ { NULL: 'no' }, 'Null attribute value types must have the value of true' ], + [ { SS: [] }, 'An string set may not be empty' ], + [ { NS: [] }, 'An number set may not be empty' ], + [ { BS: [] }, 'Binary sets should not be empty' ], + [ { SS: [ 'a', 'a' ] }, 'Input collection [a, a] contains duplicates.' ], + [ { BS: [ 'Yg==', 'Yg==' ] }, 'Input collection [Yg==, Yg==]of type BS contains duplicates.' ], + ], function (expr, cb) { assertValidation({ TableName: 'abc', - ExclusiveStartKey: {a: {}}, - AttributesToGet: ['a', 'a'], - KeyConditions: {a: {ComparisonOperator: 'EQ', AttributeValueList: [{}]}}, - QueryFilter: {a: {ComparisonOperator: 'EQ', AttributeValueList: [{N: '1'}, expr[0], {}]}}, + ExclusiveStartKey: { a: {} }, + AttributesToGet: [ 'a', 'a' ], + KeyConditions: { a: { ComparisonOperator: 'EQ', AttributeValueList: [ {} ] } }, + QueryFilter: { a: { ComparisonOperator: 'EQ', AttributeValueList: [ { N: '1' }, expr[0], {} ] } }, }, 'One or more parameter values were invalid: ' + expr[1], cb) }, done) }) - it('should return ValidationException for empty/invalid numbers in QueryFilter', function(done) { + it('should return ValidationException for empty/invalid numbers in QueryFilter', function (done) { async.forEach([ - [{S: '', N: ''}, 'The parameter cannot be converted to a numeric value'], - [{S: 'a', N: ''}, 'The parameter cannot be converted to a numeric value'], - [{S: 'a', N: 'b'}, 'The parameter cannot be converted to a numeric value: b'], - [{NS: ['1', '']}, 'The parameter cannot be converted to a numeric value'], - [{NS: ['1', 'b']}, 'The parameter cannot be converted to a numeric value: b'], - [{NS: ['1', '1']}, 'Input collection contains duplicates'], - [{N: '123456789012345678901234567890123456789'}, 'Attempting to store more than 38 significant digits in a Number'], - [{N: '-1.23456789012345678901234567890123456789'}, 'Attempting to store more than 38 significant digits in a Number'], - [{N: '1e126'}, 'Number overflow. Attempting to store a number with magnitude larger than supported range'], - [{N: '-1e126'}, 'Number overflow. Attempting to store a number with magnitude larger than supported range'], - [{N: '1e-131'}, 'Number underflow. Attempting to store a number with magnitude smaller than supported range'], - [{N: '-1e-131'}, 'Number underflow. Attempting to store a number with magnitude smaller than supported range'], - ], function(expr, cb) { + [ { S: '', N: '' }, 'The parameter cannot be converted to a numeric value' ], + [ { S: 'a', N: '' }, 'The parameter cannot be converted to a numeric value' ], + [ { S: 'a', N: 'b' }, 'The parameter cannot be converted to a numeric value: b' ], + [ { NS: [ '1', '' ] }, 'The parameter cannot be converted to a numeric value' ], + [ { NS: [ '1', 'b' ] }, 'The parameter cannot be converted to a numeric value: b' ], + [ { NS: [ '1', '1' ] }, 'Input collection contains duplicates' ], + [ { N: '123456789012345678901234567890123456789' }, 'Attempting to store more than 38 significant digits in a Number' ], + [ { N: '-1.23456789012345678901234567890123456789' }, 'Attempting to store more than 38 significant digits in a Number' ], + [ { N: '1e126' }, 'Number overflow. Attempting to store a number with magnitude larger than supported range' ], + [ { N: '-1e126' }, 'Number overflow. Attempting to store a number with magnitude larger than supported range' ], + [ { N: '1e-131' }, 'Number underflow. Attempting to store a number with magnitude smaller than supported range' ], + [ { N: '-1e-131' }, 'Number underflow. Attempting to store a number with magnitude smaller than supported range' ], + ], function (expr, cb) { assertValidation({ TableName: 'abc', - ExclusiveStartKey: {a: {}}, - AttributesToGet: ['a', 'a'], - KeyConditions: {a: {ComparisonOperator: 'EQ', AttributeValueList: [{}]}}, - QueryFilter: {a: {ComparisonOperator: 'EQ', AttributeValueList: [{N: '1'}, expr[0]]}}, + ExclusiveStartKey: { a: {} }, + AttributesToGet: [ 'a', 'a' ], + KeyConditions: { a: { ComparisonOperator: 'EQ', AttributeValueList: [ {} ] } }, + QueryFilter: { a: { ComparisonOperator: 'EQ', AttributeValueList: [ { N: '1' }, expr[0] ] } }, }, expr[1], cb) }, done) }) - it('should return ValidationException for multiple datatypes in QueryFilter', function(done) { + it('should return ValidationException for multiple datatypes in QueryFilter', function (done) { assertValidation({ TableName: 'abc', - ExclusiveStartKey: {a: {}}, - AttributesToGet: ['a', 'a'], - KeyConditions: {a: {ComparisonOperator: 'EQ', AttributeValueList: [{}]}}, - QueryFilter: {a: {ComparisonOperator: 'EQ', AttributeValueList: [{N: '1'}, {S: 'a', N: '1'}]}}, + ExclusiveStartKey: { a: {} }, + AttributesToGet: [ 'a', 'a' ], + KeyConditions: { a: { ComparisonOperator: 'EQ', AttributeValueList: [ {} ] } }, + QueryFilter: { a: { ComparisonOperator: 'EQ', AttributeValueList: [ { N: '1' }, { S: 'a', N: '1' } ] } }, }, 'Supplied AttributeValue has more than one datatypes set, must contain exactly one of the supported datatypes', done) }) - it('should return ValidationException for incorrect number of QueryFilter arguments', function(done) { + it('should return ValidationException for incorrect number of QueryFilter arguments', function (done) { async.forEach([ - {a: {ComparisonOperator: 'EQ'}, b: {ComparisonOperator: 'NULL'}, c: {ComparisonOperator: 'NULL'}}, - {a: {ComparisonOperator: 'EQ'}}, - {a: {ComparisonOperator: 'EQ', AttributeValueList: []}}, - {a: {ComparisonOperator: 'NE'}}, - {a: {ComparisonOperator: 'LE'}}, - {a: {ComparisonOperator: 'LT'}}, - {a: {ComparisonOperator: 'GE'}}, - {a: {ComparisonOperator: 'GT'}}, - {a: {ComparisonOperator: 'CONTAINS'}}, - {a: {ComparisonOperator: 'NOT_CONTAINS'}}, - {a: {ComparisonOperator: 'BEGINS_WITH'}}, - {a: {ComparisonOperator: 'IN'}}, - {a: {ComparisonOperator: 'BETWEEN'}}, - {a: {ComparisonOperator: 'NULL', AttributeValueList: [{S: 'a'}]}}, - {a: {ComparisonOperator: 'NOT_NULL', AttributeValueList: [{S: 'a'}]}}, - {a: {ComparisonOperator: 'EQ', AttributeValueList: [{S: 'a'}, {S: 'a'}]}}, - {a: {ComparisonOperator: 'NE', AttributeValueList: [{S: 'a'}, {S: 'a'}]}}, - {a: {ComparisonOperator: 'LE', AttributeValueList: [{S: 'a'}, {S: 'a'}]}}, - {a: {ComparisonOperator: 'LT', AttributeValueList: [{S: 'a'}, {S: 'a'}]}}, - {a: {ComparisonOperator: 'GE', AttributeValueList: [{S: 'a'}, {S: 'a'}]}}, - {a: {ComparisonOperator: 'GT', AttributeValueList: [{S: 'a'}, {S: 'a'}]}}, - {a: {ComparisonOperator: 'CONTAINS', AttributeValueList: [{S: 'a'}, {S: 'a'}]}}, - {a: {ComparisonOperator: 'NOT_CONTAINS', AttributeValueList: [{S: 'a'}, {S: 'a'}]}}, - {a: {ComparisonOperator: 'NULL', AttributeValueList: [{S: 'a'}, {S: 'a'}]}}, - {a: {ComparisonOperator: 'NOT_NULL', AttributeValueList: [{S: 'a'}, {S: 'a'}]}}, - {a: {ComparisonOperator: 'BETWEEN', AttributeValueList: [{S: 'a'}, {S: 'a'}, {S: 'a'}]}}, - ], function(expr, cb) { + { a: { ComparisonOperator: 'EQ' }, b: { ComparisonOperator: 'NULL' }, c: { ComparisonOperator: 'NULL' } }, + { a: { ComparisonOperator: 'EQ' } }, + { a: { ComparisonOperator: 'EQ', AttributeValueList: [] } }, + { a: { ComparisonOperator: 'NE' } }, + { a: { ComparisonOperator: 'LE' } }, + { a: { ComparisonOperator: 'LT' } }, + { a: { ComparisonOperator: 'GE' } }, + { a: { ComparisonOperator: 'GT' } }, + { a: { ComparisonOperator: 'CONTAINS' } }, + { a: { ComparisonOperator: 'NOT_CONTAINS' } }, + { a: { ComparisonOperator: 'BEGINS_WITH' } }, + { a: { ComparisonOperator: 'IN' } }, + { a: { ComparisonOperator: 'BETWEEN' } }, + { a: { ComparisonOperator: 'NULL', AttributeValueList: [ { S: 'a' } ] } }, + { a: { ComparisonOperator: 'NOT_NULL', AttributeValueList: [ { S: 'a' } ] } }, + { a: { ComparisonOperator: 'EQ', AttributeValueList: [ { S: 'a' }, { S: 'a' } ] } }, + { a: { ComparisonOperator: 'NE', AttributeValueList: [ { S: 'a' }, { S: 'a' } ] } }, + { a: { ComparisonOperator: 'LE', AttributeValueList: [ { S: 'a' }, { S: 'a' } ] } }, + { a: { ComparisonOperator: 'LT', AttributeValueList: [ { S: 'a' }, { S: 'a' } ] } }, + { a: { ComparisonOperator: 'GE', AttributeValueList: [ { S: 'a' }, { S: 'a' } ] } }, + { a: { ComparisonOperator: 'GT', AttributeValueList: [ { S: 'a' }, { S: 'a' } ] } }, + { a: { ComparisonOperator: 'CONTAINS', AttributeValueList: [ { S: 'a' }, { S: 'a' } ] } }, + { a: { ComparisonOperator: 'NOT_CONTAINS', AttributeValueList: [ { S: 'a' }, { S: 'a' } ] } }, + { a: { ComparisonOperator: 'NULL', AttributeValueList: [ { S: 'a' }, { S: 'a' } ] } }, + { a: { ComparisonOperator: 'NOT_NULL', AttributeValueList: [ { S: 'a' }, { S: 'a' } ] } }, + { a: { ComparisonOperator: 'BETWEEN', AttributeValueList: [ { S: 'a' }, { S: 'a' }, { S: 'a' } ] } }, + ], function (expr, cb) { assertValidation({ TableName: 'abc', - ExclusiveStartKey: {a: {}}, - AttributesToGet: ['a', 'a'], - KeyConditions: {a: {ComparisonOperator: 'EQ', AttributeValueList: [{}]}}, + ExclusiveStartKey: { a: {} }, + AttributesToGet: [ 'a', 'a' ], + KeyConditions: { a: { ComparisonOperator: 'EQ', AttributeValueList: [ {} ] } }, QueryFilter: expr, }, 'One or more parameter values were invalid: Invalid number of argument(s) for the ' + expr.a.ComparisonOperator + ' ComparisonOperator', cb) }, done) }) - it('should return ValidationException for duplicate values in AttributesToGet', function(done) { + it('should return ValidationException for duplicate values in AttributesToGet', function (done) { assertValidation({ TableName: 'abc', QueryFilter: {}, - ExclusiveStartKey: {a: {}}, - AttributesToGet: ['a', 'a'], + ExclusiveStartKey: { a: {} }, + AttributesToGet: [ 'a', 'a' ], }, 'One or more parameter values were invalid: Duplicate value in attribute name: a', done) }) - it('should return ValidationException for unsupported datatype in ExclusiveStartKey', function(done) { + it('should return ValidationException for unsupported datatype in ExclusiveStartKey', function (done) { async.forEach([ - {KeyConditions: {a: {ComparisonOperator: 'EQ'}}}, - {KeyConditionExpression: '', ExpressionAttributeNames: {}, ExpressionAttributeValues: {}}, - ], function(keyOpts, cb) { + { KeyConditions: { a: { ComparisonOperator: 'EQ' } } }, + { KeyConditionExpression: '', ExpressionAttributeNames: {}, ExpressionAttributeValues: {} }, + ], function (keyOpts, cb) { async.forEach([ {}, - {a: ''}, - {M: {a: {}}}, - {L: [{}]}, - {L: [{a: {}}]}, - ], function(expr, cb) { + { a: '' }, + { M: { a: {} } }, + { L: [ {} ] }, + { L: [ { a: {} } ] }, + ], function (expr, cb) { assertValidation({ TableName: 'abc', KeyConditions: keyOpts.KeyConditions, KeyConditionExpression: keyOpts.KeyConditionExpression, - ExclusiveStartKey: {a: expr}, + ExclusiveStartKey: { a: expr }, }, 'The provided starting key is invalid: ' + 'Supplied AttributeValue is empty, must contain exactly one of the supported datatypes', cb) }, cb) }, done) }) - it('should return ValidationException for invalid values in ExclusiveStartKey', function(done) { + it('should return ValidationException for invalid values in ExclusiveStartKey', function (done) { async.forEach([ - {KeyConditions: {a: {ComparisonOperator: 'EQ', AttributeValueList: [{}, {}]}}}, - {KeyConditionExpression: '', ExpressionAttributeNames: {}, ExpressionAttributeValues: {}}, - ], function(keyOpts, cb) { + { KeyConditions: { a: { ComparisonOperator: 'EQ', AttributeValueList: [ {}, {} ] } } }, + { KeyConditionExpression: '', ExpressionAttributeNames: {}, ExpressionAttributeValues: {} }, + ], function (keyOpts, cb) { async.forEach([ - [{NULL: 'no'}, 'Null attribute value types must have the value of true'], - [{SS: []}, 'An string set may not be empty'], - [{BS: []}, 'Binary sets should not be empty'], - ], function(expr, cb) { + [ { NULL: 'no' }, 'Null attribute value types must have the value of true' ], + [ { SS: [] }, 'An string set may not be empty' ], + [ { BS: [] }, 'Binary sets should not be empty' ], + ], function (expr, cb) { assertValidation({ TableName: 'abc', KeyConditions: keyOpts.KeyConditions, KeyConditionExpression: keyOpts.KeyConditionExpression, - ExclusiveStartKey: {a: expr[0]}, + ExclusiveStartKey: { a: expr[0] }, }, 'The provided starting key is invalid: ' + 'One or more parameter values were invalid: ' + expr[1], cb) }, cb) }, done) }) - it('should return ValidationException for invalid values in ExclusiveStartKey without provided message', function(done) { + it('should return ValidationException for invalid values in ExclusiveStartKey without provided message', function (done) { async.forEach([ - {KeyConditions: {a: {ComparisonOperator: 'EQ', AttributeValueList: [{}, {}]}}}, - {KeyConditionExpression: '', ExpressionAttributeNames: {}, ExpressionAttributeValues: {}}, - ], function(keyOpts, cb) { + { KeyConditions: { a: { ComparisonOperator: 'EQ', AttributeValueList: [ {}, {} ] } } }, + { KeyConditionExpression: '', ExpressionAttributeNames: {}, ExpressionAttributeValues: {} }, + ], function (keyOpts, cb) { async.forEach([ - [{NS: []}, 'An number set may not be empty'], - [{SS: ['a', 'a']}, 'Input collection [a, a] contains duplicates.'], - [{BS: ['Yg==', 'Yg==']}, 'Input collection [Yg==, Yg==]of type BS contains duplicates.'], - ], function(expr, cb) { + [ { NS: [] }, 'An number set may not be empty' ], + [ { SS: [ 'a', 'a' ] }, 'Input collection [a, a] contains duplicates.' ], + [ { BS: [ 'Yg==', 'Yg==' ] }, 'Input collection [Yg==, Yg==]of type BS contains duplicates.' ], + ], function (expr, cb) { assertValidation({ TableName: 'abc', KeyConditions: keyOpts.KeyConditions, KeyConditionExpression: keyOpts.KeyConditionExpression, - ExclusiveStartKey: {a: expr[0]}, + ExclusiveStartKey: { a: expr[0] }, }, 'One or more parameter values were invalid: ' + expr[1], cb) }, cb) }, done) }) - it('should return ValidationException for empty/invalid numbers in ExclusiveStartKey', function(done) { + it('should return ValidationException for empty/invalid numbers in ExclusiveStartKey', function (done) { async.forEach([ - {KeyConditions: {a: {ComparisonOperator: 'EQ', AttributeValueList: [{}]}}}, - {KeyConditionExpression: '', ExpressionAttributeNames: {}, ExpressionAttributeValues: {}}, - ], function(keyOpts, cb) { + { KeyConditions: { a: { ComparisonOperator: 'EQ', AttributeValueList: [ {} ] } } }, + { KeyConditionExpression: '', ExpressionAttributeNames: {}, ExpressionAttributeValues: {} }, + ], function (keyOpts, cb) { async.forEach([ - [{S: '', N: ''}, 'The parameter cannot be converted to a numeric value'], - [{S: 'a', N: ''}, 'The parameter cannot be converted to a numeric value'], - [{S: 'a', N: 'b'}, 'The parameter cannot be converted to a numeric value: b'], - [{NS: ['1', '']}, 'The parameter cannot be converted to a numeric value'], - [{NS: ['1', 'b']}, 'The parameter cannot be converted to a numeric value: b'], - [{NS: ['1', '1']}, 'Input collection contains duplicates'], - [{N: '123456789012345678901234567890123456789'}, 'Attempting to store more than 38 significant digits in a Number'], - [{N: '-1.23456789012345678901234567890123456789'}, 'Attempting to store more than 38 significant digits in a Number'], - [{N: '1e126'}, 'Number overflow. Attempting to store a number with magnitude larger than supported range'], - [{N: '-1e126'}, 'Number overflow. Attempting to store a number with magnitude larger than supported range'], - [{N: '1e-131'}, 'Number underflow. Attempting to store a number with magnitude smaller than supported range'], - [{N: '-1e-131'}, 'Number underflow. Attempting to store a number with magnitude smaller than supported range'], - ], function(expr, cb) { + [ { S: '', N: '' }, 'The parameter cannot be converted to a numeric value' ], + [ { S: 'a', N: '' }, 'The parameter cannot be converted to a numeric value' ], + [ { S: 'a', N: 'b' }, 'The parameter cannot be converted to a numeric value: b' ], + [ { NS: [ '1', '' ] }, 'The parameter cannot be converted to a numeric value' ], + [ { NS: [ '1', 'b' ] }, 'The parameter cannot be converted to a numeric value: b' ], + [ { NS: [ '1', '1' ] }, 'Input collection contains duplicates' ], + [ { N: '123456789012345678901234567890123456789' }, 'Attempting to store more than 38 significant digits in a Number' ], + [ { N: '-1.23456789012345678901234567890123456789' }, 'Attempting to store more than 38 significant digits in a Number' ], + [ { N: '1e126' }, 'Number overflow. Attempting to store a number with magnitude larger than supported range' ], + [ { N: '-1e126' }, 'Number overflow. Attempting to store a number with magnitude larger than supported range' ], + [ { N: '1e-131' }, 'Number underflow. Attempting to store a number with magnitude smaller than supported range' ], + [ { N: '-1e-131' }, 'Number underflow. Attempting to store a number with magnitude smaller than supported range' ], + ], function (expr, cb) { assertValidation({ TableName: 'abc', KeyConditions: keyOpts.KeyConditions, KeyConditionExpression: keyOpts.KeyConditionExpression, - ExclusiveStartKey: {a: expr[0]}, + ExclusiveStartKey: { a: expr[0] }, }, expr[1], cb) }, cb) }, done) }) - it('should return ValidationException for multiple datatypes in ExclusiveStartKey', function(done) { + it('should return ValidationException for multiple datatypes in ExclusiveStartKey', function (done) { async.forEach([ - {KeyConditions: {a: {ComparisonOperator: 'EQ', AttributeValueList: [{}]}}}, - {KeyConditionExpression: '', ExpressionAttributeNames: {}, ExpressionAttributeValues: {}}, - ], function(keyOpts, cb) { + { KeyConditions: { a: { ComparisonOperator: 'EQ', AttributeValueList: [ {} ] } } }, + { KeyConditionExpression: '', ExpressionAttributeNames: {}, ExpressionAttributeValues: {} }, + ], function (keyOpts, cb) { assertValidation({ TableName: 'abc', KeyConditions: keyOpts.KeyConditions, KeyConditionExpression: keyOpts.KeyConditionExpression, - ExclusiveStartKey: {a: {S: 'a', N: '1'}}, + ExclusiveStartKey: { a: { S: 'a', N: '1' } }, }, 'The provided starting key is invalid: ' + 'Supplied AttributeValue has more than one datatypes set, must contain exactly one of the supported datatypes', cb) }, done) }) - it('should return ValidationException for bad attribute values in KeyConditions', function(done) { + it('should return ValidationException for bad attribute values in KeyConditions', function (done) { async.forEach([ {}, - {a: ''}, - ], function(expr, cb) { + { a: '' }, + ], function (expr, cb) { assertValidation({ TableName: 'abc', QueryFilter: {}, - KeyConditions: {a: {ComparisonOperator: 'EQ', AttributeValueList: [expr, {S: ''}]}}, + KeyConditions: { a: { ComparisonOperator: 'EQ', AttributeValueList: [ expr, { S: '' } ] } }, }, 'Supplied AttributeValue is empty, must contain exactly one of the supported datatypes', cb) }, done) }) - it('should return ValidationException for invalid values in KeyConditions', function(done) { + it('should return ValidationException for invalid values in KeyConditions', function (done) { async.forEach([ - [{NULL: 'no'}, 'Null attribute value types must have the value of true'], - [{SS: []}, 'An string set may not be empty'], - [{NS: []}, 'An number set may not be empty'], - [{BS: []}, 'Binary sets should not be empty'], - [{SS: ['a', 'a']}, 'Input collection [a, a] contains duplicates.'], - [{BS: ['Yg==', 'Yg==']}, 'Input collection [Yg==, Yg==]of type BS contains duplicates.'], - ], function(expr, cb) { + [ { NULL: 'no' }, 'Null attribute value types must have the value of true' ], + [ { SS: [] }, 'An string set may not be empty' ], + [ { NS: [] }, 'An number set may not be empty' ], + [ { BS: [] }, 'Binary sets should not be empty' ], + [ { SS: [ 'a', 'a' ] }, 'Input collection [a, a] contains duplicates.' ], + [ { BS: [ 'Yg==', 'Yg==' ] }, 'Input collection [Yg==, Yg==]of type BS contains duplicates.' ], + ], function (expr, cb) { assertValidation({ TableName: 'abc', - KeyConditions: {a: {ComparisonOperator: 'EQ', AttributeValueList: [{N: '1'}, expr[0], {}]}}, + KeyConditions: { a: { ComparisonOperator: 'EQ', AttributeValueList: [ { N: '1' }, expr[0], {} ] } }, }, 'One or more parameter values were invalid: ' + expr[1], cb) }, done) }) - it('should return ValidationException for empty/invalid numbers in KeyConditions', function(done) { + it('should return ValidationException for empty/invalid numbers in KeyConditions', function (done) { async.forEach([ - [{S: '', N: ''}, 'The parameter cannot be converted to a numeric value'], - [{S: 'a', N: ''}, 'The parameter cannot be converted to a numeric value'], - [{S: 'a', N: 'b'}, 'The parameter cannot be converted to a numeric value: b'], - [{NS: ['1', '']}, 'The parameter cannot be converted to a numeric value'], - [{NS: ['1', 'b']}, 'The parameter cannot be converted to a numeric value: b'], - [{NS: ['1', '1']}, 'Input collection contains duplicates'], - [{N: '123456789012345678901234567890123456789'}, 'Attempting to store more than 38 significant digits in a Number'], - [{N: '-1.23456789012345678901234567890123456789'}, 'Attempting to store more than 38 significant digits in a Number'], - [{N: '1e126'}, 'Number overflow. Attempting to store a number with magnitude larger than supported range'], - [{N: '-1e126'}, 'Number overflow. Attempting to store a number with magnitude larger than supported range'], - [{N: '1e-131'}, 'Number underflow. Attempting to store a number with magnitude smaller than supported range'], - [{N: '-1e-131'}, 'Number underflow. Attempting to store a number with magnitude smaller than supported range'], - ], function(expr, cb) { + [ { S: '', N: '' }, 'The parameter cannot be converted to a numeric value' ], + [ { S: 'a', N: '' }, 'The parameter cannot be converted to a numeric value' ], + [ { S: 'a', N: 'b' }, 'The parameter cannot be converted to a numeric value: b' ], + [ { NS: [ '1', '' ] }, 'The parameter cannot be converted to a numeric value' ], + [ { NS: [ '1', 'b' ] }, 'The parameter cannot be converted to a numeric value: b' ], + [ { NS: [ '1', '1' ] }, 'Input collection contains duplicates' ], + [ { N: '123456789012345678901234567890123456789' }, 'Attempting to store more than 38 significant digits in a Number' ], + [ { N: '-1.23456789012345678901234567890123456789' }, 'Attempting to store more than 38 significant digits in a Number' ], + [ { N: '1e126' }, 'Number overflow. Attempting to store a number with magnitude larger than supported range' ], + [ { N: '-1e126' }, 'Number overflow. Attempting to store a number with magnitude larger than supported range' ], + [ { N: '1e-131' }, 'Number underflow. Attempting to store a number with magnitude smaller than supported range' ], + [ { N: '-1e-131' }, 'Number underflow. Attempting to store a number with magnitude smaller than supported range' ], + ], function (expr, cb) { assertValidation({ TableName: 'abc', - KeyConditions: {a: {ComparisonOperator: 'EQ', AttributeValueList: [{N: '1'}, expr[0]]}}, + KeyConditions: { a: { ComparisonOperator: 'EQ', AttributeValueList: [ { N: '1' }, expr[0] ] } }, }, expr[1], cb) }, done) }) - it('should return ValidationException for multiple datatypes in KeyConditions', function(done) { + it('should return ValidationException for multiple datatypes in KeyConditions', function (done) { assertValidation({ TableName: 'abc', - KeyConditions: {a: {ComparisonOperator: 'EQ', AttributeValueList: [{N: '1'}, {S: 'a', N: '1'}]}}, + KeyConditions: { a: { ComparisonOperator: 'EQ', AttributeValueList: [ { N: '1' }, { S: 'a', N: '1' } ] } }, }, 'Supplied AttributeValue has more than one datatypes set, must contain exactly one of the supported datatypes', done) }) - it('should return ValidationException for incorrect number of KeyConditions arguments', function(done) { + it('should return ValidationException for incorrect number of KeyConditions arguments', function (done) { async.forEach([ - {a: {ComparisonOperator: 'EQ'}, b: {ComparisonOperator: 'NULL'}, c: {ComparisonOperator: 'NULL'}}, - {a: {ComparisonOperator: 'EQ'}}, - {a: {ComparisonOperator: 'EQ', AttributeValueList: []}}, - {a: {ComparisonOperator: 'NE'}}, - {a: {ComparisonOperator: 'LE'}}, - {a: {ComparisonOperator: 'LT'}}, - {a: {ComparisonOperator: 'GE'}}, - {a: {ComparisonOperator: 'GT'}}, - {a: {ComparisonOperator: 'CONTAINS'}}, - {a: {ComparisonOperator: 'NOT_CONTAINS'}}, - {a: {ComparisonOperator: 'BEGINS_WITH'}}, - {a: {ComparisonOperator: 'IN'}}, - {a: {ComparisonOperator: 'BETWEEN'}}, - {a: {ComparisonOperator: 'NULL', AttributeValueList: [{S: 'a'}]}}, - {a: {ComparisonOperator: 'NOT_NULL', AttributeValueList: [{S: 'a'}]}}, - {a: {ComparisonOperator: 'EQ', AttributeValueList: [{S: 'a'}, {S: 'a'}]}}, - {a: {ComparisonOperator: 'NE', AttributeValueList: [{S: 'a'}, {S: 'a'}]}}, - {a: {ComparisonOperator: 'LE', AttributeValueList: [{S: 'a'}, {S: 'a'}]}}, - {a: {ComparisonOperator: 'LT', AttributeValueList: [{S: 'a'}, {S: 'a'}]}}, - {a: {ComparisonOperator: 'GE', AttributeValueList: [{S: 'a'}, {S: 'a'}]}}, - {a: {ComparisonOperator: 'GT', AttributeValueList: [{S: 'a'}, {S: 'a'}]}}, - {a: {ComparisonOperator: 'CONTAINS', AttributeValueList: [{S: 'a'}, {S: 'a'}]}}, - {a: {ComparisonOperator: 'NOT_CONTAINS', AttributeValueList: [{S: 'a'}, {S: 'a'}]}}, - {a: {ComparisonOperator: 'NULL', AttributeValueList: [{S: 'a'}, {S: 'a'}]}}, - {a: {ComparisonOperator: 'NOT_NULL', AttributeValueList: [{S: 'a'}, {S: 'a'}]}}, - {a: {ComparisonOperator: 'BETWEEN', AttributeValueList: [{S: 'a'}, {S: 'a'}, {S: 'a'}]}}, - ], function(expr, cb) { + { a: { ComparisonOperator: 'EQ' }, b: { ComparisonOperator: 'NULL' }, c: { ComparisonOperator: 'NULL' } }, + { a: { ComparisonOperator: 'EQ' } }, + { a: { ComparisonOperator: 'EQ', AttributeValueList: [] } }, + { a: { ComparisonOperator: 'NE' } }, + { a: { ComparisonOperator: 'LE' } }, + { a: { ComparisonOperator: 'LT' } }, + { a: { ComparisonOperator: 'GE' } }, + { a: { ComparisonOperator: 'GT' } }, + { a: { ComparisonOperator: 'CONTAINS' } }, + { a: { ComparisonOperator: 'NOT_CONTAINS' } }, + { a: { ComparisonOperator: 'BEGINS_WITH' } }, + { a: { ComparisonOperator: 'IN' } }, + { a: { ComparisonOperator: 'BETWEEN' } }, + { a: { ComparisonOperator: 'NULL', AttributeValueList: [ { S: 'a' } ] } }, + { a: { ComparisonOperator: 'NOT_NULL', AttributeValueList: [ { S: 'a' } ] } }, + { a: { ComparisonOperator: 'EQ', AttributeValueList: [ { S: 'a' }, { S: 'a' } ] } }, + { a: { ComparisonOperator: 'NE', AttributeValueList: [ { S: 'a' }, { S: 'a' } ] } }, + { a: { ComparisonOperator: 'LE', AttributeValueList: [ { S: 'a' }, { S: 'a' } ] } }, + { a: { ComparisonOperator: 'LT', AttributeValueList: [ { S: 'a' }, { S: 'a' } ] } }, + { a: { ComparisonOperator: 'GE', AttributeValueList: [ { S: 'a' }, { S: 'a' } ] } }, + { a: { ComparisonOperator: 'GT', AttributeValueList: [ { S: 'a' }, { S: 'a' } ] } }, + { a: { ComparisonOperator: 'CONTAINS', AttributeValueList: [ { S: 'a' }, { S: 'a' } ] } }, + { a: { ComparisonOperator: 'NOT_CONTAINS', AttributeValueList: [ { S: 'a' }, { S: 'a' } ] } }, + { a: { ComparisonOperator: 'NULL', AttributeValueList: [ { S: 'a' }, { S: 'a' } ] } }, + { a: { ComparisonOperator: 'NOT_NULL', AttributeValueList: [ { S: 'a' }, { S: 'a' } ] } }, + { a: { ComparisonOperator: 'BETWEEN', AttributeValueList: [ { S: 'a' }, { S: 'a' }, { S: 'a' } ] } }, + ], function (expr, cb) { assertValidation({ TableName: 'abc', QueryFilter: {}, @@ -623,13 +623,13 @@ describe('query', function() { }, done) }) - it('should return ValidationException for incorrect number of KeyConditions', function(done) { + it('should return ValidationException for incorrect number of KeyConditions', function (done) { async.forEach([ - {KeyConditions: {}}, - {KeyConditions: {a: {ComparisonOperator: 'NULL'}, b: {ComparisonOperator: 'NULL'}, c: {ComparisonOperator: 'NULL'}}}, - {KeyConditionExpression: ':a = a and b = :a and :a = c', ExpressionAttributeValues: {':a': {S: 'a'}}}, - {KeyConditionExpression: '(a > :a and b > :a) and (c > :a and d > :a) and (e > :a and f > :a)', ExpressionAttributeValues: {':a': {S: 'a'}}}, - ], function(queryOpts, cb) { + { KeyConditions: {} }, + { KeyConditions: { a: { ComparisonOperator: 'NULL' }, b: { ComparisonOperator: 'NULL' }, c: { ComparisonOperator: 'NULL' } } }, + { KeyConditionExpression: ':a = a and b = :a and :a = c', ExpressionAttributeValues: { ':a': { S: 'a' } } }, + { KeyConditionExpression: '(a > :a and b > :a) and (c > :a and d > :a) and (e > :a and f > :a)', ExpressionAttributeValues: { ':a': { S: 'a' } } }, + ], function (queryOpts, cb) { assertValidation({ TableName: 'abc', QueryFilter: queryOpts.KeyConditions ? {} : undefined, @@ -640,26 +640,26 @@ describe('query', function() { }, done) }) - it('should return ValidationException for invalid ComparisonOperator types', function(done) { - async.forEach(['QueryFilter', 'KeyConditions'], function(attr, cb) { + it('should return ValidationException for invalid ComparisonOperator types', function (done) { + async.forEach([ 'QueryFilter', 'KeyConditions' ], function (attr, cb) { async.forEach([ 'LT', 'LE', 'GT', 'GE', 'IN', - ], function(cond, cb) { + ], function (cond, cb) { async.forEach([ - [{BOOL: true}], - [{NULL: true}], - [{SS: ['a']}], - [{NS: ['1']}], - [{BS: ['abcd']}], - [{M: {}}], - [{L: []}], - ], function(list, cb) { - var queryOpts = {TableName: 'abc'} - queryOpts[attr] = {a: {ComparisonOperator: cond, AttributeValueList: list}} + [ { BOOL: true } ], + [ { NULL: true } ], + [ { SS: [ 'a' ] } ], + [ { NS: [ '1' ] } ], + [ { BS: [ 'abcd' ] } ], + [ { M: {} } ], + [ { L: [] } ], + ], function (list, cb) { + var queryOpts = { TableName: 'abc' } + queryOpts[attr] = { a: { ComparisonOperator: cond, AttributeValueList: list } } assertValidation(queryOpts, 'One or more parameter values were invalid: ' + 'ComparisonOperator ' + cond + ' is not valid for ' + Object.keys(list[0])[0] + ' AttributeValue type', cb) @@ -668,21 +668,21 @@ describe('query', function() { }, done) }) - it('should return ValidationException for invalid CONTAINS ComparisonOperator types', function(done) { - async.forEach(['QueryFilter', 'KeyConditions'], function(attr, cb) { + it('should return ValidationException for invalid CONTAINS ComparisonOperator types', function (done) { + async.forEach([ 'QueryFilter', 'KeyConditions' ], function (attr, cb) { async.forEach([ 'CONTAINS', 'NOT_CONTAINS', - ], function(cond, cb) { + ], function (cond, cb) { async.forEach([ - [{SS: ['a']}], - [{NS: ['1']}], - [{BS: ['abcd']}], - [{M: {}}], - [{L: []}], - ], function(list, cb) { - var queryOpts = {TableName: 'abc'} - queryOpts[attr] = {a: {ComparisonOperator: cond, AttributeValueList: list}} + [ { SS: [ 'a' ] } ], + [ { NS: [ '1' ] } ], + [ { BS: [ 'abcd' ] } ], + [ { M: {} } ], + [ { L: [] } ], + ], function (list, cb) { + var queryOpts = { TableName: 'abc' } + queryOpts[attr] = { a: { ComparisonOperator: cond, AttributeValueList: list } } assertValidation(queryOpts, 'One or more parameter values were invalid: ' + 'ComparisonOperator ' + cond + ' is not valid for ' + Object.keys(list[0])[0] + ' AttributeValue type', cb) @@ -691,19 +691,19 @@ describe('query', function() { }, done) }) - it('should return ValidationException for invalid BETWEEN ComparisonOperator types', function(done) { - async.forEach(['QueryFilter', 'KeyConditions'], function(attr, cb) { + it('should return ValidationException for invalid BETWEEN ComparisonOperator types', function (done) { + async.forEach([ 'QueryFilter', 'KeyConditions' ], function (attr, cb) { async.forEach([ - [{BOOL: true}, {BOOL: true}], - [{NULL: true}, {NULL: true}], - [{SS: ['a']}, {SS: ['a']}], - [{NS: ['1']}, {NS: ['1']}], - [{BS: ['abcd']}, {BS: ['abcd']}], - [{M: {}}, {M: {}}], - [{L: []}, {L: []}], - ], function(list, cb) { - var queryOpts = {TableName: 'abc'} - queryOpts[attr] = {a: {ComparisonOperator: 'BETWEEN', AttributeValueList: list}} + [ { BOOL: true }, { BOOL: true } ], + [ { NULL: true }, { NULL: true } ], + [ { SS: [ 'a' ] }, { SS: [ 'a' ] } ], + [ { NS: [ '1' ] }, { NS: [ '1' ] } ], + [ { BS: [ 'abcd' ] }, { BS: [ 'abcd' ] } ], + [ { M: {} }, { M: {} } ], + [ { L: [] }, { L: [] } ], + ], function (list, cb) { + var queryOpts = { TableName: 'abc' } + queryOpts[attr] = { a: { ComparisonOperator: 'BETWEEN', AttributeValueList: list } } assertValidation(queryOpts, 'One or more parameter values were invalid: ' + 'ComparisonOperator BETWEEN is not valid for ' + Object.keys(list[0])[0] + ' AttributeValue type', cb) @@ -711,21 +711,21 @@ describe('query', function() { }, done) }) - it('should return ValidationException for invalid BEGINS_WITH ComparisonOperator types', function(done) { - async.forEach(['QueryFilter', 'KeyConditions'], function(attr, cb) { + it('should return ValidationException for invalid BEGINS_WITH ComparisonOperator types', function (done) { + async.forEach([ 'QueryFilter', 'KeyConditions' ], function (attr, cb) { async.forEach([ - [{N: '1'}], + [ { N: '1' } ], // [{B: 'YQ=='}], // B is fine - [{BOOL: true}], - [{NULL: true}], - [{SS: ['a']}], - [{NS: ['1']}], - [{BS: ['abcd']}], - [{M: {}}], - [{L: []}], - ], function(list, cb) { - var queryOpts = {TableName: 'abc'} - queryOpts[attr] = {a: {ComparisonOperator: 'BEGINS_WITH', AttributeValueList: list}} + [ { BOOL: true } ], + [ { NULL: true } ], + [ { SS: [ 'a' ] } ], + [ { NS: [ '1' ] } ], + [ { BS: [ 'abcd' ] } ], + [ { M: {} } ], + [ { L: [] } ], + ], function (list, cb) { + var queryOpts = { TableName: 'abc' } + queryOpts[attr] = { a: { ComparisonOperator: 'BEGINS_WITH', AttributeValueList: list } } assertValidation(queryOpts, 'One or more parameter values were invalid: ' + 'ComparisonOperator BEGINS_WITH is not valid for ' + Object.keys(list[0])[0] + ' AttributeValue type', cb) @@ -733,21 +733,21 @@ describe('query', function() { }, done) }) - it('should return ValidationException if AttributeValueList has different types', function(done) { + it('should return ValidationException if AttributeValueList has different types', function (done) { assertValidation({ TableName: 'abc', - KeyConditions: {a: {ComparisonOperator: 'IN', AttributeValueList: [{S: 'b'}, {N: '1'}]}}, + KeyConditions: { a: { ComparisonOperator: 'IN', AttributeValueList: [ { S: 'b' }, { N: '1' } ] } }, }, 'One or more parameter values were invalid: AttributeValues inside AttributeValueList must be of same type', done) }) - it('should return ValidationException if BETWEEN arguments are in the incorrect order', function(done) { + it('should return ValidationException if BETWEEN arguments are in the incorrect order', function (done) { assertValidation({ TableName: 'abc', - KeyConditions: {a: {ComparisonOperator: 'BETWEEN', AttributeValueList: [{S: 'b'}, {S: 'a'}]}}, + KeyConditions: { a: { ComparisonOperator: 'BETWEEN', AttributeValueList: [ { S: 'b' }, { S: 'a' } ] } }, }, 'The BETWEEN condition was provided a range where the lower bound is greater than the upper bound', done) }) - it('should return ValidationException for empty ExpressionAttributeNames', function(done) { + it('should return ValidationException for empty ExpressionAttributeNames', function (done) { assertValidation({ TableName: 'abc', KeyConditionExpression: '', @@ -756,16 +756,16 @@ describe('query', function() { }, 'ExpressionAttributeNames must not be empty', done) }) - it('should return ValidationException for invalid ExpressionAttributeNames', function(done) { + it('should return ValidationException for invalid ExpressionAttributeNames', function (done) { assertValidation({ TableName: 'abc', KeyConditionExpression: '', - ExpressionAttributeNames: {'a': 'a'}, + ExpressionAttributeNames: { 'a': 'a' }, ExpressionAttributeValues: {}, }, 'ExpressionAttributeNames contains invalid key: Syntax error; key: "a"', done) }) - it('should return ValidationException for empty ExpressionAttributeValues', function(done) { + it('should return ValidationException for empty ExpressionAttributeValues', function (done) { assertValidation({ TableName: 'abc', KeyConditionExpression: '', @@ -773,31 +773,31 @@ describe('query', function() { }, 'ExpressionAttributeValues must not be empty', done) }) - it('should return ValidationException for invalid ExpressionAttributeValues', function(done) { + it('should return ValidationException for invalid ExpressionAttributeValues', function (done) { assertValidation({ TableName: 'abc', KeyConditionExpression: '', - ExpressionAttributeValues: {'a': {S: 'b'}}, + ExpressionAttributeValues: { 'a': { S: 'b' } }, }, 'ExpressionAttributeValues contains invalid key: Syntax error; key: "a"', done) }) - it('should return ValidationException for empty KeyConditionExpression', function(done) { + it('should return ValidationException for empty KeyConditionExpression', function (done) { assertValidation({ TableName: 'abc', KeyConditionExpression: '', FilterExpression: '', ProjectionExpression: '', - ExpressionAttributeValues: {':0': {S: 'b'}}, + ExpressionAttributeValues: { ':0': { S: 'b' } }, }, 'Invalid KeyConditionExpression: The expression can not be empty;', done) }) - it('should return ValidationException for syntax errors in KeyConditionExpression', function(done) { + it('should return ValidationException for syntax errors in KeyConditionExpression', function (done) { var expressions = [ 'things are not gonna be ok', 'a > 4', '(size(a))[0] > a', ] - async.forEach(expressions, function(expression, cb) { + async.forEach(expressions, function (expression, cb) { assertValidation({ TableName: 'abc', FilterExpression: '', @@ -806,11 +806,11 @@ describe('query', function() { }, done) }) - it('should return ValidationException for invalid operand types', function(done) { + it('should return ValidationException for invalid operand types', function (done) { var expressions = [ 'attribute_type(a, b)', ] - async.forEach(expressions, function(expression, cb) { + async.forEach(expressions, function (expression, cb) { assertValidation({ TableName: 'abc', FilterExpression: '', @@ -819,64 +819,64 @@ describe('query', function() { }, done) }) - it('should return ValidationException for invalid operand types with attributes', function(done) { + it('should return ValidationException for invalid operand types with attributes', function (done) { var expressions = [ 'attribute_type(a, :a)', ] - async.forEach(expressions, function(expression, cb) { + async.forEach(expressions, function (expression, cb) { assertValidation({ TableName: 'abc', FilterExpression: '', KeyConditionExpression: expression, - ExpressionAttributeValues: {':a': {N: '1'}}, + ExpressionAttributeValues: { ':a': { N: '1' } }, }, /^Invalid KeyConditionExpression: Incorrect operand type for operator or function; operator or function: attribute_type, operand type:/, cb) }, done) }) - it('should return ValidationException for empty FilterExpression', function(done) { + it('should return ValidationException for empty FilterExpression', function (done) { assertValidation({ TableName: 'abc', KeyConditionExpression: 'attribute_type(a, :a)', FilterExpression: '', ProjectionExpression: '', - ExpressionAttributeValues: {':a': {S: 'N'}}, + ExpressionAttributeValues: { ':a': { S: 'N' } }, }, 'Invalid FilterExpression: The expression can not be empty;', done) }) - it('should return ValidationException for empty ProjectionExpression', function(done) { + it('should return ValidationException for empty ProjectionExpression', function (done) { assertValidation({ TableName: 'abc', KeyConditionExpression: 'attribute_type(a, :a)', FilterExpression: 'a > b', ProjectionExpression: '', - ExpressionAttributeValues: {':a': {S: 'N'}}, + ExpressionAttributeValues: { ':a': { S: 'N' } }, }, 'Invalid ProjectionExpression: The expression can not be empty;', done) }) - it('should return ValidationException for invalid operator', function(done) { + it('should return ValidationException for invalid operator', function (done) { var expressions = [ 'attribute_type(a, :a)', ] - async.forEach(expressions, function(expression, cb) { + async.forEach(expressions, function (expression, cb) { assertValidation({ TableName: 'abc', KeyConditionExpression: expression, - ExpressionAttributeValues: {':a': {S: 'S'}}, + ExpressionAttributeValues: { ':a': { S: 'S' } }, }, 'Invalid operator used in KeyConditionExpression: attribute_type', cb) }, done) }) - it('should return ValidationException for invalid operators', function(done) { + it('should return ValidationException for invalid operators', function (done) { var expressions = [ - ['a > b and size(b) > c or a > c', 'OR'], - ['a in (b, size(c), d)', 'IN'], - ['attribute_exists(a)', 'attribute_exists'], - ['attribute_not_exists(a)', 'attribute_not_exists'], - ['contains(a.d, b)', 'contains'], - ['not a > b', 'NOT'], - ['a <> b', '<>'], + [ 'a > b and size(b) > c or a > c', 'OR' ], + [ 'a in (b, size(c), d)', 'IN' ], + [ 'attribute_exists(a)', 'attribute_exists' ], + [ 'attribute_not_exists(a)', 'attribute_not_exists' ], + [ 'contains(a.d, b)', 'contains' ], + [ 'not a > b', 'NOT' ], + [ 'a <> b', '<>' ], ] - async.forEach(expressions, function(expr, cb) { + async.forEach(expressions, function (expr, cb) { assertValidation({ TableName: 'abc', KeyConditionExpression: expr[0], @@ -884,27 +884,27 @@ describe('query', function() { }, done) }) - it('should return ValidationException no key attribute as first operator', function(done) { + it('should return ValidationException no key attribute as first operator', function (done) { var expressions = [ - [':a between size(b) and size(a) and b > :b', 'BETWEEN'], - ['begins_with(:a, b) and a > :b', 'begins_with'], + [ ':a between size(b) and size(a) and b > :b', 'BETWEEN' ], + [ 'begins_with(:a, b) and a > :b', 'begins_with' ], ] - async.forEach(expressions, function(expr, cb) { + async.forEach(expressions, function (expr, cb) { assertValidation({ TableName: 'abc', KeyConditionExpression: expr[0], - ExpressionAttributeValues: {':a': {S: '1'}, ':b': {S: '1'}}, + ExpressionAttributeValues: { ':a': { S: '1' }, ':b': { S: '1' } }, }, 'Invalid condition in KeyConditionExpression: ' + expr[1] + ' operator must have the key attribute as its first operand', cb) }, done) }) - it('should return ValidationException for nested operations', function(done) { + it('should return ValidationException for nested operations', function (done) { var expressions = [ 'size(b) > a AND a.b > b AND b > c', 'a > size(b.d)', 'a between size(b) and size(a)', ] - async.forEach(expressions, function(expression, cb) { + async.forEach(expressions, function (expression, cb) { assertValidation({ TableName: 'abc', KeyConditionExpression: expression, @@ -912,14 +912,14 @@ describe('query', function() { }, done) }) - it('should return ValidationException for multiple attribute names', function(done) { + it('should return ValidationException for multiple attribute names', function (done) { var expressions = [ 'b > a.b', 'b between c[1] and d', 'a between b and size(a)', 'begins_with(a, b)', ] - async.forEach(expressions, function(expression, cb) { + async.forEach(expressions, function (expression, cb) { assertValidation({ TableName: 'abc', KeyConditionExpression: expression, @@ -927,13 +927,13 @@ describe('query', function() { }, done) }) - it('should return ValidationException for nested attributes', function(done) { + it('should return ValidationException for nested attributes', function (done) { var expressions = [ 'b.d > a AND c.d > e.f', 'a.d > c', 'b[0] > a', ] - async.forEach(expressions, function(expression, cb) { + async.forEach(expressions, function (expression, cb) { assertValidation({ TableName: 'abc', KeyConditionExpression: expression, @@ -941,63 +941,63 @@ describe('query', function() { }, done) }) - it('should return ValidationException for no key attribute', function(done) { + it('should return ValidationException for no key attribute', function (done) { var expressions = [ ':b > :a AND a < :b', ':a > b AND :a < :b', ] - async.forEach(expressions, function(expression, cb) { + async.forEach(expressions, function (expression, cb) { assertValidation({ TableName: 'abc', KeyConditionExpression: expression, - ExpressionAttributeValues: {':a': {N: '1'}, ':b': {N: '1'}}, + ExpressionAttributeValues: { ':a': { N: '1' }, ':b': { N: '1' } }, }, 'Invalid condition in KeyConditionExpression: No key attribute specified', cb) }, done) }) - it('should return ValidationException for multiple conditions per key', function(done) { + it('should return ValidationException for multiple conditions per key', function (done) { var expressions = [ 'b > :a AND b < :a and c = :a and d = :a', '(a > :a and b > :a) and (b > :a and c > :a)', ] - async.forEach(expressions, function(expression, cb) { + async.forEach(expressions, function (expression, cb) { assertValidation({ TableName: 'abc', KeyConditionExpression: expression, - ExpressionAttributeValues: {':a': {N: '1'}}, + ExpressionAttributeValues: { ':a': { N: '1' } }, }, 'KeyConditionExpressions must only contain one condition per key', cb) }, done) }) - it('should return ValidationException if KeyConditionExpression BETWEEN args have different types', function(done) { + it('should return ValidationException if KeyConditionExpression BETWEEN args have different types', function (done) { assertValidation({ TableName: 'abc', KeyConditionExpression: 'a between :b and :a', - ExpressionAttributeValues: {':a': {S: 'a'}, ':b': {N: '1'}}, + ExpressionAttributeValues: { ':a': { S: 'a' }, ':b': { N: '1' } }, }, 'Invalid KeyConditionExpression: The BETWEEN operator requires same data type for lower and upper bounds; ' + 'lower bound operand: AttributeValue: {N:1}, upper bound operand: AttributeValue: {S:a}', done) }) - it('should return ValidationException if KeyConditionExpression BETWEEN args are in the incorrect order', function(done) { + it('should return ValidationException if KeyConditionExpression BETWEEN args are in the incorrect order', function (done) { assertValidation({ TableName: 'abc', KeyConditionExpression: 'a between :b and :a', - ExpressionAttributeValues: {':a': {S: 'a'}, ':b': {S: 'b'}}, + ExpressionAttributeValues: { ':a': { S: 'a' }, ':b': { S: 'b' } }, }, 'Invalid KeyConditionExpression: The BETWEEN operator requires upper bound to be greater than or equal to lower bound; ' + 'lower bound operand: AttributeValue: {S:b}, upper bound operand: AttributeValue: {S:a}', done) }) - it('should check table exists before checking key validity', function(done) { + it('should check table exists before checking key validity', function (done) { async.forEach([ - {KeyConditions: {z: {ComparisonOperator: 'NULL'}}, QueryFilter: {}}, - {KeyConditionExpression: 'z = :a', ExpressionAttributeValues: {':a': {N: '1'}}}, - {KeyConditionExpression: 'b between :a and :b', ExpressionAttributeValues: {':a': {N: '1'}, ':b': {N: '1'}}}, - ], function(keyOpts, cb) { + { KeyConditions: { z: { ComparisonOperator: 'NULL' } }, QueryFilter: {} }, + { KeyConditionExpression: 'z = :a', ExpressionAttributeValues: { ':a': { N: '1' } } }, + { KeyConditionExpression: 'b between :a and :b', ExpressionAttributeValues: { ':a': { N: '1' }, ':b': { N: '1' } } }, + ], function (keyOpts, cb) { async.forEach([ {}, - {b: {S: 'a'}}, - {a: {S: 'a'}, b: {S: 'a'}}, - ], function(expr, cb) { + { b: { S: 'a' } }, + { a: { S: 'a' }, b: { S: 'a' } }, + ], function (expr, cb) { assertNotFound({ TableName: 'abc', ExclusiveStartKey: expr, @@ -1010,40 +1010,40 @@ describe('query', function() { }, done) }) - it('should return ValidationException for non-existent index name', function(done) { + it('should return ValidationException for non-existent index name', function (done) { async.forEach([ helpers.testHashTable, helpers.testRangeTable, - ], function(table, cb) { + ], function (table, cb) { assertValidation({ TableName: table, IndexName: 'whatever', ExclusiveStartKey: {}, - KeyConditions: {z: {ComparisonOperator: 'NULL'}}, + KeyConditions: { z: { ComparisonOperator: 'NULL' } }, }, 'The table does not have the specified index: whatever', cb) }, done) }) - it('should return ValidationException for querying global index with ConsistentRead', function(done) { + it('should return ValidationException for querying global index with ConsistentRead', function (done) { assertValidation({ TableName: helpers.testRangeTable, IndexName: 'index3', ConsistentRead: true, ExclusiveStartKey: {}, - KeyConditions: {z: {ComparisonOperator: 'NULL'}}, + KeyConditions: { z: { ComparisonOperator: 'NULL' } }, }, 'Consistent reads are not supported on global secondary indexes', done) }) - it('should return ValidationException if ExclusiveStartKey is invalid', function(done) { + it('should return ValidationException if ExclusiveStartKey is invalid', function (done) { async.forEach([ - {KeyConditions: {z: {ComparisonOperator: 'NULL'}}, QueryFilter: {}}, - {KeyConditionExpression: 'z = :a', ExpressionAttributeValues: {':a': {N: '1'}}}, - ], function(keyOpts, cb) { + { KeyConditions: { z: { ComparisonOperator: 'NULL' } }, QueryFilter: {} }, + { KeyConditionExpression: 'z = :a', ExpressionAttributeValues: { ':a': { N: '1' } } }, + ], function (keyOpts, cb) { async.forEach([ {}, - {b: {S: 'a'}}, - {a: {S: 'a'}, b: {S: 'a'}}, - ], function(expr, cb) { + { b: { S: 'a' } }, + { a: { S: 'a' }, b: { S: 'a' } }, + ], function (expr, cb) { assertValidation({ TableName: helpers.testHashTable, ExclusiveStartKey: expr, @@ -1056,20 +1056,20 @@ describe('query', function() { }, done) }) - it('should return ValidationException if ExclusiveStartKey for range table is invalid', function(done) { + it('should return ValidationException if ExclusiveStartKey for range table is invalid', function (done) { async.forEach([ - {KeyConditions: {z: {ComparisonOperator: 'NULL'}}, QueryFilter: {}}, - {KeyConditionExpression: 'z = :a', ExpressionAttributeValues: {':a': {N: '1'}}}, - ], function(keyOpts, cb) { + { KeyConditions: { z: { ComparisonOperator: 'NULL' } }, QueryFilter: {} }, + { KeyConditionExpression: 'z = :a', ExpressionAttributeValues: { ':a': { N: '1' } } }, + ], function (keyOpts, cb) { async.forEach([ {}, - {z: {N: '1'}}, - {b: {S: 'a'}, c: {S: 'b'}}, - {a: {B: 'abcd'}}, - {a: {S: 'a'}}, - {a: {N: '1'}, b: {S: 'a'}, c: {S: 'b'}}, - {a: {N: '1'}, b: {N: '1'}, z: {N: '1'}}, - ], function(expr, cb) { + { z: { N: '1' } }, + { b: { S: 'a' }, c: { S: 'b' } }, + { a: { B: 'abcd' } }, + { a: { S: 'a' } }, + { a: { N: '1' }, b: { S: 'a' }, c: { S: 'b' } }, + { a: { N: '1' }, b: { N: '1' }, z: { N: '1' } }, + ], function (expr, cb) { assertValidation({ TableName: helpers.testRangeTable, ExclusiveStartKey: expr, @@ -1082,20 +1082,20 @@ describe('query', function() { }, done) }) - it('should return ValidationException if ExclusiveStartKey is invalid for local index', function(done) { + it('should return ValidationException if ExclusiveStartKey is invalid for local index', function (done) { async.forEach([ - {KeyConditions: {z: {ComparisonOperator: 'NULL'}}, QueryFilter: {}}, - {KeyConditionExpression: 'z = :a', ExpressionAttributeValues: {':a': {N: '1'}}}, - ], function(keyOpts, cb) { + { KeyConditions: { z: { ComparisonOperator: 'NULL' } }, QueryFilter: {} }, + { KeyConditionExpression: 'z = :a', ExpressionAttributeValues: { ':a': { N: '1' } } }, + ], function (keyOpts, cb) { async.forEach([ {}, - {z: {N: '1'}}, - {a: {B: 'abcd'}}, - {a: {S: 'a'}}, - {a: {S: 'a'}, b: {S: 'a'}}, - {a: {S: 'a'}, c: {S: 'a'}}, - {b: {S: 'a'}, c: {S: 'a'}}, - ], function(expr, cb) { + { z: { N: '1' } }, + { a: { B: 'abcd' } }, + { a: { S: 'a' } }, + { a: { S: 'a' }, b: { S: 'a' } }, + { a: { S: 'a' }, c: { S: 'a' } }, + { b: { S: 'a' }, c: { S: 'a' } }, + ], function (expr, cb) { assertValidation({ TableName: helpers.testRangeTable, IndexName: 'index1', @@ -1109,23 +1109,23 @@ describe('query', function() { }, done) }) - it('should return ValidationException if ExclusiveStartKey is invalid for global index', function(done) { + it('should return ValidationException if ExclusiveStartKey is invalid for global index', function (done) { async.forEach([ - {KeyConditions: {z: {ComparisonOperator: 'NULL'}}, QueryFilter: {}}, - {KeyConditionExpression: 'z = :a', ExpressionAttributeValues: {':a': {N: '1'}}}, - ], function(keyOpts, cb) { + { KeyConditions: { z: { ComparisonOperator: 'NULL' } }, QueryFilter: {} }, + { KeyConditionExpression: 'z = :a', ExpressionAttributeValues: { ':a': { N: '1' } } }, + ], function (keyOpts, cb) { async.forEach([ {}, - {z: {N: '1'}}, - {a: {B: 'abcd'}}, - {a: {S: 'a'}}, - {a: {S: 'a'}, b: {S: 'a'}}, - {a: {S: 'a'}, c: {S: 'a'}}, - {a: {S: 'a'}, b: {S: 'a'}, z: {S: 'a'}}, - {a: {S: 'a'}, b: {S: 'a'}, c: {S: 'a'}, z: {S: 'a'}}, - {c: {N: '1'}}, - {c: {S: '1'}}, - ], function(expr, cb) { + { z: { N: '1' } }, + { a: { B: 'abcd' } }, + { a: { S: 'a' } }, + { a: { S: 'a' }, b: { S: 'a' } }, + { a: { S: 'a' }, c: { S: 'a' } }, + { a: { S: 'a' }, b: { S: 'a' }, z: { S: 'a' } }, + { a: { S: 'a' }, b: { S: 'a' }, c: { S: 'a' }, z: { S: 'a' } }, + { c: { N: '1' } }, + { c: { S: '1' } }, + ], function (expr, cb) { assertValidation({ TableName: helpers.testRangeTable, IndexName: 'index3', @@ -1139,22 +1139,22 @@ describe('query', function() { }, done) }) - it('should return ValidationException if ExclusiveStartKey does not match hash schema', function(done) { + it('should return ValidationException if ExclusiveStartKey does not match hash schema', function (done) { async.forEach([ - {KeyConditions: {z: {ComparisonOperator: 'NULL'}}, QueryFilter: {}}, - {KeyConditionExpression: 'z = :a', ExpressionAttributeValues: {':a': {N: '1'}}}, - ], function(keyOpts, cb) { + { KeyConditions: { z: { ComparisonOperator: 'NULL' } }, QueryFilter: {} }, + { KeyConditionExpression: 'z = :a', ExpressionAttributeValues: { ':a': { N: '1' } } }, + ], function (keyOpts, cb) { async.forEach([ - {a: {B: 'abcd'}}, - {a: {N: '1'}}, - {a: {BOOL: true}}, - {a: {NULL: true}}, - {a: {SS: ['a']}}, - {a: {NS: ['1']}}, - {a: {BS: ['aaaa']}}, - {a: {M: {}}}, - {a: {L: []}}, - ], function(expr, cb) { + { a: { B: 'abcd' } }, + { a: { N: '1' } }, + { a: { BOOL: true } }, + { a: { NULL: true } }, + { a: { SS: [ 'a' ] } }, + { a: { NS: [ '1' ] } }, + { a: { BS: [ 'aaaa' ] } }, + { a: { M: {} } }, + { a: { L: [] } }, + ], function (expr, cb) { assertValidation({ TableName: helpers.testHashTable, ExclusiveStartKey: expr, @@ -1167,15 +1167,15 @@ describe('query', function() { }, done) }) - it('should return ValidationException if ExclusiveStartKey does not match range schema', function(done) { + it('should return ValidationException if ExclusiveStartKey does not match range schema', function (done) { async.forEach([ - {KeyConditions: {z: {ComparisonOperator: 'NULL'}}, QueryFilter: {}}, - {KeyConditionExpression: 'z = :a', ExpressionAttributeValues: {':a': {N: '1'}}}, - ], function(keyOpts, cb) { + { KeyConditions: { z: { ComparisonOperator: 'NULL' } }, QueryFilter: {} }, + { KeyConditionExpression: 'z = :a', ExpressionAttributeValues: { ':a': { N: '1' } } }, + ], function (keyOpts, cb) { async.forEach([ - {a: {N: '1'}, z: {S: 'a'}}, - {a: {B: 'YQ=='}, b: {S: 'a'}}, - ], function(expr, cb) { + { a: { N: '1' }, z: { S: 'a' } }, + { a: { B: 'YQ==' }, b: { S: 'a' } }, + ], function (expr, cb) { assertValidation({ TableName: helpers.testRangeTable, ExclusiveStartKey: expr, @@ -1188,15 +1188,15 @@ describe('query', function() { }, done) }) - it('should return ValidationException if ExclusiveStartKey does not match schema for local index', function(done) { + it('should return ValidationException if ExclusiveStartKey does not match schema for local index', function (done) { async.forEach([ - {KeyConditions: {z: {ComparisonOperator: 'NULL'}}, QueryFilter: {}}, - {KeyConditionExpression: 'z = :a', ExpressionAttributeValues: {':a': {N: '1'}}}, - ], function(keyOpts, cb) { + { KeyConditions: { z: { ComparisonOperator: 'NULL' } }, QueryFilter: {} }, + { KeyConditionExpression: 'z = :a', ExpressionAttributeValues: { ':a': { N: '1' } } }, + ], function (keyOpts, cb) { async.forEach([ - {a: {N: '1'}, x: {S: '1'}, y: {S: '1'}}, - {a: {B: 'YQ=='}, b: {S: '1'}, c: {S: '1'}}, - ], function(expr, cb) { + { a: { N: '1' }, x: { S: '1' }, y: { S: '1' } }, + { a: { B: 'YQ==' }, b: { S: '1' }, c: { S: '1' } }, + ], function (expr, cb) { assertValidation({ TableName: helpers.testRangeTable, IndexName: 'index1', @@ -1210,15 +1210,15 @@ describe('query', function() { }, done) }) - it('should return ValidationException if ExclusiveStartKey does not match schema for global index', function(done) { + it('should return ValidationException if ExclusiveStartKey does not match schema for global index', function (done) { async.forEach([ - {KeyConditions: {z: {ComparisonOperator: 'NULL'}}, QueryFilter: {}}, - {KeyConditionExpression: 'z = :a', ExpressionAttributeValues: {':a': {N: '1'}}}, - ], function(keyOpts, cb) { + { KeyConditions: { z: { ComparisonOperator: 'NULL' } }, QueryFilter: {} }, + { KeyConditionExpression: 'z = :a', ExpressionAttributeValues: { ':a': { N: '1' } } }, + ], function (keyOpts, cb) { async.forEach([ - {x: {S: '1'}, y: {S: '1'}, c: {N: '1'}}, - {a: {S: '1'}, b: {S: '1'}, c: {B: 'YQ=='}}, - ], function(expr, cb) { + { x: { S: '1' }, y: { S: '1' }, c: { N: '1' } }, + { a: { S: '1' }, b: { S: '1' }, c: { B: 'YQ==' } }, + ], function (expr, cb) { assertValidation({ TableName: helpers.testRangeTable, IndexName: 'index3', @@ -1232,17 +1232,17 @@ describe('query', function() { }, done) }) - it('should return ValidationException if hash in ExclusiveStartKey but not in query', function(done) { + it('should return ValidationException if hash in ExclusiveStartKey but not in query', function (done) { async.forEach([ undefined, - {a: {S: 'a'}, b: {N: '1'}}, - {a: {S: 'a'}, c: {N: '1'}}, - {a: {S: 'a'}, z: {S: '1'}}, - ], function(expr, cb) { + { a: { S: 'a' }, b: { N: '1' } }, + { a: { S: 'a' }, c: { N: '1' } }, + { a: { S: 'a' }, z: { S: '1' } }, + ], function (expr, cb) { async.forEach([ - {KeyConditions: {z: {ComparisonOperator: 'NULL'}}}, - {KeyConditionExpression: 'z between :a and :b', ExpressionAttributeValues: {':a': {N: '1'}, ':b': {N: '1'}}}, - ], function(keyOpts, cb) { + { KeyConditions: { z: { ComparisonOperator: 'NULL' } } }, + { KeyConditionExpression: 'z between :a and :b', ExpressionAttributeValues: { ':a': { N: '1' }, ':b': { N: '1' } } }, + ], function (keyOpts, cb) { assertValidation({ TableName: helpers.testRangeTable, ExclusiveStartKey: expr, @@ -1254,17 +1254,17 @@ describe('query', function() { }, done) }) - it('should return ValidationException if local hash in ExclusiveStartKey but not in query', function(done) { + it('should return ValidationException if local hash in ExclusiveStartKey but not in query', function (done) { async.forEach([ undefined, - {a: {S: '1'}, b: {N: '1'}, c: {N: '1'}}, - {a: {S: 'a'}, b: {S: 'a'}, c: {S: 'a'}}, - {a: {S: 'a'}, b: {S: 'a'}, z: {S: 'a'}}, - ], function(expr, cb) { + { a: { S: '1' }, b: { N: '1' }, c: { N: '1' } }, + { a: { S: 'a' }, b: { S: 'a' }, c: { S: 'a' } }, + { a: { S: 'a' }, b: { S: 'a' }, z: { S: 'a' } }, + ], function (expr, cb) { async.forEach([ - {KeyConditions: {z: {ComparisonOperator: 'NULL'}}}, - {KeyConditionExpression: 'z between :a and :b', ExpressionAttributeValues: {':a': {N: '1'}, ':b': {N: '1'}}}, - ], function(keyOpts, cb) { + { KeyConditions: { z: { ComparisonOperator: 'NULL' } } }, + { KeyConditionExpression: 'z between :a and :b', ExpressionAttributeValues: { ':a': { N: '1' }, ':b': { N: '1' } } }, + ], function (keyOpts, cb) { assertValidation({ TableName: helpers.testRangeTable, IndexName: 'index1', @@ -1277,17 +1277,17 @@ describe('query', function() { }, done) }) - it('should return ValidationException if global hash in ExclusiveStartKey but not in query', function(done) { + it('should return ValidationException if global hash in ExclusiveStartKey but not in query', function (done) { async.forEach([ undefined, - {x: {N: '1'}, y: {N: '1'}, c: {S: '1'}}, - {a: {N: '1'}, b: {N: '1'}, c: {S: '1'}}, - {a: {S: 'a'}, b: {S: 'a'}, c: {S: 'a'}}, - ], function(expr, cb) { + { x: { N: '1' }, y: { N: '1' }, c: { S: '1' } }, + { a: { N: '1' }, b: { N: '1' }, c: { S: '1' } }, + { a: { S: 'a' }, b: { S: 'a' }, c: { S: 'a' } }, + ], function (expr, cb) { async.forEach([ - {KeyConditions: {z: {ComparisonOperator: 'NULL'}}}, - {KeyConditionExpression: 'z between :a and :b', ExpressionAttributeValues: {':a': {N: '1'}, ':b': {N: '1'}}}, - ], function(keyOpts, cb) { + { KeyConditions: { z: { ComparisonOperator: 'NULL' } } }, + { KeyConditionExpression: 'z between :a and :b', ExpressionAttributeValues: { ':a': { N: '1' }, ':b': { N: '1' } } }, + ], function (keyOpts, cb) { assertValidation({ TableName: helpers.testRangeTable, IndexName: 'index3', @@ -1300,17 +1300,17 @@ describe('query', function() { }, done) }) - it('should return ValidationException if range in ExclusiveStartKey is invalid', function(done) { + it('should return ValidationException if range in ExclusiveStartKey is invalid', function (done) { async.forEach([ - {a: {S: 'a'}}, - {a: {S: 'a'}, c: {N: '1'}}, - {a: {S: 'a'}, z: {S: '1'}}, - {a: {S: 'a'}, b: {S: '1'}, c: {S: '1'}}, - ], function(expr, cb) { + { a: { S: 'a' } }, + { a: { S: 'a' }, c: { N: '1' } }, + { a: { S: 'a' }, z: { S: '1' } }, + { a: { S: 'a' }, b: { S: '1' }, c: { S: '1' } }, + ], function (expr, cb) { async.forEach([ - {KeyConditions: {a: {ComparisonOperator: 'EQ', AttributeValueList: [{S: 'b'}]}}}, - {KeyConditionExpression: 'a = :a', ExpressionAttributeValues: {':a': {S: 'b'}}}, - ], function(keyOpts, cb) { + { KeyConditions: { a: { ComparisonOperator: 'EQ', AttributeValueList: [ { S: 'b' } ] } } }, + { KeyConditionExpression: 'a = :a', ExpressionAttributeValues: { ':a': { S: 'b' } } }, + ], function (keyOpts, cb) { assertValidation({ TableName: helpers.testRangeTable, ExclusiveStartKey: expr, @@ -1322,17 +1322,17 @@ describe('query', function() { }, done) }) - it('should return ValidationException if local range in ExclusiveStartKey is invalid', function(done) { + it('should return ValidationException if local range in ExclusiveStartKey is invalid', function (done) { async.forEach([ - {a: {S: 'a'}}, - {a: {S: 'a'}, c: {N: '1'}}, - {a: {S: 'a'}, z: {S: '1'}}, - {a: {S: 'a'}, b: {S: '1'}, c: {S: '1'}, d: {S: '1'}}, - ], function(expr, cb) { + { a: { S: 'a' } }, + { a: { S: 'a' }, c: { N: '1' } }, + { a: { S: 'a' }, z: { S: '1' } }, + { a: { S: 'a' }, b: { S: '1' }, c: { S: '1' }, d: { S: '1' } }, + ], function (expr, cb) { async.forEach([ - {KeyConditions: {a: {ComparisonOperator: 'EQ', AttributeValueList: [{S: 'b'}]}}}, - {KeyConditionExpression: 'a = :a', ExpressionAttributeValues: {':a': {S: 'b'}}}, - ], function(keyOpts, cb) { + { KeyConditions: { a: { ComparisonOperator: 'EQ', AttributeValueList: [ { S: 'b' } ] } } }, + { KeyConditionExpression: 'a = :a', ExpressionAttributeValues: { ':a': { S: 'b' } } }, + ], function (keyOpts, cb) { assertValidation({ TableName: helpers.testRangeTable, IndexName: 'index1', @@ -1345,18 +1345,18 @@ describe('query', function() { }, done) }) - it('should return ValidationException if global range in ExclusiveStartKey is invalid', function(done) { + it('should return ValidationException if global range in ExclusiveStartKey is invalid', function (done) { async.forEach([ - {c: {S: '1'}}, - {a: {N: '1'}, c: {S: '1'}}, - {a: {N: '1'}, b: {N: '1'}, c: {S: '1'}}, - {a: {N: '1'}, b: {N: '1'}, c: {S: '1'}, e: {N: '1'}}, - {a: {S: 'a'}, b: {S: '1'}, c: {S: '1'}, d: {S: '1'}, e: {S: '1'}}, - ], function(expr, cb) { + { c: { S: '1' } }, + { a: { N: '1' }, c: { S: '1' } }, + { a: { N: '1' }, b: { N: '1' }, c: { S: '1' } }, + { a: { N: '1' }, b: { N: '1' }, c: { S: '1' }, e: { N: '1' } }, + { a: { S: 'a' }, b: { S: '1' }, c: { S: '1' }, d: { S: '1' }, e: { S: '1' } }, + ], function (expr, cb) { async.forEach([ - {KeyConditions: {c: {ComparisonOperator: 'EQ', AttributeValueList: [{S: 'b'}]}}}, - {KeyConditionExpression: 'c = :a', ExpressionAttributeValues: {':a': {S: 'b'}}}, - ], function(keyOpts, cb) { + { KeyConditions: { c: { ComparisonOperator: 'EQ', AttributeValueList: [ { S: 'b' } ] } } }, + { KeyConditionExpression: 'c = :a', ExpressionAttributeValues: { ':a': { S: 'b' } } }, + ], function (keyOpts, cb) { assertValidation({ TableName: helpers.testRangeTable, IndexName: 'index4', @@ -1370,15 +1370,15 @@ describe('query', function() { }, done) }) - it('should return ValidationException if hash in ExclusiveStartKey and KeyConditions but range has incorrect schema', function(done) { + it('should return ValidationException if hash in ExclusiveStartKey and KeyConditions but range has incorrect schema', function (done) { async.forEach([ - {a: {S: 'a'}, b: {N: '1'}}, - {a: {S: 'a'}, b: {B: 'YQ=='}}, - ], function(expr, cb) { + { a: { S: 'a' }, b: { N: '1' } }, + { a: { S: 'a' }, b: { B: 'YQ==' } }, + ], function (expr, cb) { async.forEach([ - {KeyConditions: {a: {ComparisonOperator: 'EQ', AttributeValueList: [{S: 'b'}]}}}, - {KeyConditionExpression: 'a = :a', ExpressionAttributeValues: {':a': {S: 'b'}}}, - ], function(keyOpts, cb) { + { KeyConditions: { a: { ComparisonOperator: 'EQ', AttributeValueList: [ { S: 'b' } ] } } }, + { KeyConditionExpression: 'a = :a', ExpressionAttributeValues: { ':a': { S: 'b' } } }, + ], function (keyOpts, cb) { assertValidation({ TableName: helpers.testRangeTable, ExclusiveStartKey: expr, @@ -1390,17 +1390,17 @@ describe('query', function() { }, done) }) - it('should return ValidationException if hash in ExclusiveStartKey and KeyConditions but local has incorrect schema', function(done) { + it('should return ValidationException if hash in ExclusiveStartKey and KeyConditions but local has incorrect schema', function (done) { async.forEach([ - {a: {S: 'a'}, b: {N: '1'}, c: {N: '1'}}, - {a: {S: 'a'}, b: {B: 'YQ=='}, c: {N: '1'}}, - {a: {S: 'a'}, b: {S: 'a'}, c: {N: '1'}}, - {a: {S: 'a'}, b: {S: 'a'}, c: {B: 'YQ=='}}, - ], function(expr, cb) { + { a: { S: 'a' }, b: { N: '1' }, c: { N: '1' } }, + { a: { S: 'a' }, b: { B: 'YQ==' }, c: { N: '1' } }, + { a: { S: 'a' }, b: { S: 'a' }, c: { N: '1' } }, + { a: { S: 'a' }, b: { S: 'a' }, c: { B: 'YQ==' } }, + ], function (expr, cb) { async.forEach([ - {KeyConditions: {a: {ComparisonOperator: 'EQ', AttributeValueList: [{S: 'b'}]}}}, - {KeyConditionExpression: 'a = :a', ExpressionAttributeValues: {':a': {S: 'b'}}}, - ], function(keyOpts, cb) { + { KeyConditions: { a: { ComparisonOperator: 'EQ', AttributeValueList: [ { S: 'b' } ] } } }, + { KeyConditionExpression: 'a = :a', ExpressionAttributeValues: { ':a': { S: 'b' } } }, + ], function (keyOpts, cb) { assertValidation({ TableName: helpers.testRangeTable, IndexName: 'index1', @@ -1413,15 +1413,15 @@ describe('query', function() { }, done) }) - it('should return ValidationException if range in ExclusiveStartKey is invalid, but hash and local are ok', function(done) { + it('should return ValidationException if range in ExclusiveStartKey is invalid, but hash and local are ok', function (done) { async.forEach([ - {a: {S: '1'}, b: {N: '1'}, c: {S: 'a'}}, - {a: {S: '1'}, b: {B: 'YQ=='}, c: {S: 'a'}}, - ], function(expr, cb) { + { a: { S: '1' }, b: { N: '1' }, c: { S: 'a' } }, + { a: { S: '1' }, b: { B: 'YQ==' }, c: { S: 'a' } }, + ], function (expr, cb) { async.forEach([ - {KeyConditions: {a: {ComparisonOperator: 'EQ', AttributeValueList: [{S: 'b'}]}}}, - {KeyConditionExpression: 'a = :a', ExpressionAttributeValues: {':a': {S: 'b'}}}, - ], function(keyOpts, cb) { + { KeyConditions: { a: { ComparisonOperator: 'EQ', AttributeValueList: [ { S: 'b' } ] } } }, + { KeyConditionExpression: 'a = :a', ExpressionAttributeValues: { ':a': { S: 'b' } } }, + ], function (keyOpts, cb) { assertValidation({ TableName: helpers.testRangeTable, IndexName: 'index1', @@ -1434,16 +1434,16 @@ describe('query', function() { }, done) }) - it('should return ValidationException if global hash in ExclusiveStartKey but bad in query', function(done) { + it('should return ValidationException if global hash in ExclusiveStartKey but bad in query', function (done) { async.forEach([ - {x: {N: '1'}, y: {N: '1'}, c: {S: 'a'}}, - {a: {N: '1'}, b: {S: '1'}, c: {S: 'a'}}, - {a: {S: '1'}, b: {N: '1'}, c: {S: 'a'}}, - ], function(expr, cb) { + { x: { N: '1' }, y: { N: '1' }, c: { S: 'a' } }, + { a: { N: '1' }, b: { S: '1' }, c: { S: 'a' } }, + { a: { S: '1' }, b: { N: '1' }, c: { S: 'a' } }, + ], function (expr, cb) { async.forEach([ - {KeyConditions: {c: {ComparisonOperator: 'EQ', AttributeValueList: [{S: 'b'}]}}}, - {KeyConditionExpression: 'c = :a', ExpressionAttributeValues: {':a': {S: 'b'}}}, - ], function(keyOpts, cb) { + { KeyConditions: { c: { ComparisonOperator: 'EQ', AttributeValueList: [ { S: 'b' } ] } } }, + { KeyConditionExpression: 'c = :a', ExpressionAttributeValues: { ':a': { S: 'b' } } }, + ], function (keyOpts, cb) { assertValidation({ TableName: helpers.testRangeTable, IndexName: 'index3', @@ -1456,16 +1456,16 @@ describe('query', function() { }, done) }) - it('should return ValidationException if global range in ExclusiveStartKey but bad in query', function(done) { + it('should return ValidationException if global range in ExclusiveStartKey but bad in query', function (done) { async.forEach([ - {x: {N: '1'}, y: {N: '1'}, c: {S: 'a'}, d: {S: 'a'}}, - {a: {N: '1'}, b: {S: '1'}, c: {S: 'a'}, d: {S: 'a'}}, - {a: {S: '1'}, b: {N: '1'}, c: {S: 'a'}, d: {S: 'a'}}, - ], function(expr, cb) { + { x: { N: '1' }, y: { N: '1' }, c: { S: 'a' }, d: { S: 'a' } }, + { a: { N: '1' }, b: { S: '1' }, c: { S: 'a' }, d: { S: 'a' } }, + { a: { S: '1' }, b: { N: '1' }, c: { S: 'a' }, d: { S: 'a' } }, + ], function (expr, cb) { async.forEach([ - {KeyConditions: {c: {ComparisonOperator: 'EQ', AttributeValueList: [{S: 'b'}]}}}, - {KeyConditionExpression: 'c = :a', ExpressionAttributeValues: {':a': {S: 'b'}}}, - ], function(keyOpts, cb) { + { KeyConditions: { c: { ComparisonOperator: 'EQ', AttributeValueList: [ { S: 'b' } ] } } }, + { KeyConditionExpression: 'c = :a', ExpressionAttributeValues: { ':a': { S: 'b' } } }, + ], function (keyOpts, cb) { assertValidation({ TableName: helpers.testRangeTable, IndexName: 'index4', @@ -1478,14 +1478,14 @@ describe('query', function() { }, done) }) - it('should return ValidationException for missing range element', function(done) { + it('should return ValidationException for missing range element', function (done) { async.forEach([ - {KeyConditions: {a: {ComparisonOperator: 'EQ', AttributeValueList: [{S: 'b'}]}, c: {ComparisonOperator: 'NULL'}}}, - {KeyConditionExpression: 'a = :a and c = :b', ExpressionAttributeValues: {':a': {S: 'b'}, ':b': {N: '1'}}}, - ], function(keyOpts, cb) { + { KeyConditions: { a: { ComparisonOperator: 'EQ', AttributeValueList: [ { S: 'b' } ] }, c: { ComparisonOperator: 'NULL' } } }, + { KeyConditionExpression: 'a = :a and c = :b', ExpressionAttributeValues: { ':a': { S: 'b' }, ':b': { N: '1' } } }, + ], function (keyOpts, cb) { assertValidation({ TableName: helpers.testRangeTable, - ExclusiveStartKey: {a: {S: 'a'}, b: {S: 'a'}}, + ExclusiveStartKey: { a: { S: 'a' }, b: { S: 'a' } }, KeyConditions: keyOpts.KeyConditions, KeyConditionExpression: keyOpts.KeyConditionExpression, ExpressionAttributeValues: keyOpts.ExpressionAttributeValues, @@ -1493,15 +1493,15 @@ describe('query', function() { }, done) }) - it('should return ValidationException for ExclusiveStartKey with local index and missing part', function(done) { + it('should return ValidationException for ExclusiveStartKey with local index and missing part', function (done) { async.forEach([ - {KeyConditions: {a: {ComparisonOperator: 'EQ', AttributeValueList: [{S: 'b'}]}, b: {ComparisonOperator: 'NULL'}}}, - {KeyConditionExpression: 'a = :a and b = :b', ExpressionAttributeValues: {':a': {S: 'b'}, ':b': {N: '1'}}}, - ], function(keyOpts, cb) { + { KeyConditions: { a: { ComparisonOperator: 'EQ', AttributeValueList: [ { S: 'b' } ] }, b: { ComparisonOperator: 'NULL' } } }, + { KeyConditionExpression: 'a = :a and b = :b', ExpressionAttributeValues: { ':a': { S: 'b' }, ':b': { N: '1' } } }, + ], function (keyOpts, cb) { assertValidation({ TableName: helpers.testRangeTable, IndexName: 'index1', - ExclusiveStartKey: {a: {S: 'a'}, b: {S: 'a'}, c: {S: 'a'}}, + ExclusiveStartKey: { a: { S: 'a' }, b: { S: 'a' }, c: { S: 'a' } }, KeyConditions: keyOpts.KeyConditions, KeyConditionExpression: keyOpts.KeyConditionExpression, ExpressionAttributeValues: keyOpts.ExpressionAttributeValues, @@ -1509,16 +1509,16 @@ describe('query', function() { }, done) }) - it('should return ValidationException for ExclusiveStartKey with global index and missing part', function(done) { + it('should return ValidationException for ExclusiveStartKey with global index and missing part', function (done) { async.forEach([ - {KeyConditions: {c: {ComparisonOperator: 'EQ', AttributeValueList: [{S: 'b'}]}, b: {ComparisonOperator: 'NULL'}}}, - {KeyConditionExpression: 'c = :a and b = :b', ExpressionAttributeValues: {':a': {S: 'b'}, ':b': {N: '1'}}}, - ], function(keyOpts, cb) { + { KeyConditions: { c: { ComparisonOperator: 'EQ', AttributeValueList: [ { S: 'b' } ] }, b: { ComparisonOperator: 'NULL' } } }, + { KeyConditionExpression: 'c = :a and b = :b', ExpressionAttributeValues: { ':a': { S: 'b' }, ':b': { N: '1' } } }, + ], function (keyOpts, cb) { assertValidation({ TableName: helpers.testRangeTable, IndexName: 'index4', Select: 'ALL_ATTRIBUTES', - ExclusiveStartKey: {a: {S: 'a'}, b: {S: 'a'}, c: {S: 'a'}, d: {S: 'a'}}, + ExclusiveStartKey: { a: { S: 'a' }, b: { S: 'a' }, c: { S: 'a' }, d: { S: 'a' } }, KeyConditions: keyOpts.KeyConditions, KeyConditionExpression: keyOpts.KeyConditionExpression, ExpressionAttributeValues: keyOpts.ExpressionAttributeValues, @@ -1526,80 +1526,80 @@ describe('query', function() { }, done) }) - it('should return ValidationException if querying with non-indexable operations', function(done) { + it('should return ValidationException if querying with non-indexable operations', function (done) { async.forEach([ - {ComparisonOperator: 'NULL'}, - {ComparisonOperator: 'NOT_NULL'}, - {ComparisonOperator: 'NE', AttributeValueList: [{N: '1'}]}, - {ComparisonOperator: 'CONTAINS', AttributeValueList: [{S: 'a'}]}, - {ComparisonOperator: 'NOT_CONTAINS', AttributeValueList: [{S: 'a'}]}, - {ComparisonOperator: 'IN', AttributeValueList: [{S: 'a'}]}, - ], function(keyOpts, cb) { + { ComparisonOperator: 'NULL' }, + { ComparisonOperator: 'NOT_NULL' }, + { ComparisonOperator: 'NE', AttributeValueList: [ { N: '1' } ] }, + { ComparisonOperator: 'CONTAINS', AttributeValueList: [ { S: 'a' } ] }, + { ComparisonOperator: 'NOT_CONTAINS', AttributeValueList: [ { S: 'a' } ] }, + { ComparisonOperator: 'IN', AttributeValueList: [ { S: 'a' } ] }, + ], function (keyOpts, cb) { assertValidation({ TableName: helpers.testHashTable, - KeyConditions: {a: keyOpts}, + KeyConditions: { a: keyOpts }, }, 'Attempted conditional constraint is not an indexable operation', cb) }, done) }) - it('should return ValidationException for unsupported comparison on range', function(done) { + it('should return ValidationException for unsupported comparison on range', function (done) { async.forEach([ - {ComparisonOperator: 'NULL'}, - {ComparisonOperator: 'NOT_NULL'}, - {ComparisonOperator: 'CONTAINS', AttributeValueList: [{S: 'a'}]}, - {ComparisonOperator: 'NOT_CONTAINS', AttributeValueList: [{S: 'a'}]}, - {ComparisonOperator: 'IN', AttributeValueList: [{S: 'a'}]}, - ], function(keyOpts, cb) { + { ComparisonOperator: 'NULL' }, + { ComparisonOperator: 'NOT_NULL' }, + { ComparisonOperator: 'CONTAINS', AttributeValueList: [ { S: 'a' } ] }, + { ComparisonOperator: 'NOT_CONTAINS', AttributeValueList: [ { S: 'a' } ] }, + { ComparisonOperator: 'IN', AttributeValueList: [ { S: 'a' } ] }, + ], function (keyOpts, cb) { assertValidation({ TableName: helpers.testRangeTable, - ExclusiveStartKey: {a: {S: 'a'}, b: {S: 'a'}}, - KeyConditions: {a: {ComparisonOperator: 'EQ', AttributeValueList: [{S: 'b'}]}, b: keyOpts}, + ExclusiveStartKey: { a: { S: 'a' }, b: { S: 'a' } }, + KeyConditions: { a: { ComparisonOperator: 'EQ', AttributeValueList: [ { S: 'b' } ] }, b: keyOpts }, }, 'Attempted conditional constraint is not an indexable operation', cb) }, done) }) - it('should return ValidationException for incorrect comparison operator on index', function(done) { + it('should return ValidationException for incorrect comparison operator on index', function (done) { assertValidation({ TableName: helpers.testRangeTable, IndexName: 'index1', KeyConditions: { - a: {ComparisonOperator: 'EQ', AttributeValueList: [{S: 'a'}]}, - c: {ComparisonOperator: 'NULL'}, - }}, - 'Attempted conditional constraint is not an indexable operation', done) + a: { ComparisonOperator: 'EQ', AttributeValueList: [ { S: 'a' } ] }, + c: { ComparisonOperator: 'NULL' }, + } }, + 'Attempted conditional constraint is not an indexable operation', done) }) - it('should return ValidationException for mismatching param type', function(done) { + it('should return ValidationException for mismatching param type', function (done) { var expressions = [ ':a > a', ] - async.forEach(expressions, function(expression, cb) { + async.forEach(expressions, function (expression, cb) { assertValidation({ TableName: helpers.testHashTable, KeyConditionExpression: expression, - ExpressionAttributeValues: {':a': {N: '1'}}, + ExpressionAttributeValues: { ':a': { N: '1' } }, }, 'One or more parameter values were invalid: Condition parameter type does not match schema type', cb) }, done) }) - it('should return ValidationException if querying with unsupported conditions', function(done) { + it('should return ValidationException if querying with unsupported conditions', function (done) { async.forEach([ - {KeyConditions: {a: {ComparisonOperator: 'EQ', AttributeValueList: [{S: 'a'}]}, b: {ComparisonOperator: 'EQ', AttributeValueList: [{S: 'a'}]}}}, - {KeyConditions: {a: {ComparisonOperator: 'LE', AttributeValueList: [{S: 'a'}]}}}, - {KeyConditions: {a: {ComparisonOperator: 'LT', AttributeValueList: [{S: 'a'}]}}}, - {KeyConditions: {a: {ComparisonOperator: 'GE', AttributeValueList: [{S: 'a'}]}}}, - {KeyConditions: {a: {ComparisonOperator: 'GT', AttributeValueList: [{S: 'a'}]}}}, - {KeyConditions: {a: {ComparisonOperator: 'BEGINS_WITH', AttributeValueList: [{S: 'a'}]}}}, - {KeyConditions: {a: {ComparisonOperator: 'BETWEEN', AttributeValueList: [{S: 'a'}, {S: 'a'}]}}}, - {KeyConditionExpression: 'a > :a', ExpressionAttributeValues: {':a': {S: '1'}}}, - {KeyConditionExpression: 'a < :a', ExpressionAttributeValues: {':a': {S: '1'}}}, - {KeyConditionExpression: ':a <= a', ExpressionAttributeValues: {':a': {S: '1'}}}, - {KeyConditionExpression: ':a >= a', ExpressionAttributeValues: {':a': {S: '1'}}}, - {KeyConditionExpression: 'begins_with(a, :a)', ExpressionAttributeValues: {':a': {S: '1'}}}, - {KeyConditionExpression: 'a between :a and :a', ExpressionAttributeValues: {':a': {S: '1'}}}, - {KeyConditionExpression: 'a = :a AND b = :a', ExpressionAttributeValues: {':a': {S: '1'}}}, - {KeyConditionExpression: 'y = :a and z = :a', ExpressionAttributeValues: {':a': {S: '1'}}}, - ], function(keyOpts, cb) { + { KeyConditions: { a: { ComparisonOperator: 'EQ', AttributeValueList: [ { S: 'a' } ] }, b: { ComparisonOperator: 'EQ', AttributeValueList: [ { S: 'a' } ] } } }, + { KeyConditions: { a: { ComparisonOperator: 'LE', AttributeValueList: [ { S: 'a' } ] } } }, + { KeyConditions: { a: { ComparisonOperator: 'LT', AttributeValueList: [ { S: 'a' } ] } } }, + { KeyConditions: { a: { ComparisonOperator: 'GE', AttributeValueList: [ { S: 'a' } ] } } }, + { KeyConditions: { a: { ComparisonOperator: 'GT', AttributeValueList: [ { S: 'a' } ] } } }, + { KeyConditions: { a: { ComparisonOperator: 'BEGINS_WITH', AttributeValueList: [ { S: 'a' } ] } } }, + { KeyConditions: { a: { ComparisonOperator: 'BETWEEN', AttributeValueList: [ { S: 'a' }, { S: 'a' } ] } } }, + { KeyConditionExpression: 'a > :a', ExpressionAttributeValues: { ':a': { S: '1' } } }, + { KeyConditionExpression: 'a < :a', ExpressionAttributeValues: { ':a': { S: '1' } } }, + { KeyConditionExpression: ':a <= a', ExpressionAttributeValues: { ':a': { S: '1' } } }, + { KeyConditionExpression: ':a >= a', ExpressionAttributeValues: { ':a': { S: '1' } } }, + { KeyConditionExpression: 'begins_with(a, :a)', ExpressionAttributeValues: { ':a': { S: '1' } } }, + { KeyConditionExpression: 'a between :a and :a', ExpressionAttributeValues: { ':a': { S: '1' } } }, + { KeyConditionExpression: 'a = :a AND b = :a', ExpressionAttributeValues: { ':a': { S: '1' } } }, + { KeyConditionExpression: 'y = :a and z = :a', ExpressionAttributeValues: { ':a': { S: '1' } } }, + ], function (keyOpts, cb) { assertValidation({ TableName: helpers.testHashTable, KeyConditions: keyOpts.KeyConditions, @@ -1609,24 +1609,24 @@ describe('query', function() { }, done) }) - it('should return ValidationException if querying global with unsupported conditions', function(done) { + it('should return ValidationException if querying global with unsupported conditions', function (done) { async.forEach([ - {KeyConditions: {c: {ComparisonOperator: 'EQ', AttributeValueList: [{S: 'a'}]}, z: {ComparisonOperator: 'EQ', AttributeValueList: [{S: 'a'}]}}}, - {KeyConditions: {c: {ComparisonOperator: 'LE', AttributeValueList: [{S: 'a'}]}}}, - {KeyConditions: {c: {ComparisonOperator: 'LT', AttributeValueList: [{S: 'a'}]}}}, - {KeyConditions: {c: {ComparisonOperator: 'GE', AttributeValueList: [{S: 'a'}]}}}, - {KeyConditions: {c: {ComparisonOperator: 'GT', AttributeValueList: [{S: 'a'}]}}}, - {KeyConditions: {c: {ComparisonOperator: 'BEGINS_WITH', AttributeValueList: [{S: 'a'}]}}}, - {KeyConditions: {c: {ComparisonOperator: 'BETWEEN', AttributeValueList: [{S: 'a'}, {S: 'a'}]}}}, - {KeyConditionExpression: 'c > :a', ExpressionAttributeValues: {':a': {S: '1'}}}, - {KeyConditionExpression: 'c < :a', ExpressionAttributeValues: {':a': {S: '1'}}}, - {KeyConditionExpression: ':a <= c', ExpressionAttributeValues: {':a': {S: '1'}}}, - {KeyConditionExpression: ':a >= c', ExpressionAttributeValues: {':a': {S: '1'}}}, - {KeyConditionExpression: 'begins_with(c, :a)', ExpressionAttributeValues: {':a': {S: '1'}}}, - {KeyConditionExpression: 'c between :a and :a', ExpressionAttributeValues: {':a': {S: '1'}}}, - {KeyConditionExpression: 'c = :a AND b = :a', ExpressionAttributeValues: {':a': {S: '1'}}}, - {KeyConditionExpression: 'y = :a and z = :a', ExpressionAttributeValues: {':a': {S: '1'}}}, - ], function(keyOpts, cb) { + { KeyConditions: { c: { ComparisonOperator: 'EQ', AttributeValueList: [ { S: 'a' } ] }, z: { ComparisonOperator: 'EQ', AttributeValueList: [ { S: 'a' } ] } } }, + { KeyConditions: { c: { ComparisonOperator: 'LE', AttributeValueList: [ { S: 'a' } ] } } }, + { KeyConditions: { c: { ComparisonOperator: 'LT', AttributeValueList: [ { S: 'a' } ] } } }, + { KeyConditions: { c: { ComparisonOperator: 'GE', AttributeValueList: [ { S: 'a' } ] } } }, + { KeyConditions: { c: { ComparisonOperator: 'GT', AttributeValueList: [ { S: 'a' } ] } } }, + { KeyConditions: { c: { ComparisonOperator: 'BEGINS_WITH', AttributeValueList: [ { S: 'a' } ] } } }, + { KeyConditions: { c: { ComparisonOperator: 'BETWEEN', AttributeValueList: [ { S: 'a' }, { S: 'a' } ] } } }, + { KeyConditionExpression: 'c > :a', ExpressionAttributeValues: { ':a': { S: '1' } } }, + { KeyConditionExpression: 'c < :a', ExpressionAttributeValues: { ':a': { S: '1' } } }, + { KeyConditionExpression: ':a <= c', ExpressionAttributeValues: { ':a': { S: '1' } } }, + { KeyConditionExpression: ':a >= c', ExpressionAttributeValues: { ':a': { S: '1' } } }, + { KeyConditionExpression: 'begins_with(c, :a)', ExpressionAttributeValues: { ':a': { S: '1' } } }, + { KeyConditionExpression: 'c between :a and :a', ExpressionAttributeValues: { ':a': { S: '1' } } }, + { KeyConditionExpression: 'c = :a AND b = :a', ExpressionAttributeValues: { ':a': { S: '1' } } }, + { KeyConditionExpression: 'y = :a and z = :a', ExpressionAttributeValues: { ':a': { S: '1' } } }, + ], function (keyOpts, cb) { assertValidation({ TableName: helpers.testRangeTable, IndexName: 'index3', @@ -1637,14 +1637,14 @@ describe('query', function() { }, done) }) - it('should return ValidationException for ExclusiveStartKey with out-of-bounds hash key', function(done) { + it('should return ValidationException for ExclusiveStartKey with out-of-bounds hash key', function (done) { async.forEach([ - {KeyConditions: {a: {ComparisonOperator: 'EQ', AttributeValueList: [{S: 'b'}]}}}, - {KeyConditionExpression: 'a = :a', ExpressionAttributeValues: {':a': {S: 'b'}}}, - ], function(keyOpts, cb) { + { KeyConditions: { a: { ComparisonOperator: 'EQ', AttributeValueList: [ { S: 'b' } ] } } }, + { KeyConditionExpression: 'a = :a', ExpressionAttributeValues: { ':a': { S: 'b' } } }, + ], function (keyOpts, cb) { assertValidation({ TableName: helpers.testRangeTable, - ExclusiveStartKey: {a: {S: 'a'}, b: {S: 'a'}}, + ExclusiveStartKey: { a: { S: 'a' }, b: { S: 'a' } }, KeyConditions: keyOpts.KeyConditions, KeyConditionExpression: keyOpts.KeyConditionExpression, ExpressionAttributeValues: keyOpts.ExpressionAttributeValues, @@ -1652,15 +1652,15 @@ describe('query', function() { }, done) }) - it('should return ValidationException for ExclusiveStartKey with local index and out-of-bounds hash key', function(done) { + it('should return ValidationException for ExclusiveStartKey with local index and out-of-bounds hash key', function (done) { async.forEach([ - {KeyConditions: {a: {ComparisonOperator: 'EQ', AttributeValueList: [{S: 'b'}]}}}, - {KeyConditionExpression: 'a = :a', ExpressionAttributeValues: {':a': {S: 'b'}}}, - ], function(keyOpts, cb) { + { KeyConditions: { a: { ComparisonOperator: 'EQ', AttributeValueList: [ { S: 'b' } ] } } }, + { KeyConditionExpression: 'a = :a', ExpressionAttributeValues: { ':a': { S: 'b' } } }, + ], function (keyOpts, cb) { assertValidation({ TableName: helpers.testRangeTable, IndexName: 'index1', - ExclusiveStartKey: {a: {S: 'a'}, b: {S: 'a'}, c: {S: 'a'}}, + ExclusiveStartKey: { a: { S: 'a' }, b: { S: 'a' }, c: { S: 'a' } }, KeyConditions: keyOpts.KeyConditions, KeyConditionExpression: keyOpts.KeyConditionExpression, ExpressionAttributeValues: keyOpts.ExpressionAttributeValues, @@ -1668,15 +1668,15 @@ describe('query', function() { }, done) }) - it('should return ValidationException if global hash in ExclusiveStartKey but outside range', function(done) { + it('should return ValidationException if global hash in ExclusiveStartKey but outside range', function (done) { async.forEach([ - {KeyConditions: {c: {ComparisonOperator: 'EQ', AttributeValueList: [{S: 'b'}]}}}, - {KeyConditionExpression: 'c = :a', ExpressionAttributeValues: {':a': {S: 'b'}}}, - ], function(keyOpts, cb) { + { KeyConditions: { c: { ComparisonOperator: 'EQ', AttributeValueList: [ { S: 'b' } ] } } }, + { KeyConditionExpression: 'c = :a', ExpressionAttributeValues: { ':a': { S: 'b' } } }, + ], function (keyOpts, cb) { assertValidation({ TableName: helpers.testRangeTable, IndexName: 'index3', - ExclusiveStartKey: {a: {S: 'a'}, b: {S: 'a'}, c: {S: 'a'}}, + ExclusiveStartKey: { a: { S: 'a' }, b: { S: 'a' }, c: { S: 'a' } }, KeyConditions: keyOpts.KeyConditions, KeyConditionExpression: keyOpts.KeyConditionExpression, ExpressionAttributeValues: keyOpts.ExpressionAttributeValues, @@ -1684,15 +1684,15 @@ describe('query', function() { }, done) }) - it('should return ValidationException if second global hash in ExclusiveStartKey but outside range', function(done) { + it('should return ValidationException if second global hash in ExclusiveStartKey but outside range', function (done) { async.forEach([ - {KeyConditions: {c: {ComparisonOperator: 'EQ', AttributeValueList: [{S: 'b'}]}}}, - {KeyConditionExpression: 'c = :a', ExpressionAttributeValues: {':a': {S: 'b'}}}, - ], function(keyOpts, cb) { + { KeyConditions: { c: { ComparisonOperator: 'EQ', AttributeValueList: [ { S: 'b' } ] } } }, + { KeyConditionExpression: 'c = :a', ExpressionAttributeValues: { ':a': { S: 'b' } } }, + ], function (keyOpts, cb) { assertValidation({ TableName: helpers.testRangeTable, IndexName: 'index4', - ExclusiveStartKey: {a: {S: 'a'}, b: {S: 'a'}, c: {S: 'a'}, d: {S: 'a'}}, + ExclusiveStartKey: { a: { S: 'a' }, b: { S: 'a' }, c: { S: 'a' }, d: { S: 'a' } }, KeyConditions: keyOpts.KeyConditions, KeyConditionExpression: keyOpts.KeyConditionExpression, ExpressionAttributeValues: keyOpts.ExpressionAttributeValues, @@ -1700,19 +1700,19 @@ describe('query', function() { }, done) }) - it('should return ValidationException for ExclusiveStartKey with non-matching range key', function(done) { - async.forEach([{ + it('should return ValidationException for ExclusiveStartKey with non-matching range key', function (done) { + async.forEach([ { KeyConditions: { - a: {ComparisonOperator: 'EQ', AttributeValueList: [{S: 'b'}]}, - b: {ComparisonOperator: 'GT', AttributeValueList: [{S: 'a'}]}, + a: { ComparisonOperator: 'EQ', AttributeValueList: [ { S: 'b' } ] }, + b: { ComparisonOperator: 'GT', AttributeValueList: [ { S: 'a' } ] }, }, }, { KeyConditionExpression: 'a = :a and b > :a', - ExpressionAttributeValues: {':a': {S: 'b'}}, - }], function(keyOpts, cb) { + ExpressionAttributeValues: { ':a': { S: 'b' } }, + } ], function (keyOpts, cb) { assertValidation({ TableName: helpers.testRangeTable, - ExclusiveStartKey: {a: {S: 'a'}, b: {S: 'a'}}, + ExclusiveStartKey: { a: { S: 'a' }, b: { S: 'a' } }, KeyConditions: keyOpts.KeyConditions, KeyConditionExpression: keyOpts.KeyConditionExpression, ExpressionAttributeValues: keyOpts.ExpressionAttributeValues, @@ -1720,20 +1720,20 @@ describe('query', function() { }, done) }) - it('should return ValidationException for ExclusiveStartKey with local index and not matching predicate', function(done) { - async.forEach([{ + it('should return ValidationException for ExclusiveStartKey with local index and not matching predicate', function (done) { + async.forEach([ { KeyConditions: { - a: {ComparisonOperator: 'EQ', AttributeValueList: [{S: 'a'}]}, - c: {ComparisonOperator: 'GT', AttributeValueList: [{S: 'a'}]}, + a: { ComparisonOperator: 'EQ', AttributeValueList: [ { S: 'a' } ] }, + c: { ComparisonOperator: 'GT', AttributeValueList: [ { S: 'a' } ] }, }, }, { KeyConditionExpression: 'a = :a and c > :a', - ExpressionAttributeValues: {':a': {S: 'b'}}, - }], function(keyOpts, cb) { + ExpressionAttributeValues: { ':a': { S: 'b' } }, + } ], function (keyOpts, cb) { assertValidation({ TableName: helpers.testRangeTable, IndexName: 'index1', - ExclusiveStartKey: {a: {S: 'a'}, b: {S: 'a'}, c: {S: 'a'}}, + ExclusiveStartKey: { a: { S: 'a' }, b: { S: 'a' }, c: { S: 'a' } }, KeyConditions: keyOpts.KeyConditions, KeyConditionExpression: keyOpts.KeyConditionExpression, ExpressionAttributeValues: keyOpts.ExpressionAttributeValues, @@ -1741,20 +1741,20 @@ describe('query', function() { }, done) }) - it('should return ValidationException if global hash in ExclusiveStartKey but not matching predicate', function(done) { - async.forEach([{ + it('should return ValidationException if global hash in ExclusiveStartKey but not matching predicate', function (done) { + async.forEach([ { KeyConditions: { - c: {ComparisonOperator: 'EQ', AttributeValueList: [{S: 'a'}]}, - d: {ComparisonOperator: 'GT', AttributeValueList: [{S: 'a'}]}, + c: { ComparisonOperator: 'EQ', AttributeValueList: [ { S: 'a' } ] }, + d: { ComparisonOperator: 'GT', AttributeValueList: [ { S: 'a' } ] }, }, }, { KeyConditionExpression: 'c = :a and d > :a', - ExpressionAttributeValues: {':a': {S: 'b'}}, - }], function(keyOpts, cb) { + ExpressionAttributeValues: { ':a': { S: 'b' } }, + } ], function (keyOpts, cb) { async.forEach([ - {a: {S: 'a'}, b: {S: 'a'}, c: {S: 'a'}, d: {S: 'a'}}, - {a: {S: 'a'}, b: {S: 'a'}, c: {S: 'b'}, d: {S: 'a'}}, - ], function(expr, cb) { + { a: { S: 'a' }, b: { S: 'a' }, c: { S: 'a' }, d: { S: 'a' } }, + { a: { S: 'a' }, b: { S: 'a' }, c: { S: 'b' }, d: { S: 'a' } }, + ], function (expr, cb) { assertValidation({ TableName: helpers.testRangeTable, IndexName: 'index4', @@ -1767,19 +1767,19 @@ describe('query', function() { }, done) }) - it('should return ValidationException for ExclusiveStartKey with matching range but non-matching hash key', function(done) { - async.forEach([{ + it('should return ValidationException for ExclusiveStartKey with matching range but non-matching hash key', function (done) { + async.forEach([ { KeyConditions: { - a: {ComparisonOperator: 'EQ', AttributeValueList: [{S: 'b'}]}, - b: {ComparisonOperator: 'LT', AttributeValueList: [{S: 'b'}]}, + a: { ComparisonOperator: 'EQ', AttributeValueList: [ { S: 'b' } ] }, + b: { ComparisonOperator: 'LT', AttributeValueList: [ { S: 'b' } ] }, }, }, { KeyConditionExpression: 'a = :a and b < :a', - ExpressionAttributeValues: {':a': {S: 'b'}}, - }], function(keyOpts, cb) { + ExpressionAttributeValues: { ':a': { S: 'b' } }, + } ], function (keyOpts, cb) { assertValidation({ TableName: helpers.testRangeTable, - ExclusiveStartKey: {a: {S: 'a'}, b: {S: 'a'}}, + ExclusiveStartKey: { a: { S: 'a' }, b: { S: 'a' } }, KeyConditions: keyOpts.KeyConditions, KeyConditionExpression: keyOpts.KeyConditionExpression, ExpressionAttributeValues: keyOpts.ExpressionAttributeValues, @@ -1787,107 +1787,107 @@ describe('query', function() { }, done) }) - it('should return ValidationException if global hash in ExclusiveStartKey but exact match', function(done) { + it('should return ValidationException if global hash in ExclusiveStartKey but exact match', function (done) { async.forEach([ - {a: {S: 'a'}, b: {S: 'a'}, c: {S: 'c'}, d: {S: 'a'}}, - {a: {S: 'a'}, b: {S: 'a'}, c: {S: 'b'}, d: {S: 'a'}}, - ], function(expr, cb) { + { a: { S: 'a' }, b: { S: 'a' }, c: { S: 'c' }, d: { S: 'a' } }, + { a: { S: 'a' }, b: { S: 'a' }, c: { S: 'b' }, d: { S: 'a' } }, + ], function (expr, cb) { assertValidation({ TableName: helpers.testRangeTable, IndexName: 'index4', ExclusiveStartKey: expr, KeyConditions: { - c: {ComparisonOperator: 'EQ', AttributeValueList: [{S: 'a'}]}, - d: {ComparisonOperator: 'EQ', AttributeValueList: [{S: 'a'}]}, + c: { ComparisonOperator: 'EQ', AttributeValueList: [ { S: 'a' } ] }, + d: { ComparisonOperator: 'EQ', AttributeValueList: [ { S: 'a' } ] }, }, }, 'The query can return at most one row and cannot be restarted', cb) }, done) }) - it('should return ValidationException if hash key in QueryFilter', function(done) { + it('should return ValidationException if hash key in QueryFilter', function (done) { assertValidation({ TableName: helpers.testHashTable, - KeyConditions: {a: {ComparisonOperator: 'EQ', AttributeValueList: [{S: 'a'}]}}, - QueryFilter: {a: {ComparisonOperator: 'EQ', AttributeValueList: [{S: 'a'}]}}, + KeyConditions: { a: { ComparisonOperator: 'EQ', AttributeValueList: [ { S: 'a' } ] } }, + QueryFilter: { a: { ComparisonOperator: 'EQ', AttributeValueList: [ { S: 'a' } ] } }, }, 'QueryFilter can only contain non-primary key attributes: Primary key attribute: a', done) }) - it('should return ValidationException if hash key in FilterExpression', function(done) { + it('should return ValidationException if hash key in FilterExpression', function (done) { async.forEach([ 'attribute_exists(a.b) AND b = :b', 'a = :b', 'a[1] = :b', - ], function(expr, cb) { + ], function (expr, cb) { assertValidation({ TableName: helpers.testHashTable, FilterExpression: expr, KeyConditionExpression: 'a = :a', - ExpressionAttributeValues: {':a': {S: '1'}, ':b': {N: '1'}}, + ExpressionAttributeValues: { ':a': { S: '1' }, ':b': { N: '1' } }, }, 'Filter Expression can only contain non-primary key attributes: Primary key attribute: a', cb) }, done) }) - it('should return ValidationException if range key in QueryFilter', function(done) { + it('should return ValidationException if range key in QueryFilter', function (done) { assertValidation({ TableName: helpers.testRangeTable, - KeyConditions: {a: {ComparisonOperator: 'EQ', AttributeValueList: [{S: 'a'}]}}, - QueryFilter: {b: {ComparisonOperator: 'EQ', AttributeValueList: [{S: 'a'}]}}, + KeyConditions: { a: { ComparisonOperator: 'EQ', AttributeValueList: [ { S: 'a' } ] } }, + QueryFilter: { b: { ComparisonOperator: 'EQ', AttributeValueList: [ { S: 'a' } ] } }, }, 'QueryFilter can only contain non-primary key attributes: Primary key attribute: b', done) }) - it('should return ValidationException if global range key in QueryFilter', function(done) { + it('should return ValidationException if global range key in QueryFilter', function (done) { assertValidation({ TableName: helpers.testRangeTable, IndexName: 'index4', Select: 'ALL_ATTRIBUTES', - KeyConditions: {c: {ComparisonOperator: 'EQ', AttributeValueList: [{S: 'a'}]}}, - QueryFilter: {d: {ComparisonOperator: 'EQ', AttributeValueList: [{S: 'a'}]}}, + KeyConditions: { c: { ComparisonOperator: 'EQ', AttributeValueList: [ { S: 'a' } ] } }, + QueryFilter: { d: { ComparisonOperator: 'EQ', AttributeValueList: [ { S: 'a' } ] } }, }, 'QueryFilter can only contain non-primary key attributes: Primary key attribute: d', done) }) - it('should return ValidationException if range key in FilterExpression', function(done) { + it('should return ValidationException if range key in FilterExpression', function (done) { async.forEach([ 'attribute_exists(b.c) AND c = :b', 'b = :b', 'b[1] = :b', - ], function(expr, cb) { + ], function (expr, cb) { assertValidation({ TableName: helpers.testRangeTable, FilterExpression: expr, KeyConditionExpression: 'a = :a', - ExpressionAttributeValues: {':a': {S: '1'}, ':b': {N: '1'}}, + ExpressionAttributeValues: { ':a': { S: '1' }, ':b': { N: '1' } }, }, 'Filter Expression can only contain non-primary key attributes: Primary key attribute: b', cb) }, done) }) - it('should return ValidationException for non-scalar index access in FilterExpression', function(done) { + it('should return ValidationException for non-scalar index access in FilterExpression', function (done) { async.forEach([ 'attribute_exists(d.c) AND c = :b', 'd[1] = :b', - ], function(expr, cb) { + ], function (expr, cb) { assertValidation({ TableName: helpers.testRangeTable, FilterExpression: expr, KeyConditionExpression: 'a = :a', - ExpressionAttributeValues: {':a': {S: '1'}, ':b': {N: '1'}}, + ExpressionAttributeValues: { ':a': { S: '1' }, ':b': { N: '1' } }, }, 'Key attributes must be scalars; list random access \'[]\' and map lookup \'.\' are not allowed: IndexKey: d', cb) }, done) }) - it('should return ValidationException for specifying ALL_ATTRIBUTES when global index does not have ALL', function(done) { - async.forEach([{ - KeyConditions: {c: {ComparisonOperator: 'EQ', AttributeValueList: [{S: 'a'}]}}, - QueryFilter: {a: {ComparisonOperator: 'EQ', AttributeValueList: [{N: '1'}]}}, + it('should return ValidationException for specifying ALL_ATTRIBUTES when global index does not have ALL', function (done) { + async.forEach([ { + KeyConditions: { c: { ComparisonOperator: 'EQ', AttributeValueList: [ { S: 'a' } ] } }, + QueryFilter: { a: { ComparisonOperator: 'EQ', AttributeValueList: [ { N: '1' } ] } }, }, { KeyConditionExpression: 'c = :a', FilterExpression: 'a = :b and a.b = :a', - ExpressionAttributeValues: {':a': {S: 'a'}, ':b': {N: '1'}}, - }], function(queryOpts, cb) { + ExpressionAttributeValues: { ':a': { S: 'a' }, ':b': { N: '1' } }, + } ], function (queryOpts, cb) { assertValidation({ TableName: helpers.testRangeTable, IndexName: 'index4', Select: 'ALL_ATTRIBUTES', - ExclusiveStartKey: {a: {S: 'a'}, b: {S: 'b'}, c: {S: 'a'}, d: {S: 'b'}}, + ExclusiveStartKey: { a: { S: 'a' }, b: { S: 'b' }, c: { S: 'a' }, d: { S: 'b' } }, KeyConditions: queryOpts.KeyConditions, QueryFilter: queryOpts.QueryFilter, KeyConditionExpression: queryOpts.KeyConditionExpression, @@ -1900,404 +1900,404 @@ describe('query', function() { }) }) - describe('functionality', function() { + describe('functionality', function () { - it('should query a hash table when empty', function(done) { - async.forEach([{ - KeyConditions: {a: {ComparisonOperator: 'EQ', AttributeValueList: [{S: helpers.randomString()}]}}, + it('should query a hash table when empty', function (done) { + async.forEach([ { + KeyConditions: { a: { ComparisonOperator: 'EQ', AttributeValueList: [ { S: helpers.randomString() } ] } }, }, { KeyConditionExpression: 'a = :a', - ExpressionAttributeValues: {':a': {S: helpers.randomString()}}, - }], function(queryOpts, cb) { + ExpressionAttributeValues: { ':a': { S: helpers.randomString() } }, + } ], function (queryOpts, cb) { queryOpts.TableName = helpers.testHashTable queryOpts.ConsistentRead = false queryOpts.ReturnConsumedCapacity = 'NONE' queryOpts.ScanIndexForward = true queryOpts.Select = 'ALL_ATTRIBUTES' - request(opts(queryOpts), function(err, res) { + request(opts(queryOpts), function (err, res) { if (err) return cb(err) res.statusCode.should.equal(200) - res.body.should.eql({Count: 0, ScannedCount: 0, Items: []}) + res.body.should.eql({ Count: 0, ScannedCount: 0, Items: [] }) cb() }) }, done) }) - it('should query a hash table with items', function(done) { - var item = {a: {S: helpers.randomString()}, b: {N: helpers.randomNumber()}}, - item2 = {a: {S: helpers.randomString()}, b: item.b}, - item3 = {a: {S: helpers.randomString()}, b: {N: helpers.randomNumber()}}, - items = [item, item2, item3] - helpers.batchBulkPut(helpers.testHashTable, items, function(err) { + it('should query a hash table with items', function (done) { + var item = { a: { S: helpers.randomString() }, b: { N: helpers.randomNumber() } }, + item2 = { a: { S: helpers.randomString() }, b: item.b }, + item3 = { a: { S: helpers.randomString() }, b: { N: helpers.randomNumber() } }, + items = [ item, item2, item3 ] + helpers.batchBulkPut(helpers.testHashTable, items, function (err) { if (err) return done(err) - async.forEach([{ + async.forEach([ { QueryFilter: {}, - KeyConditions: {a: {ComparisonOperator: 'EQ', AttributeValueList: [item2.a]}}, + KeyConditions: { a: { ComparisonOperator: 'EQ', AttributeValueList: [ item2.a ] } }, }, { KeyConditionExpression: 'a = :a', - ExpressionAttributeValues: {':a': item2.a}, - }], function(queryOpts, cb) { + ExpressionAttributeValues: { ':a': item2.a }, + } ], function (queryOpts, cb) { queryOpts.TableName = helpers.testHashTable queryOpts.ConsistentRead = true - request(opts(queryOpts), function(err, res) { + request(opts(queryOpts), function (err, res) { if (err) return cb(err) res.statusCode.should.equal(200) - res.body.should.eql({Count: 1, ScannedCount: 1, Items: [item2]}) + res.body.should.eql({ Count: 1, ScannedCount: 1, Items: [ item2 ] }) cb() }) }, done) }) }) - it('should query a range table with EQ on just hash key', function(done) { - var item = {a: {S: helpers.randomString()}, b: {S: '1'}}, - item2 = {a: item.a, b: {S: '2'}}, - item3 = {a: item.a, b: {S: '3'}}, - items = [item, item2, item3] - helpers.batchBulkPut(helpers.testRangeTable, items, function(err) { + it('should query a range table with EQ on just hash key', function (done) { + var item = { a: { S: helpers.randomString() }, b: { S: '1' } }, + item2 = { a: item.a, b: { S: '2' } }, + item3 = { a: item.a, b: { S: '3' } }, + items = [ item, item2, item3 ] + helpers.batchBulkPut(helpers.testRangeTable, items, function (err) { if (err) return done(err) - async.forEach([{ - KeyConditions: {a: {ComparisonOperator: 'EQ', AttributeValueList: [item.a]}}, + async.forEach([ { + KeyConditions: { a: { ComparisonOperator: 'EQ', AttributeValueList: [ item.a ] } }, }, { KeyConditionExpression: 'a = :a', - ExpressionAttributeValues: {':a': item.a}, - }], function(queryOpts, cb) { + ExpressionAttributeValues: { ':a': item.a }, + } ], function (queryOpts, cb) { queryOpts.TableName = helpers.testRangeTable queryOpts.ConsistentRead = true - request(opts(queryOpts), function(err, res) { + request(opts(queryOpts), function (err, res) { if (err) return cb(err) res.statusCode.should.equal(200) - res.body.should.eql({Count: 3, ScannedCount: 3, Items: [item, item2, item3]}) + res.body.should.eql({ Count: 3, ScannedCount: 3, Items: [ item, item2, item3 ] }) cb() }) }, done) }) }) - it('should query a range table with EQ', function(done) { - var item = {a: {S: helpers.randomString()}, b: {S: '1'}}, - item2 = {a: item.a, b: {S: '2'}}, - item3 = {a: item.a, b: {S: '3'}}, - items = [item, item2, item3] - helpers.batchBulkPut(helpers.testRangeTable, items, function(err) { + it('should query a range table with EQ', function (done) { + var item = { a: { S: helpers.randomString() }, b: { S: '1' } }, + item2 = { a: item.a, b: { S: '2' } }, + item3 = { a: item.a, b: { S: '3' } }, + items = [ item, item2, item3 ] + helpers.batchBulkPut(helpers.testRangeTable, items, function (err) { if (err) return done(err) - async.forEach([{ + async.forEach([ { KeyConditions: { - a: {ComparisonOperator: 'EQ', AttributeValueList: [item.a]}, - b: {ComparisonOperator: 'EQ', AttributeValueList: [item2.b]}, + a: { ComparisonOperator: 'EQ', AttributeValueList: [ item.a ] }, + b: { ComparisonOperator: 'EQ', AttributeValueList: [ item2.b ] }, }, }, { KeyConditionExpression: 'a = :a AND b = :b', - ExpressionAttributeValues: {':a': item.a, ':b': item2.b}, - }], function(queryOpts, cb) { + ExpressionAttributeValues: { ':a': item.a, ':b': item2.b }, + } ], function (queryOpts, cb) { queryOpts.TableName = helpers.testRangeTable queryOpts.ConsistentRead = true - request(opts(queryOpts), function(err, res) { + request(opts(queryOpts), function (err, res) { if (err) return cb(err) res.statusCode.should.equal(200) - res.body.should.eql({Count: 1, ScannedCount: 1, Items: [item2]}) + res.body.should.eql({ Count: 1, ScannedCount: 1, Items: [ item2 ] }) cb() }) }, done) }) }) - it('should query a range table with LE', function(done) { - var item = {a: {S: helpers.randomString()}, b: {S: '1'}}, - item2 = {a: item.a, b: {S: '2'}}, - item3 = {a: item.a, b: {S: '3'}}, - items = [item, item2, item3] - helpers.batchBulkPut(helpers.testRangeTable, items, function(err) { + it('should query a range table with LE', function (done) { + var item = { a: { S: helpers.randomString() }, b: { S: '1' } }, + item2 = { a: item.a, b: { S: '2' } }, + item3 = { a: item.a, b: { S: '3' } }, + items = [ item, item2, item3 ] + helpers.batchBulkPut(helpers.testRangeTable, items, function (err) { if (err) return done(err) - async.forEach([{ + async.forEach([ { KeyConditions: { - a: {ComparisonOperator: 'EQ', AttributeValueList: [item.a]}, - b: {ComparisonOperator: 'LE', AttributeValueList: [item2.b]}, + a: { ComparisonOperator: 'EQ', AttributeValueList: [ item.a ] }, + b: { ComparisonOperator: 'LE', AttributeValueList: [ item2.b ] }, }, }, { KeyConditionExpression: 'a = :a AND b <= :b', - ExpressionAttributeValues: {':a': item.a, ':b': item2.b}, - }], function(queryOpts, cb) { + ExpressionAttributeValues: { ':a': item.a, ':b': item2.b }, + } ], function (queryOpts, cb) { queryOpts.TableName = helpers.testRangeTable queryOpts.ConsistentRead = true - request(opts(queryOpts), function(err, res) { + request(opts(queryOpts), function (err, res) { if (err) return cb(err) res.statusCode.should.equal(200) - res.body.should.eql({Count: 2, ScannedCount: 2, Items: [item, item2]}) + res.body.should.eql({ Count: 2, ScannedCount: 2, Items: [ item, item2 ] }) cb() }) }, done) }) }) - it('should query a range table with LT', function(done) { - var item = {a: {S: helpers.randomString()}, b: {S: '1'}}, - item2 = {a: item.a, b: {S: '2'}}, - item3 = {a: item.a, b: {S: '3'}}, - items = [item, item2, item3] - helpers.batchBulkPut(helpers.testRangeTable, items, function(err) { + it('should query a range table with LT', function (done) { + var item = { a: { S: helpers.randomString() }, b: { S: '1' } }, + item2 = { a: item.a, b: { S: '2' } }, + item3 = { a: item.a, b: { S: '3' } }, + items = [ item, item2, item3 ] + helpers.batchBulkPut(helpers.testRangeTable, items, function (err) { if (err) return done(err) - async.forEach([{ + async.forEach([ { KeyConditions: { - a: {ComparisonOperator: 'EQ', AttributeValueList: [item.a]}, - b: {ComparisonOperator: 'LT', AttributeValueList: [item2.b]}, + a: { ComparisonOperator: 'EQ', AttributeValueList: [ item.a ] }, + b: { ComparisonOperator: 'LT', AttributeValueList: [ item2.b ] }, }, }, { KeyConditionExpression: 'a = :a AND b < :b', - ExpressionAttributeValues: {':a': item.a, ':b': item2.b}, - }], function(queryOpts, cb) { + ExpressionAttributeValues: { ':a': item.a, ':b': item2.b }, + } ], function (queryOpts, cb) { queryOpts.TableName = helpers.testRangeTable queryOpts.ConsistentRead = true - request(opts(queryOpts), function(err, res) { + request(opts(queryOpts), function (err, res) { if (err) return cb(err) res.statusCode.should.equal(200) - res.body.should.eql({Count: 1, ScannedCount: 1, Items: [item]}) + res.body.should.eql({ Count: 1, ScannedCount: 1, Items: [ item ] }) cb() }) }, done) }) }) - it('should query a range table with GE', function(done) { - var item = {a: {S: helpers.randomString()}, b: {S: '1'}}, - item2 = {a: item.a, b: {S: '2'}}, - item3 = {a: item.a, b: {S: '3'}}, - items = [item, item2, item3] - helpers.batchBulkPut(helpers.testRangeTable, items, function(err) { + it('should query a range table with GE', function (done) { + var item = { a: { S: helpers.randomString() }, b: { S: '1' } }, + item2 = { a: item.a, b: { S: '2' } }, + item3 = { a: item.a, b: { S: '3' } }, + items = [ item, item2, item3 ] + helpers.batchBulkPut(helpers.testRangeTable, items, function (err) { if (err) return done(err) - async.forEach([{ + async.forEach([ { KeyConditions: { - a: {ComparisonOperator: 'EQ', AttributeValueList: [item.a]}, - b: {ComparisonOperator: 'GE', AttributeValueList: [item2.b]}, + a: { ComparisonOperator: 'EQ', AttributeValueList: [ item.a ] }, + b: { ComparisonOperator: 'GE', AttributeValueList: [ item2.b ] }, }, }, { KeyConditionExpression: 'a = :a AND b >= :b', - ExpressionAttributeValues: {':a': item.a, ':b': item2.b}, - }], function(queryOpts, cb) { + ExpressionAttributeValues: { ':a': item.a, ':b': item2.b }, + } ], function (queryOpts, cb) { queryOpts.TableName = helpers.testRangeTable queryOpts.ConsistentRead = true - request(opts(queryOpts), function(err, res) { + request(opts(queryOpts), function (err, res) { if (err) return cb(err) res.statusCode.should.equal(200) - res.body.should.eql({Count: 2, ScannedCount: 2, Items: [item2, item3]}) + res.body.should.eql({ Count: 2, ScannedCount: 2, Items: [ item2, item3 ] }) cb() }) }, done) }) }) - it('should query a range table with GT', function(done) { - var item = {a: {S: helpers.randomString()}, b: {S: '1'}}, - item2 = {a: item.a, b: {S: '2'}}, - item3 = {a: item.a, b: {S: '3'}}, - items = [item, item2, item3] - helpers.batchBulkPut(helpers.testRangeTable, items, function(err) { + it('should query a range table with GT', function (done) { + var item = { a: { S: helpers.randomString() }, b: { S: '1' } }, + item2 = { a: item.a, b: { S: '2' } }, + item3 = { a: item.a, b: { S: '3' } }, + items = [ item, item2, item3 ] + helpers.batchBulkPut(helpers.testRangeTable, items, function (err) { if (err) return done(err) - async.forEach([{ + async.forEach([ { KeyConditions: { - a: {ComparisonOperator: 'EQ', AttributeValueList: [item.a]}, - b: {ComparisonOperator: 'GT', AttributeValueList: [item2.b]}, + a: { ComparisonOperator: 'EQ', AttributeValueList: [ item.a ] }, + b: { ComparisonOperator: 'GT', AttributeValueList: [ item2.b ] }, }, }, { KeyConditionExpression: 'a = :a AND b > :b', - ExpressionAttributeValues: {':a': item.a, ':b': item2.b}, - }], function(queryOpts, cb) { + ExpressionAttributeValues: { ':a': item.a, ':b': item2.b }, + } ], function (queryOpts, cb) { queryOpts.TableName = helpers.testRangeTable queryOpts.ConsistentRead = true - request(opts(queryOpts), function(err, res) { + request(opts(queryOpts), function (err, res) { if (err) return cb(err) res.statusCode.should.equal(200) - res.body.should.eql({Count: 1, ScannedCount: 1, Items: [item3]}) + res.body.should.eql({ Count: 1, ScannedCount: 1, Items: [ item3 ] }) cb() }) }, done) }) }) - it('should query a range table with BEGINS_WITH', function(done) { - var item = {a: {S: helpers.randomString()}, b: {S: 'aaa'}}, - item2 = {a: item.a, b: {S: 'aab'}}, - item3 = {a: item.a, b: {S: 'abc'}}, - items = [item, item2, item3] - helpers.batchBulkPut(helpers.testRangeTable, items, function(err) { + it('should query a range table with BEGINS_WITH', function (done) { + var item = { a: { S: helpers.randomString() }, b: { S: 'aaa' } }, + item2 = { a: item.a, b: { S: 'aab' } }, + item3 = { a: item.a, b: { S: 'abc' } }, + items = [ item, item2, item3 ] + helpers.batchBulkPut(helpers.testRangeTable, items, function (err) { if (err) return done(err) - async.forEach([{ + async.forEach([ { KeyConditions: { - a: {ComparisonOperator: 'EQ', AttributeValueList: [item.a]}, - b: {ComparisonOperator: 'BEGINS_WITH', AttributeValueList: [{S: 'aa'}]}, + a: { ComparisonOperator: 'EQ', AttributeValueList: [ item.a ] }, + b: { ComparisonOperator: 'BEGINS_WITH', AttributeValueList: [ { S: 'aa' } ] }, }, }, { KeyConditionExpression: 'a = :a AND begins_with(b, :b)', - ExpressionAttributeValues: {':a': item.a, ':b': {S: 'aa'}}, - }], function(queryOpts, cb) { + ExpressionAttributeValues: { ':a': item.a, ':b': { S: 'aa' } }, + } ], function (queryOpts, cb) { queryOpts.TableName = helpers.testRangeTable queryOpts.ConsistentRead = true - request(opts(queryOpts), function(err, res) { + request(opts(queryOpts), function (err, res) { if (err) return cb(err) res.statusCode.should.equal(200) - res.body.should.eql({Count: 2, ScannedCount: 2, Items: [item, item2]}) + res.body.should.eql({ Count: 2, ScannedCount: 2, Items: [ item, item2 ] }) cb() }) }, done) }) }) - it('should query a range table with BETWEEN', function(done) { - var item = {a: {S: helpers.randomString()}, b: {S: 'aa'}}, - item2 = {a: item.a, b: {S: 'ab'}}, - item3 = {a: item.a, b: {S: 'abc'}}, - item4 = {a: item.a, b: {S: 'ac'}}, - item5 = {a: item.a, b: {S: 'aca'}}, - items = [item, item2, item3, item4, item5] - helpers.batchBulkPut(helpers.testRangeTable, items, function(err) { + it('should query a range table with BETWEEN', function (done) { + var item = { a: { S: helpers.randomString() }, b: { S: 'aa' } }, + item2 = { a: item.a, b: { S: 'ab' } }, + item3 = { a: item.a, b: { S: 'abc' } }, + item4 = { a: item.a, b: { S: 'ac' } }, + item5 = { a: item.a, b: { S: 'aca' } }, + items = [ item, item2, item3, item4, item5 ] + helpers.batchBulkPut(helpers.testRangeTable, items, function (err) { if (err) return done(err) - async.forEach([{ + async.forEach([ { KeyConditions: { - a: {ComparisonOperator: 'EQ', AttributeValueList: [item.a]}, - b: {ComparisonOperator: 'BETWEEN', AttributeValueList: [{S: 'ab'}, {S: 'ac'}]}, + a: { ComparisonOperator: 'EQ', AttributeValueList: [ item.a ] }, + b: { ComparisonOperator: 'BETWEEN', AttributeValueList: [ { S: 'ab' }, { S: 'ac' } ] }, }, }, { KeyConditionExpression: 'a = :a AND b BETWEEN :b AND :c', - ExpressionAttributeValues: {':a': item.a, ':b': {S: 'ab'}, ':c': {S: 'ac'}}, - }], function(queryOpts, cb) { + ExpressionAttributeValues: { ':a': item.a, ':b': { S: 'ab' }, ':c': { S: 'ac' } }, + } ], function (queryOpts, cb) { queryOpts.TableName = helpers.testRangeTable queryOpts.ConsistentRead = true - request(opts(queryOpts), function(err, res) { + request(opts(queryOpts), function (err, res) { if (err) return cb(err) res.statusCode.should.equal(200) - res.body.should.eql({Count: 3, ScannedCount: 3, Items: [item2, item3, item4]}) + res.body.should.eql({ Count: 3, ScannedCount: 3, Items: [ item2, item3, item4 ] }) cb() }) }, done) }) }) - it('should only return requested attributes', function(done) { - var item = {a: {S: helpers.randomString()}, b: {S: 'b1'}, d: {S: 'd1'}}, - item2 = {a: item.a, b: {S: 'b2'}}, - item3 = {a: item.a, b: {S: 'b3'}, d: {S: 'd3'}, e: {S: 'e3'}}, - items = [item, item2, item3] - helpers.batchBulkPut(helpers.testRangeTable, items, function(err) { + it('should only return requested attributes', function (done) { + var item = { a: { S: helpers.randomString() }, b: { S: 'b1' }, d: { S: 'd1' } }, + item2 = { a: item.a, b: { S: 'b2' } }, + item3 = { a: item.a, b: { S: 'b3' }, d: { S: 'd3' }, e: { S: 'e3' } }, + items = [ item, item2, item3 ] + helpers.batchBulkPut(helpers.testRangeTable, items, function (err) { if (err) return done(err) - async.forEach([{ + async.forEach([ { KeyConditions: { - a: {ComparisonOperator: 'EQ', AttributeValueList: [item.a]}, + a: { ComparisonOperator: 'EQ', AttributeValueList: [ item.a ] }, }, - AttributesToGet: ['b', 'd'], + AttributesToGet: [ 'b', 'd' ], }, { KeyConditions: { - a: {ComparisonOperator: 'EQ', AttributeValueList: [item.a]}, + a: { ComparisonOperator: 'EQ', AttributeValueList: [ item.a ] }, }, ProjectionExpression: 'b, d', }, { KeyConditionExpression: 'a = :a', - ExpressionAttributeValues: {':a': item.a}, + ExpressionAttributeValues: { ':a': item.a }, ProjectionExpression: 'b, d', }, { KeyConditionExpression: 'a = :a', - ExpressionAttributeValues: {':a': item.a}, - ExpressionAttributeNames: {'#b': 'b', '#d': 'd'}, + ExpressionAttributeValues: { ':a': item.a }, + ExpressionAttributeNames: { '#b': 'b', '#d': 'd' }, ProjectionExpression: '#b, #d', - }], function(queryOpts, cb) { + } ], function (queryOpts, cb) { queryOpts.TableName = helpers.testRangeTable queryOpts.ConsistentRead = true - request(opts(queryOpts), function(err, res) { + request(opts(queryOpts), function (err, res) { if (err) return cb(err) res.statusCode.should.equal(200) - res.body.should.eql({Count: 3, ScannedCount: 3, Items: [ - {b: {S: 'b1'}, d: {S: 'd1'}}, - {b: {S: 'b2'}}, - {b: {S: 'b3'}, d: {S: 'd3'}}, - ]}) + res.body.should.eql({ Count: 3, ScannedCount: 3, Items: [ + { b: { S: 'b1' }, d: { S: 'd1' } }, + { b: { S: 'b2' } }, + { b: { S: 'b3' }, d: { S: 'd3' } }, + ] }) cb() }) }, done) }) }) - it('should only return requested nested attributes', function(done) { - var item = {a: {S: helpers.randomString()}, b: {S: 'b1'}, e: {M: {a: {S: 'b1'}, d: {S: 'b1'}}}, f: {L: [{S: 'd1'}, {S: 'd2'}, {S: 'd3'}]}}, - item2 = {a: item.a, b: {S: 'b2'}}, - item3 = {a: item.a, b: {S: 'b3'}, d: {S: 'd3'}, e: {S: 'e3'}}, - items = [item, item2, item3] - helpers.batchBulkPut(helpers.testRangeTable, items, function(err) { + it('should only return requested nested attributes', function (done) { + var item = { a: { S: helpers.randomString() }, b: { S: 'b1' }, e: { M: { a: { S: 'b1' }, d: { S: 'b1' } } }, f: { L: [ { S: 'd1' }, { S: 'd2' }, { S: 'd3' } ] } }, + item2 = { a: item.a, b: { S: 'b2' } }, + item3 = { a: item.a, b: { S: 'b3' }, d: { S: 'd3' }, e: { S: 'e3' } }, + items = [ item, item2, item3 ] + helpers.batchBulkPut(helpers.testRangeTable, items, function (err) { if (err) return done(err) - async.forEach([{ + async.forEach([ { KeyConditions: { - a: {ComparisonOperator: 'EQ', AttributeValueList: [item.a]}, + a: { ComparisonOperator: 'EQ', AttributeValueList: [ item.a ] }, }, ProjectionExpression: 'f[2], f[0], e.d, e.a, d', }, { KeyConditionExpression: 'a = :a', - ExpressionAttributeValues: {':a': item.a}, + ExpressionAttributeValues: { ':a': item.a }, ProjectionExpression: 'f[2], f[0], e.d, e.a, d', }, { KeyConditionExpression: 'a = :a', - ExpressionAttributeValues: {':a': item.a}, - ExpressionAttributeNames: {'#f': 'f', '#e': 'e', '#a': 'a'}, + ExpressionAttributeValues: { ':a': item.a }, + ExpressionAttributeNames: { '#f': 'f', '#e': 'e', '#a': 'a' }, ProjectionExpression: '#f[2],#f[0],#e.d,e.#a,d', - }], function(queryOpts, cb) { + } ], function (queryOpts, cb) { queryOpts.TableName = helpers.testRangeTable queryOpts.ConsistentRead = true - request(opts(queryOpts), function(err, res) { + request(opts(queryOpts), function (err, res) { if (err) return cb(err) res.statusCode.should.equal(200) - res.body.should.eql({Count: 3, ScannedCount: 3, Items: [ - {e: {M: {a: {S: 'b1'}, d: {S: 'b1'}}}, f: {L: [{S: 'd1'}, {S: 'd3'}]}}, + res.body.should.eql({ Count: 3, ScannedCount: 3, Items: [ + { e: { M: { a: { S: 'b1' }, d: { S: 'b1' } } }, f: { L: [ { S: 'd1' }, { S: 'd3' } ] } }, {}, - {d: {S: 'd3'}}, - ]}) + { d: { S: 'd3' } }, + ] }) cb() }) }, done) }) }) - it('should filter items by query filter', function(done) { - var item = {a: {S: helpers.randomString()}, b: {S: 'b1'}, d: {S: '1'}}, - item2 = {a: item.a, b: {S: 'b2'}}, - item3 = {a: item.a, b: {S: 'b3'}, d: {S: 'd3'}, e: {S: 'e3'}}, - items = [item, item2, item3] - helpers.batchBulkPut(helpers.testRangeTable, items, function(err) { + it('should filter items by query filter', function (done) { + var item = { a: { S: helpers.randomString() }, b: { S: 'b1' }, d: { S: '1' } }, + item2 = { a: item.a, b: { S: 'b2' } }, + item3 = { a: item.a, b: { S: 'b3' }, d: { S: 'd3' }, e: { S: 'e3' } }, + items = [ item, item2, item3 ] + helpers.batchBulkPut(helpers.testRangeTable, items, function (err) { if (err) return done(err) - async.forEach([{ + async.forEach([ { KeyConditions: { - a: {ComparisonOperator: 'EQ', AttributeValueList: [item.a]}, + a: { ComparisonOperator: 'EQ', AttributeValueList: [ item.a ] }, }, QueryFilter: { - e: {ComparisonOperator: 'NOT_NULL'}, + e: { ComparisonOperator: 'NOT_NULL' }, }, }, { KeyConditionExpression: 'a = :a', - ExpressionAttributeValues: {':a': item.a}, + ExpressionAttributeValues: { ':a': item.a }, FilterExpression: 'attribute_exists(e)', - }], function(queryOpts, cb) { + } ], function (queryOpts, cb) { queryOpts.TableName = helpers.testRangeTable queryOpts.ConsistentRead = true - request(opts(queryOpts), function(err, res) { + request(opts(queryOpts), function (err, res) { if (err) return cb(err) res.statusCode.should.equal(200) - res.body.should.eql({Count: 1, ScannedCount: 3, Items: [ - {a: item.a, b: {S: 'b3'}, d: {S: 'd3'}, e: {S: 'e3'}}, - ]}) + res.body.should.eql({ Count: 1, ScannedCount: 3, Items: [ + { a: item.a, b: { S: 'b3' }, d: { S: 'd3' }, e: { S: 'e3' } }, + ] }) cb() }) }, done) }) }) - it('should only return projected attributes by default for secondary indexes', function(done) { - var item = {a: {S: helpers.randomString()}, b: {S: 'b1'}, c: {S: 'c1'}, d: {S: 'd1'}}, - item2 = {a: item.a, b: {S: 'b2'}}, - item3 = {a: item.a, b: {S: 'b3'}, d: {S: 'd3'}, e: {S: 'e3'}, f: {S: 'f3'}}, - item4 = {a: item.a, b: {S: 'b4'}, c: {S: 'c4'}, d: {S: 'd4'}, e: {S: 'e4'}}, - items = [item, item2, item3, item4] - helpers.batchBulkPut(helpers.testRangeTable, items, function(err) { + it('should only return projected attributes by default for secondary indexes', function (done) { + var item = { a: { S: helpers.randomString() }, b: { S: 'b1' }, c: { S: 'c1' }, d: { S: 'd1' } }, + item2 = { a: item.a, b: { S: 'b2' } }, + item3 = { a: item.a, b: { S: 'b3' }, d: { S: 'd3' }, e: { S: 'e3' }, f: { S: 'f3' } }, + item4 = { a: item.a, b: { S: 'b4' }, c: { S: 'c4' }, d: { S: 'd4' }, e: { S: 'e4' } }, + items = [ item, item2, item3, item4 ] + helpers.batchBulkPut(helpers.testRangeTable, items, function (err) { if (err) return done(err) - var req = {TableName: helpers.testRangeTable, ConsistentRead: true, IndexName: 'index2', - KeyConditions: {a: {ComparisonOperator: 'EQ', AttributeValueList: [item.a]}}, - ReturnConsumedCapacity: 'TOTAL'} - request(opts(req), function(err, res) { + var req = { TableName: helpers.testRangeTable, ConsistentRead: true, IndexName: 'index2', + KeyConditions: { a: { ComparisonOperator: 'EQ', AttributeValueList: [ item.a ] } }, + ReturnConsumedCapacity: 'TOTAL' } + request(opts(req), function (err, res) { if (err) return done(err) res.statusCode.should.equal(200) delete item3.e @@ -2306,22 +2306,22 @@ describe('query', function() { res.body.should.eql({ Count: 3, ScannedCount: 3, - Items: [item, item3, item4], - ConsumedCapacity: {CapacityUnits: 1, TableName: helpers.testRangeTable}, + Items: [ item, item3, item4 ], + ConsumedCapacity: { CapacityUnits: 1, TableName: helpers.testRangeTable }, }) req.ReturnConsumedCapacity = 'INDEXES' - request(opts(req), function(err, res) { + request(opts(req), function (err, res) { if (err) return done(err) res.statusCode.should.equal(200) res.body.should.eql({ Count: 3, ScannedCount: 3, - Items: [item, item3, item4], + Items: [ item, item3, item4 ], ConsumedCapacity: { CapacityUnits: 1, TableName: helpers.testRangeTable, - Table: {CapacityUnits: 0}, - LocalSecondaryIndexes: {index2: {CapacityUnits: 1}}, + Table: { CapacityUnits: 0 }, + LocalSecondaryIndexes: { index2: { CapacityUnits: 1 } }, }, }) done() @@ -2330,39 +2330,39 @@ describe('query', function() { }) }) - it('should return all attributes when specified for secondary indexes', function(done) { - var item = {a: {S: helpers.randomString()}, b: {S: 'b1'}, c: {S: 'c1'}, d: {S: 'd1'}}, - item2 = {a: item.a, b: {S: 'b2'}}, - item3 = {a: item.a, b: {S: 'b3'}, d: {S: 'd3'}, e: {M: {e3: {S: new Array(4062).join('e')}}}, f: {L: [{S: 'f3'}, {S: 'ff3'}]}}, - item4 = {a: item.a, b: {S: 'b4'}, c: {S: 'c4'}, d: {S: 'd4'}, e: {M: {ee4: {S: 'e4'}, eee4: {S: new Array(4062).join('e')}}}}, - items = [item, item2, item3, item4] - helpers.batchBulkPut(helpers.testRangeTable, items, function(err) { + it('should return all attributes when specified for secondary indexes', function (done) { + var item = { a: { S: helpers.randomString() }, b: { S: 'b1' }, c: { S: 'c1' }, d: { S: 'd1' } }, + item2 = { a: item.a, b: { S: 'b2' } }, + item3 = { a: item.a, b: { S: 'b3' }, d: { S: 'd3' }, e: { M: { e3: { S: new Array(4062).join('e') } } }, f: { L: [ { S: 'f3' }, { S: 'ff3' } ] } }, + item4 = { a: item.a, b: { S: 'b4' }, c: { S: 'c4' }, d: { S: 'd4' }, e: { M: { ee4: { S: 'e4' }, eee4: { S: new Array(4062).join('e') } } } }, + items = [ item, item2, item3, item4 ] + helpers.batchBulkPut(helpers.testRangeTable, items, function (err) { if (err) return done(err) - var req = {TableName: helpers.testRangeTable, ConsistentRead: true, IndexName: 'index2', - KeyConditions: {a: {ComparisonOperator: 'EQ', AttributeValueList: [item.a]}}, - Select: 'ALL_ATTRIBUTES', ReturnConsumedCapacity: 'TOTAL'} - request(opts(req), function(err, res) { + var req = { TableName: helpers.testRangeTable, ConsistentRead: true, IndexName: 'index2', + KeyConditions: { a: { ComparisonOperator: 'EQ', AttributeValueList: [ item.a ] } }, + Select: 'ALL_ATTRIBUTES', ReturnConsumedCapacity: 'TOTAL' } + request(opts(req), function (err, res) { if (err) return done(err) res.statusCode.should.equal(200) res.body.should.eql({ Count: 3, ScannedCount: 3, - Items: [item, item3, item4], - ConsumedCapacity: {CapacityUnits: 4, TableName: helpers.testRangeTable}, + Items: [ item, item3, item4 ], + ConsumedCapacity: { CapacityUnits: 4, TableName: helpers.testRangeTable }, }) req.ReturnConsumedCapacity = 'INDEXES' - request(opts(req), function(err, res) { + request(opts(req), function (err, res) { if (err) return done(err) res.statusCode.should.equal(200) res.body.should.eql({ Count: 3, ScannedCount: 3, - Items: [item, item3, item4], + Items: [ item, item3, item4 ], ConsumedCapacity: { CapacityUnits: 4, TableName: helpers.testRangeTable, - Table: {CapacityUnits: 3}, - LocalSecondaryIndexes: {index2: {CapacityUnits: 1}}, + Table: { CapacityUnits: 3 }, + LocalSecondaryIndexes: { index2: { CapacityUnits: 1 } }, }, }) done() @@ -2371,160 +2371,160 @@ describe('query', function() { }) }) - it('should return COUNT if requested', function(done) { - var item = {a: {S: helpers.randomString()}, b: {S: '2'}}, - item2 = {a: item.a, b: {S: '1'}}, - item3 = {a: item.a, b: {S: '3'}}, - item4 = {a: item.a, b: {S: '4'}}, - item5 = {a: item.a, b: {S: '5'}}, - items = [item, item2, item3, item4, item5] - helpers.batchBulkPut(helpers.testRangeTable, items, function(err) { + it('should return COUNT if requested', function (done) { + var item = { a: { S: helpers.randomString() }, b: { S: '2' } }, + item2 = { a: item.a, b: { S: '1' } }, + item3 = { a: item.a, b: { S: '3' } }, + item4 = { a: item.a, b: { S: '4' } }, + item5 = { a: item.a, b: { S: '5' } }, + items = [ item, item2, item3, item4, item5 ] + helpers.batchBulkPut(helpers.testRangeTable, items, function (err) { if (err) return done(err) - request(opts({TableName: helpers.testRangeTable, ConsistentRead: true, KeyConditions: { - a: {ComparisonOperator: 'EQ', AttributeValueList: [item.a]}, - b: {ComparisonOperator: 'GE', AttributeValueList: [item.b]}, - }, Select: 'COUNT'}), function(err, res) { + request(opts({ TableName: helpers.testRangeTable, ConsistentRead: true, KeyConditions: { + a: { ComparisonOperator: 'EQ', AttributeValueList: [ item.a ] }, + b: { ComparisonOperator: 'GE', AttributeValueList: [ item.b ] }, + }, Select: 'COUNT' }), function (err, res) { if (err) return done(err) res.statusCode.should.equal(200) should.not.exist(res.body.Items) - res.body.should.eql({Count: 4, ScannedCount: 4}) + res.body.should.eql({ Count: 4, ScannedCount: 4 }) done() }) }) }) - it('should only return Limit items if requested', function(done) { - var item = {a: {S: helpers.randomString()}, b: {S: '2'}, c: {S: 'c'}}, - item2 = {a: item.a, b: {S: '1'}, c: {S: 'c'}}, - item3 = {a: item.a, b: {S: '3'}, c: {S: 'c'}}, - item4 = {a: item.a, b: {S: '4'}, c: {S: 'c'}}, - item5 = {a: item.a, b: {S: '5'}, c: {S: 'c'}}, - items = [item, item2, item3, item4, item5] - helpers.batchBulkPut(helpers.testRangeTable, items, function(err) { + it('should only return Limit items if requested', function (done) { + var item = { a: { S: helpers.randomString() }, b: { S: '2' }, c: { S: 'c' } }, + item2 = { a: item.a, b: { S: '1' }, c: { S: 'c' } }, + item3 = { a: item.a, b: { S: '3' }, c: { S: 'c' } }, + item4 = { a: item.a, b: { S: '4' }, c: { S: 'c' } }, + item5 = { a: item.a, b: { S: '5' }, c: { S: 'c' } }, + items = [ item, item2, item3, item4, item5 ] + helpers.batchBulkPut(helpers.testRangeTable, items, function (err) { if (err) return done(err) - request(opts({TableName: helpers.testRangeTable, ConsistentRead: true, KeyConditions: { - a: {ComparisonOperator: 'EQ', AttributeValueList: [item.a]}, - b: {ComparisonOperator: 'GE', AttributeValueList: [item.b]}, - }, Limit: 2}), function(err, res) { + request(opts({ TableName: helpers.testRangeTable, ConsistentRead: true, KeyConditions: { + a: { ComparisonOperator: 'EQ', AttributeValueList: [ item.a ] }, + b: { ComparisonOperator: 'GE', AttributeValueList: [ item.b ] }, + }, Limit: 2 }), function (err, res) { if (err) return done(err) res.statusCode.should.equal(200) - res.body.should.eql({Count: 2, ScannedCount: 2, Items: [item, item3], LastEvaluatedKey: {a: item3.a, b: item3.b}}) + res.body.should.eql({ Count: 2, ScannedCount: 2, Items: [ item, item3 ], LastEvaluatedKey: { a: item3.a, b: item3.b } }) done() }) }) }) - it('should only return Limit items if requested and QueryFilter', function(done) { - var item = {a: {S: helpers.randomString()}, b: {S: '2'}, c: {S: 'c'}}, - item2 = {a: item.a, b: {S: '1'}, c: {S: 'c'}}, - item3 = {a: item.a, b: {S: '3'}, c: {S: 'c'}, d: {S: 'd'}}, - item4 = {a: item.a, b: {S: '4'}, c: {S: 'c'}}, - item5 = {a: item.a, b: {S: '5'}, c: {S: 'c'}}, - items = [item, item2, item3, item4, item5] - helpers.batchBulkPut(helpers.testRangeTable, items, function(err) { + it('should only return Limit items if requested and QueryFilter', function (done) { + var item = { a: { S: helpers.randomString() }, b: { S: '2' }, c: { S: 'c' } }, + item2 = { a: item.a, b: { S: '1' }, c: { S: 'c' } }, + item3 = { a: item.a, b: { S: '3' }, c: { S: 'c' }, d: { S: 'd' } }, + item4 = { a: item.a, b: { S: '4' }, c: { S: 'c' } }, + item5 = { a: item.a, b: { S: '5' }, c: { S: 'c' } }, + items = [ item, item2, item3, item4, item5 ] + helpers.batchBulkPut(helpers.testRangeTable, items, function (err) { if (err) return done(err) - async.forEach([{ + async.forEach([ { KeyConditions: { - a: {ComparisonOperator: 'EQ', AttributeValueList: [item.a]}, - b: {ComparisonOperator: 'GE', AttributeValueList: [item.b]}, + a: { ComparisonOperator: 'EQ', AttributeValueList: [ item.a ] }, + b: { ComparisonOperator: 'GE', AttributeValueList: [ item.b ] }, }, QueryFilter: { - d: {ComparisonOperator: 'EQ', AttributeValueList: [item3.d]}, + d: { ComparisonOperator: 'EQ', AttributeValueList: [ item3.d ] }, }, }, { KeyConditionExpression: 'a = :a AND b >= :b', - ExpressionAttributeValues: {':a': item.a, ':b': item.b, ':d': item3.d}, + ExpressionAttributeValues: { ':a': item.a, ':b': item.b, ':d': item3.d }, FilterExpression: 'd = :d', - }], function(queryOpts, cb) { + } ], function (queryOpts, cb) { queryOpts.TableName = helpers.testRangeTable queryOpts.ConsistentRead = true queryOpts.Limit = 2 - request(opts(queryOpts), function(err, res) { + request(opts(queryOpts), function (err, res) { if (err) return cb(err) res.statusCode.should.equal(200) - res.body.should.eql({Count: 1, ScannedCount: 2, Items: [item3], LastEvaluatedKey: {a: item3.a, b: item3.b}}) + res.body.should.eql({ Count: 1, ScannedCount: 2, Items: [ item3 ], LastEvaluatedKey: { a: item3.a, b: item3.b } }) cb() }) }, done) }) }) - it('should return LastEvaluatedKey even if only Count is selected', function(done) { - var item = {a: {S: helpers.randomString()}, b: {S: '2'}, c: {S: 'c'}}, - item2 = {a: item.a, b: {S: '1'}, c: {S: 'c'}}, - item3 = {a: item.a, b: {S: '3'}, c: {S: 'c'}}, - item4 = {a: item.a, b: {S: '4'}, c: {S: 'c'}}, - item5 = {a: item.a, b: {S: '5'}, c: {S: 'c'}}, - items = [item, item2, item3, item4, item5] - helpers.batchBulkPut(helpers.testRangeTable, items, function(err) { + it('should return LastEvaluatedKey even if only Count is selected', function (done) { + var item = { a: { S: helpers.randomString() }, b: { S: '2' }, c: { S: 'c' } }, + item2 = { a: item.a, b: { S: '1' }, c: { S: 'c' } }, + item3 = { a: item.a, b: { S: '3' }, c: { S: 'c' } }, + item4 = { a: item.a, b: { S: '4' }, c: { S: 'c' } }, + item5 = { a: item.a, b: { S: '5' }, c: { S: 'c' } }, + items = [ item, item2, item3, item4, item5 ] + helpers.batchBulkPut(helpers.testRangeTable, items, function (err) { if (err) return done(err) - request(opts({TableName: helpers.testRangeTable, ConsistentRead: true, KeyConditions: { - a: {ComparisonOperator: 'EQ', AttributeValueList: [item.a]}, - b: {ComparisonOperator: 'GE', AttributeValueList: [item.b]}, - }, Limit: 2, Select: 'COUNT'}), function(err, res) { + request(opts({ TableName: helpers.testRangeTable, ConsistentRead: true, KeyConditions: { + a: { ComparisonOperator: 'EQ', AttributeValueList: [ item.a ] }, + b: { ComparisonOperator: 'GE', AttributeValueList: [ item.b ] }, + }, Limit: 2, Select: 'COUNT' }), function (err, res) { if (err) return done(err) res.statusCode.should.equal(200) - res.body.should.eql({Count: 2, ScannedCount: 2, LastEvaluatedKey: {a: item3.a, b: item3.b}}) + res.body.should.eql({ Count: 2, ScannedCount: 2, LastEvaluatedKey: { a: item3.a, b: item3.b } }) done() }) }) }) - it('should return LastEvaluatedKey even if only Count is selected and QueryFilter', function(done) { - var item = {a: {S: helpers.randomString()}, b: {S: '2'}, c: {S: 'c'}}, - item2 = {a: item.a, b: {S: '1'}, c: {S: 'c'}}, - item3 = {a: item.a, b: {S: '3'}, c: {S: 'c'}, d: {S: 'd'}}, - item4 = {a: item.a, b: {S: '4'}, c: {S: 'c'}}, - item5 = {a: item.a, b: {S: '5'}, c: {S: 'c'}}, - items = [item, item2, item3, item4, item5] - helpers.batchBulkPut(helpers.testRangeTable, items, function(err) { + it('should return LastEvaluatedKey even if only Count is selected and QueryFilter', function (done) { + var item = { a: { S: helpers.randomString() }, b: { S: '2' }, c: { S: 'c' } }, + item2 = { a: item.a, b: { S: '1' }, c: { S: 'c' } }, + item3 = { a: item.a, b: { S: '3' }, c: { S: 'c' }, d: { S: 'd' } }, + item4 = { a: item.a, b: { S: '4' }, c: { S: 'c' } }, + item5 = { a: item.a, b: { S: '5' }, c: { S: 'c' } }, + items = [ item, item2, item3, item4, item5 ] + helpers.batchBulkPut(helpers.testRangeTable, items, function (err) { if (err) return done(err) - request(opts({TableName: helpers.testRangeTable, ConsistentRead: true, KeyConditions: { - a: {ComparisonOperator: 'EQ', AttributeValueList: [item.a]}, - b: {ComparisonOperator: 'GE', AttributeValueList: [item.b]}, + request(opts({ TableName: helpers.testRangeTable, ConsistentRead: true, KeyConditions: { + a: { ComparisonOperator: 'EQ', AttributeValueList: [ item.a ] }, + b: { ComparisonOperator: 'GE', AttributeValueList: [ item.b ] }, }, QueryFilter: { - d: {ComparisonOperator: 'EQ', AttributeValueList: [item3.d]}, - }, Limit: 2, Select: 'COUNT'}), function(err, res) { + d: { ComparisonOperator: 'EQ', AttributeValueList: [ item3.d ] }, + }, Limit: 2, Select: 'COUNT' }), function (err, res) { if (err) return done(err) res.statusCode.should.equal(200) - res.body.should.eql({Count: 1, ScannedCount: 2, LastEvaluatedKey: {a: item3.a, b: item3.b}}) + res.body.should.eql({ Count: 1, ScannedCount: 2, LastEvaluatedKey: { a: item3.a, b: item3.b } }) done() }) }) }) - it('should not return LastEvaluatedKey if Limit is at least size of response', function(done) { - var item = {a: {S: helpers.randomString()}, b: {S: '1'}, c: {S: 'c'}}, - item2 = {a: item.a, b: {S: '2'}, c: {S: 'c'}}, - item3 = {a: {S: helpers.randomString()}, b: {S: '1'}, c: {S: 'c'}}, - item4 = {a: item3.a, b: {S: '2'}, c: {S: 'c'}} + it('should not return LastEvaluatedKey if Limit is at least size of response', function (done) { + var item = { a: { S: helpers.randomString() }, b: { S: '1' }, c: { S: 'c' } }, + item2 = { a: item.a, b: { S: '2' }, c: { S: 'c' } }, + item3 = { a: { S: helpers.randomString() }, b: { S: '1' }, c: { S: 'c' } }, + item4 = { a: item3.a, b: { S: '2' }, c: { S: 'c' } } - helpers.replaceTable(helpers.testRangeTable, ['a', 'b'], [item, item2, item3, item4], function(err) { + helpers.replaceTable(helpers.testRangeTable, [ 'a', 'b' ], [ item, item2, item3, item4 ], function (err) { if (err) return done(err) - request(helpers.opts('Scan', {TableName: helpers.testRangeTable}), function(err, res) { + request(helpers.opts('Scan', { TableName: helpers.testRangeTable }), function (err, res) { if (err) return done(err) res.statusCode.should.equal(200) var lastHashItem = res.body.Items[res.body.Items.length - 1], - lastHashItems = res.body.Items.filter(function(item) { return item.a.S == lastHashItem.a.S }), - otherHashItem = lastHashItem.a.S == item.a.S ? item3 : item, - otherHashItems = res.body.Items.filter(function(item) { return item.a.S == otherHashItem.a.S }) + lastHashItems = res.body.Items.filter(function (item) { return item.a.S == lastHashItem.a.S }), + otherHashItem = lastHashItem.a.S == item.a.S ? item3 : item, + otherHashItems = res.body.Items.filter(function (item) { return item.a.S == otherHashItem.a.S }) otherHashItems.length.should.equal(2) - request(opts({TableName: helpers.testRangeTable, ConsistentRead: true, KeyConditions: { - a: {ComparisonOperator: 'EQ', AttributeValueList: [lastHashItem.a]}, - }}), function(err, res) { + request(opts({ TableName: helpers.testRangeTable, ConsistentRead: true, KeyConditions: { + a: { ComparisonOperator: 'EQ', AttributeValueList: [ lastHashItem.a ] }, + } }), function (err, res) { if (err) return done(err) res.statusCode.should.equal(200) - res.body.should.eql({Count: lastHashItems.length, ScannedCount: lastHashItems.length, Items: lastHashItems}) - request(opts({TableName: helpers.testRangeTable, ConsistentRead: true, KeyConditions: { - a: {ComparisonOperator: 'EQ', AttributeValueList: [lastHashItem.a]}, - }, Limit: lastHashItems.length}), function(err, res) { + res.body.should.eql({ Count: lastHashItems.length, ScannedCount: lastHashItems.length, Items: lastHashItems }) + request(opts({ TableName: helpers.testRangeTable, ConsistentRead: true, KeyConditions: { + a: { ComparisonOperator: 'EQ', AttributeValueList: [ lastHashItem.a ] }, + }, Limit: lastHashItems.length }), function (err, res) { if (err) return done(err) res.statusCode.should.equal(200) - res.body.should.eql({Count: lastHashItems.length, ScannedCount: lastHashItems.length, Items: lastHashItems, LastEvaluatedKey: {a: lastHashItem.a, b: lastHashItem.b}}) - request(opts({TableName: helpers.testRangeTable, ConsistentRead: true, KeyConditions: { - a: {ComparisonOperator: 'EQ', AttributeValueList: [otherHashItem.a]}, - }, Limit: 2}), function(err, res) { + res.body.should.eql({ Count: lastHashItems.length, ScannedCount: lastHashItems.length, Items: lastHashItems, LastEvaluatedKey: { a: lastHashItem.a, b: lastHashItem.b } }) + request(opts({ TableName: helpers.testRangeTable, ConsistentRead: true, KeyConditions: { + a: { ComparisonOperator: 'EQ', AttributeValueList: [ otherHashItem.a ] }, + }, Limit: 2 }), function (err, res) { if (err) return done(err) res.statusCode.should.equal(200) @@ -2543,70 +2543,70 @@ describe('query', function() { }) }) - it('should return items in order for strings', function(done) { - var item = {a: {S: helpers.randomString()}, b: {S: '1'}}, - item2 = {a: item.a, b: {S: '2'}}, - item3 = {a: item.a, b: {S: '10'}}, - item4 = {a: item.a, b: {S: 'a'}}, - item5 = {a: item.a, b: {S: 'b'}}, - item6 = {a: item.a, b: {S: 'aa'}}, - item7 = {a: item.a, b: {S: 'ab'}}, - item8 = {a: item.a, b: {S: 'A'}}, - item9 = {a: item.a, b: {S: 'B'}}, - items = [item, item2, item3, item4, item5, item6, item7, item8, item9] - helpers.batchBulkPut(helpers.testRangeTable, items, function(err) { + it('should return items in order for strings', function (done) { + var item = { a: { S: helpers.randomString() }, b: { S: '1' } }, + item2 = { a: item.a, b: { S: '2' } }, + item3 = { a: item.a, b: { S: '10' } }, + item4 = { a: item.a, b: { S: 'a' } }, + item5 = { a: item.a, b: { S: 'b' } }, + item6 = { a: item.a, b: { S: 'aa' } }, + item7 = { a: item.a, b: { S: 'ab' } }, + item8 = { a: item.a, b: { S: 'A' } }, + item9 = { a: item.a, b: { S: 'B' } }, + items = [ item, item2, item3, item4, item5, item6, item7, item8, item9 ] + helpers.batchBulkPut(helpers.testRangeTable, items, function (err) { if (err) return done(err) - request(opts({TableName: helpers.testRangeTable, ConsistentRead: true, KeyConditions: { - a: {ComparisonOperator: 'EQ', AttributeValueList: [item.a]}, - }}), function(err, res) { + request(opts({ TableName: helpers.testRangeTable, ConsistentRead: true, KeyConditions: { + a: { ComparisonOperator: 'EQ', AttributeValueList: [ item.a ] }, + } }), function (err, res) { if (err) return done(err) res.statusCode.should.equal(200) - res.body.should.eql({Count: 9, ScannedCount: 9, Items: [item, item3, item2, item8, item9, item4, item6, item7, item5]}) + res.body.should.eql({ Count: 9, ScannedCount: 9, Items: [ item, item3, item2, item8, item9, item4, item6, item7, item5 ] }) done() }) }) }) - it('should return items in order for secondary index strings', function(done) { - var item = {a: {S: helpers.randomString()}, b: {S: '1'}, c: {S: '1'}, d: {S: '1'}}, - item2 = {a: item.a, b: {S: '2'}, c: {S: '2'}}, - item3 = {a: item.a, b: {S: '3'}, c: {S: '10'}}, - item4 = {a: item.a, b: {S: '4'}, c: {S: 'a'}}, - item5 = {a: item.a, b: {S: '5'}, c: {S: 'b'}}, - item6 = {a: item.a, b: {S: '6'}, c: {S: 'aa'}, e: {S: '6'}}, - item7 = {a: item.a, b: {S: '7'}, c: {S: 'ab'}}, - item8 = {a: item.a, b: {S: '8'}, c: {S: 'A'}}, - item9 = {a: item.a, b: {S: '9'}, c: {S: 'B'}}, - items = [item, item2, item3, item4, item5, item6, item7, item8, item9] - helpers.batchBulkPut(helpers.testRangeTable, items, function(err) { + it('should return items in order for secondary index strings', function (done) { + var item = { a: { S: helpers.randomString() }, b: { S: '1' }, c: { S: '1' }, d: { S: '1' } }, + item2 = { a: item.a, b: { S: '2' }, c: { S: '2' } }, + item3 = { a: item.a, b: { S: '3' }, c: { S: '10' } }, + item4 = { a: item.a, b: { S: '4' }, c: { S: 'a' } }, + item5 = { a: item.a, b: { S: '5' }, c: { S: 'b' } }, + item6 = { a: item.a, b: { S: '6' }, c: { S: 'aa' }, e: { S: '6' } }, + item7 = { a: item.a, b: { S: '7' }, c: { S: 'ab' } }, + item8 = { a: item.a, b: { S: '8' }, c: { S: 'A' } }, + item9 = { a: item.a, b: { S: '9' }, c: { S: 'B' } }, + items = [ item, item2, item3, item4, item5, item6, item7, item8, item9 ] + helpers.batchBulkPut(helpers.testRangeTable, items, function (err) { if (err) return done(err) - var req = {TableName: helpers.testRangeTable, IndexName: 'index1', - KeyConditions: {a: {ComparisonOperator: 'EQ', AttributeValueList: [item.a]}}, ReturnConsumedCapacity: 'TOTAL'} - request(opts(req), function(err, res) { + var req = { TableName: helpers.testRangeTable, IndexName: 'index1', + KeyConditions: { a: { ComparisonOperator: 'EQ', AttributeValueList: [ item.a ] } }, ReturnConsumedCapacity: 'TOTAL' } + request(opts(req), function (err, res) { if (err) return done(err) res.statusCode.should.equal(200) res.body.should.eql({ Count: 9, ScannedCount: 9, - Items: [item, item3, item2, item8, item9, item4, item6, item7, item5], + Items: [ item, item3, item2, item8, item9, item4, item6, item7, item5 ], ConsumedCapacity: { CapacityUnits: 0.5, TableName: helpers.testRangeTable, }, }) req.ReturnConsumedCapacity = 'INDEXES' - request(opts(req), function(err, res) { + request(opts(req), function (err, res) { if (err) return done(err) res.statusCode.should.equal(200) res.body.should.eql({ Count: 9, ScannedCount: 9, - Items: [item, item3, item2, item8, item9, item4, item6, item7, item5], + Items: [ item, item3, item2, item8, item9, item4, item6, item7, item5 ], ConsumedCapacity: { CapacityUnits: 0.5, TableName: helpers.testRangeTable, - Table: {CapacityUnits: 0}, - LocalSecondaryIndexes: {index1: {CapacityUnits: 0.5}}, + Table: { CapacityUnits: 0 }, + LocalSecondaryIndexes: { index1: { CapacityUnits: 0.5 } }, }, }) done() @@ -2615,78 +2615,78 @@ describe('query', function() { }) }) - it('should calculate comparisons correctly for secondary indexes', function(done) { - var item = {a: {S: helpers.randomString()}, b: {S: '1'}, c: {S: '1'}, d: {S: '1'}}, - item2 = {a: item.a, b: {S: '2'}, c: {S: '2'}}, - item3 = {a: item.a, b: {S: '3'}, c: {S: '10'}}, - item4 = {a: item.a, b: {S: '4'}, c: {S: 'a'}}, - item5 = {a: item.a, b: {S: '5'}, c: {S: 'b'}}, - item6 = {a: item.a, b: {S: '6'}, c: {S: 'aa'}, e: {S: '6'}}, - item7 = {a: item.a, b: {S: '7'}, c: {S: 'ab'}}, - item8 = {a: item.a, b: {S: '8'}, c: {S: 'A'}}, - item9 = {a: item.a, b: {S: '9'}, c: {S: 'B'}}, - items = [item, item2, item3, item4, item5, item6, item7, item8, item9] - helpers.batchBulkPut(helpers.testRangeTable, items, function(err) { + it('should calculate comparisons correctly for secondary indexes', function (done) { + var item = { a: { S: helpers.randomString() }, b: { S: '1' }, c: { S: '1' }, d: { S: '1' } }, + item2 = { a: item.a, b: { S: '2' }, c: { S: '2' } }, + item3 = { a: item.a, b: { S: '3' }, c: { S: '10' } }, + item4 = { a: item.a, b: { S: '4' }, c: { S: 'a' } }, + item5 = { a: item.a, b: { S: '5' }, c: { S: 'b' } }, + item6 = { a: item.a, b: { S: '6' }, c: { S: 'aa' }, e: { S: '6' } }, + item7 = { a: item.a, b: { S: '7' }, c: { S: 'ab' } }, + item8 = { a: item.a, b: { S: '8' }, c: { S: 'A' } }, + item9 = { a: item.a, b: { S: '9' }, c: { S: 'B' } }, + items = [ item, item2, item3, item4, item5, item6, item7, item8, item9 ] + helpers.batchBulkPut(helpers.testRangeTable, items, function (err) { if (err) return done(err) var req = { TableName: helpers.testRangeTable, IndexName: 'index1', KeyConditionExpression: 'a = :a AND c <= :c', - ExpressionAttributeValues: {':a': item.a, ':c': item4.c}, + ExpressionAttributeValues: { ':a': item.a, ':c': item4.c }, } - request(opts(req), function(err, res) { + request(opts(req), function (err, res) { if (err) return done(err) res.statusCode.should.equal(200) res.body.should.eql({ Count: 6, ScannedCount: 6, - Items: [item, item3, item2, item8, item9, item4], + Items: [ item, item3, item2, item8, item9, item4 ], }) req.KeyConditionExpression = 'a = :a AND c = :c' - request(opts(req), function(err, res) { + request(opts(req), function (err, res) { if (err) return done(err) res.statusCode.should.equal(200) res.body.should.eql({ Count: 1, ScannedCount: 1, - Items: [item4], + Items: [ item4 ], }) req.KeyConditionExpression = 'a = :a AND c >= :c' - request(opts(req), function(err, res) { + request(opts(req), function (err, res) { if (err) return done(err) res.statusCode.should.equal(200) res.body.should.eql({ Count: 4, ScannedCount: 4, - Items: [item4, item6, item7, item5], + Items: [ item4, item6, item7, item5 ], }) req.KeyConditionExpression = 'a = :a AND c > :c' - request(opts(req), function(err, res) { + request(opts(req), function (err, res) { if (err) return done(err) res.statusCode.should.equal(200) res.body.should.eql({ Count: 3, ScannedCount: 3, - Items: [item6, item7, item5], + Items: [ item6, item7, item5 ], }) req.KeyConditionExpression = 'a = :a AND c < :c' - request(opts(req), function(err, res) { + request(opts(req), function (err, res) { if (err) return done(err) res.statusCode.should.equal(200) res.body.should.eql({ Count: 5, ScannedCount: 5, - Items: [item, item3, item2, item8, item9], + Items: [ item, item3, item2, item8, item9 ], }) req.KeyConditionExpression = 'a = :a AND c BETWEEN :c AND :d' req.ExpressionAttributeValues[':d'] = item7.c - request(opts(req), function(err, res) { + request(opts(req), function (err, res) { if (err) return done(err) res.statusCode.should.equal(200) res.body.should.eql({ Count: 3, ScannedCount: 3, - Items: [item4, item6, item7], + Items: [ item4, item6, item7 ], }) done() }) @@ -2698,255 +2698,255 @@ describe('query', function() { }) }) - it('should return items in order for numbers', function(done) { - var item = {a: {S: helpers.randomString()}, b: {N: '0'}}, - item2 = {a: item.a, b: {N: '99.1'}}, - item3 = {a: item.a, b: {N: '10.9'}}, - item4 = {a: item.a, b: {N: '10.1'}}, - item5 = {a: item.a, b: {N: '9.1'}}, - item6 = {a: item.a, b: {N: '9'}}, - item7 = {a: item.a, b: {N: '1.9'}}, - item8 = {a: item.a, b: {N: '1.1'}}, - item9 = {a: item.a, b: {N: '1'}}, - item10 = {a: item.a, b: {N: '0.9'}}, - item11 = {a: item.a, b: {N: '0.1'}}, - item12 = {a: item.a, b: {N: '0.09'}}, - item13 = {a: item.a, b: {N: '0.01'}}, - item14 = {a: item.a, b: {N: '-0.01'}}, - item15 = {a: item.a, b: {N: '-0.09'}}, - item16 = {a: item.a, b: {N: '-0.1'}}, - item17 = {a: item.a, b: {N: '-0.9'}}, - item18 = {a: item.a, b: {N: '-1'}}, - item19 = {a: item.a, b: {N: '-1.01'}}, - item20 = {a: item.a, b: {N: '-9'}}, - item21 = {a: item.a, b: {N: '-9.9'}}, - item22 = {a: item.a, b: {N: '-10.1'}}, - item23 = {a: item.a, b: {N: '-99.1'}}, - items = [item, item2, item3, item4, item5, item6, item7, item8, item9, item10, item11, item12, - item13, item14, item15, item16, item17, item18, item19, item20, item21, item22, item23] - helpers.batchBulkPut(helpers.testRangeNTable, items, function(err) { + it('should return items in order for numbers', function (done) { + var item = { a: { S: helpers.randomString() }, b: { N: '0' } }, + item2 = { a: item.a, b: { N: '99.1' } }, + item3 = { a: item.a, b: { N: '10.9' } }, + item4 = { a: item.a, b: { N: '10.1' } }, + item5 = { a: item.a, b: { N: '9.1' } }, + item6 = { a: item.a, b: { N: '9' } }, + item7 = { a: item.a, b: { N: '1.9' } }, + item8 = { a: item.a, b: { N: '1.1' } }, + item9 = { a: item.a, b: { N: '1' } }, + item10 = { a: item.a, b: { N: '0.9' } }, + item11 = { a: item.a, b: { N: '0.1' } }, + item12 = { a: item.a, b: { N: '0.09' } }, + item13 = { a: item.a, b: { N: '0.01' } }, + item14 = { a: item.a, b: { N: '-0.01' } }, + item15 = { a: item.a, b: { N: '-0.09' } }, + item16 = { a: item.a, b: { N: '-0.1' } }, + item17 = { a: item.a, b: { N: '-0.9' } }, + item18 = { a: item.a, b: { N: '-1' } }, + item19 = { a: item.a, b: { N: '-1.01' } }, + item20 = { a: item.a, b: { N: '-9' } }, + item21 = { a: item.a, b: { N: '-9.9' } }, + item22 = { a: item.a, b: { N: '-10.1' } }, + item23 = { a: item.a, b: { N: '-99.1' } }, + items = [ item, item2, item3, item4, item5, item6, item7, item8, item9, item10, item11, item12, + item13, item14, item15, item16, item17, item18, item19, item20, item21, item22, item23 ] + helpers.batchBulkPut(helpers.testRangeNTable, items, function (err) { if (err) return done(err) - request(opts({TableName: helpers.testRangeNTable, ConsistentRead: true, KeyConditions: { - a: {ComparisonOperator: 'EQ', AttributeValueList: [item.a]}, - }}), function(err, res) { + request(opts({ TableName: helpers.testRangeNTable, ConsistentRead: true, KeyConditions: { + a: { ComparisonOperator: 'EQ', AttributeValueList: [ item.a ] }, + } }), function (err, res) { if (err) return done(err) res.statusCode.should.equal(200) - res.body.should.eql({Count: 23, ScannedCount: 23, Items: [item23, item22, item21, item20, item19, item18, item17, item16, item15, - item14, item, item13, item12, item11, item10, item9, item8, item7, item6, item5, item4, item3, item2]}) + res.body.should.eql({ Count: 23, ScannedCount: 23, Items: [ item23, item22, item21, item20, item19, item18, item17, item16, item15, + item14, item, item13, item12, item11, item10, item9, item8, item7, item6, item5, item4, item3, item2 ] }) done() }) }) }) - it('should return items in order for binary', function(done) { - var item = {a: {S: helpers.randomString()}, b: {B: '1Py5xA=='}}, - item2 = {a: item.a, b: {B: 'JA=='}}, - item3 = {a: item.a, b: {B: '2w=='}}, - item4 = {a: item.a, b: {B: 'cAeRhZE='}}, - item5 = {a: item.a, b: {B: '6piVtA=='}}, - item6 = {a: item.a, b: {B: 'MjA0'}}, - item7 = {a: item.a, b: {B: '1g=='}}, - item8 = {a: item.a, b: {B: 'ER/jLQ=='}}, - item9 = {a: item.a, b: {B: 'T7MzEUw='}}, - item10 = {a: item.a, b: {B: '9FkiOH0='}}, - item11 = {a: item.a, b: {B: 'Iv/a'}}, - item12 = {a: item.a, b: {B: '9V0='}}, - items = [item, item2, item3, item4, item5, item6, item7, item8, item9, item10, item11, item12] - helpers.batchBulkPut(helpers.testRangeBTable, items, function(err) { + it('should return items in order for binary', function (done) { + var item = { a: { S: helpers.randomString() }, b: { B: '1Py5xA==' } }, + item2 = { a: item.a, b: { B: 'JA==' } }, + item3 = { a: item.a, b: { B: '2w==' } }, + item4 = { a: item.a, b: { B: 'cAeRhZE=' } }, + item5 = { a: item.a, b: { B: '6piVtA==' } }, + item6 = { a: item.a, b: { B: 'MjA0' } }, + item7 = { a: item.a, b: { B: '1g==' } }, + item8 = { a: item.a, b: { B: 'ER/jLQ==' } }, + item9 = { a: item.a, b: { B: 'T7MzEUw=' } }, + item10 = { a: item.a, b: { B: '9FkiOH0=' } }, + item11 = { a: item.a, b: { B: 'Iv/a' } }, + item12 = { a: item.a, b: { B: '9V0=' } }, + items = [ item, item2, item3, item4, item5, item6, item7, item8, item9, item10, item11, item12 ] + helpers.batchBulkPut(helpers.testRangeBTable, items, function (err) { if (err) return done(err) - request(opts({TableName: helpers.testRangeBTable, ConsistentRead: true, KeyConditions: { - a: {ComparisonOperator: 'EQ', AttributeValueList: [item.a]}, - }}), function(err, res) { + request(opts({ TableName: helpers.testRangeBTable, ConsistentRead: true, KeyConditions: { + a: { ComparisonOperator: 'EQ', AttributeValueList: [ item.a ] }, + } }), function (err, res) { if (err) return done(err) res.statusCode.should.equal(200) - res.body.should.eql({Count: 12, ScannedCount: 12, Items: [item8, item11, item2, item6, item9, item4, - item, item7, item3, item5, item10, item12]}) + res.body.should.eql({ Count: 12, ScannedCount: 12, Items: [ item8, item11, item2, item6, item9, item4, + item, item7, item3, item5, item10, item12 ] }) done() }) }) }) - it('should return items in reverse order for strings', function(done) { - var item = {a: {S: helpers.randomString()}, b: {S: '1'}}, - item2 = {a: item.a, b: {S: '2'}}, - item3 = {a: item.a, b: {S: '10'}}, - items = [item, item2, item3] - helpers.batchBulkPut(helpers.testRangeTable, items, function(err) { + it('should return items in reverse order for strings', function (done) { + var item = { a: { S: helpers.randomString() }, b: { S: '1' } }, + item2 = { a: item.a, b: { S: '2' } }, + item3 = { a: item.a, b: { S: '10' } }, + items = [ item, item2, item3 ] + helpers.batchBulkPut(helpers.testRangeTable, items, function (err) { if (err) return done(err) - request(opts({TableName: helpers.testRangeTable, ConsistentRead: true, KeyConditions: { - a: {ComparisonOperator: 'EQ', AttributeValueList: [item.a]}, - }, ScanIndexForward: false}), function(err, res) { + request(opts({ TableName: helpers.testRangeTable, ConsistentRead: true, KeyConditions: { + a: { ComparisonOperator: 'EQ', AttributeValueList: [ item.a ] }, + }, ScanIndexForward: false }), function (err, res) { if (err) return done(err) res.statusCode.should.equal(200) - res.body.should.eql({Count: 3, ScannedCount: 3, Items: [item2, item3, item]}) + res.body.should.eql({ Count: 3, ScannedCount: 3, Items: [ item2, item3, item ] }) done() }) }) }) - it('should return items in reverse order with Limit for strings', function(done) { - var item = {a: {S: helpers.randomString()}, b: {S: '1'}}, - item2 = {a: item.a, b: {S: '2'}}, - item3 = {a: item.a, b: {S: '10'}}, - items = [item, item2, item3] - helpers.batchBulkPut(helpers.testRangeTable, items, function(err) { + it('should return items in reverse order with Limit for strings', function (done) { + var item = { a: { S: helpers.randomString() }, b: { S: '1' } }, + item2 = { a: item.a, b: { S: '2' } }, + item3 = { a: item.a, b: { S: '10' } }, + items = [ item, item2, item3 ] + helpers.batchBulkPut(helpers.testRangeTable, items, function (err) { if (err) return done(err) - request(opts({TableName: helpers.testRangeTable, ConsistentRead: true, KeyConditions: { - a: {ComparisonOperator: 'EQ', AttributeValueList: [item.a]}, - }, ScanIndexForward: false, Limit: 2}), function(err, res) { + request(opts({ TableName: helpers.testRangeTable, ConsistentRead: true, KeyConditions: { + a: { ComparisonOperator: 'EQ', AttributeValueList: [ item.a ] }, + }, ScanIndexForward: false, Limit: 2 }), function (err, res) { if (err) return done(err) res.statusCode.should.equal(200) - res.body.should.eql({Count: 2, ScannedCount: 2, Items: [item2, item3], LastEvaluatedKey: item3}) + res.body.should.eql({ Count: 2, ScannedCount: 2, Items: [ item2, item3 ], LastEvaluatedKey: item3 }) done() }) }) }) - it('should return items in reverse order with ExclusiveStartKey for strings', function(done) { - var item = {a: {S: helpers.randomString()}, b: {S: '1'}}, - item2 = {a: item.a, b: {S: '2'}}, - item3 = {a: item.a, b: {S: '10'}}, - items = [item, item2, item3] - helpers.batchBulkPut(helpers.testRangeTable, items, function(err) { + it('should return items in reverse order with ExclusiveStartKey for strings', function (done) { + var item = { a: { S: helpers.randomString() }, b: { S: '1' } }, + item2 = { a: item.a, b: { S: '2' } }, + item3 = { a: item.a, b: { S: '10' } }, + items = [ item, item2, item3 ] + helpers.batchBulkPut(helpers.testRangeTable, items, function (err) { if (err) return done(err) - request(opts({TableName: helpers.testRangeTable, ConsistentRead: true, KeyConditions: { - a: {ComparisonOperator: 'EQ', AttributeValueList: [item.a]}, - }, ScanIndexForward: false, ExclusiveStartKey: item2}), function(err, res) { + request(opts({ TableName: helpers.testRangeTable, ConsistentRead: true, KeyConditions: { + a: { ComparisonOperator: 'EQ', AttributeValueList: [ item.a ] }, + }, ScanIndexForward: false, ExclusiveStartKey: item2 }), function (err, res) { if (err) return done(err) res.statusCode.should.equal(200) - res.body.should.eql({Count: 2, ScannedCount: 2, Items: [item3, item]}) + res.body.should.eql({ Count: 2, ScannedCount: 2, Items: [ item3, item ] }) done() }) }) }) - it('should return items in reverse order for numbers', function(done) { - var item = {a: {S: helpers.randomString()}, b: {N: '0'}}, - item2 = {a: item.a, b: {N: '99.1'}}, - item3 = {a: item.a, b: {N: '10.9'}}, - item4 = {a: item.a, b: {N: '9.1'}}, - item5 = {a: item.a, b: {N: '0.9'}}, - item6 = {a: item.a, b: {N: '-0.01'}}, - item7 = {a: item.a, b: {N: '-0.1'}}, - item8 = {a: item.a, b: {N: '-1'}}, - item9 = {a: item.a, b: {N: '-99.1'}}, - items = [item, item2, item3, item4, item5, item6, item7, item8, item9] - helpers.batchBulkPut(helpers.testRangeNTable, items, function(err) { + it('should return items in reverse order for numbers', function (done) { + var item = { a: { S: helpers.randomString() }, b: { N: '0' } }, + item2 = { a: item.a, b: { N: '99.1' } }, + item3 = { a: item.a, b: { N: '10.9' } }, + item4 = { a: item.a, b: { N: '9.1' } }, + item5 = { a: item.a, b: { N: '0.9' } }, + item6 = { a: item.a, b: { N: '-0.01' } }, + item7 = { a: item.a, b: { N: '-0.1' } }, + item8 = { a: item.a, b: { N: '-1' } }, + item9 = { a: item.a, b: { N: '-99.1' } }, + items = [ item, item2, item3, item4, item5, item6, item7, item8, item9 ] + helpers.batchBulkPut(helpers.testRangeNTable, items, function (err) { if (err) return done(err) - request(opts({TableName: helpers.testRangeNTable, ConsistentRead: true, KeyConditions: { - a: {ComparisonOperator: 'EQ', AttributeValueList: [item.a]}, - }, ScanIndexForward: false}), function(err, res) { + request(opts({ TableName: helpers.testRangeNTable, ConsistentRead: true, KeyConditions: { + a: { ComparisonOperator: 'EQ', AttributeValueList: [ item.a ] }, + }, ScanIndexForward: false }), function (err, res) { if (err) return done(err) res.statusCode.should.equal(200) - res.body.should.eql({Count: 9, ScannedCount: 9, Items: [item2, item3, item4, item5, item, item6, item7, item8, item9]}) + res.body.should.eql({ Count: 9, ScannedCount: 9, Items: [ item2, item3, item4, item5, item, item6, item7, item8, item9 ] }) done() }) }) }) - it('should return items in reverse order with Limit for numbers', function(done) { - var item = {a: {S: helpers.randomString()}, b: {N: '0'}}, - item2 = {a: item.a, b: {N: '99.1'}, c: {S: 'c'}}, - item3 = {a: item.a, b: {N: '10.9'}, c: {S: 'c'}}, - item4 = {a: item.a, b: {N: '9.1'}, c: {S: 'c'}}, - item5 = {a: item.a, b: {N: '0.9'}, c: {S: 'c'}}, - items = [item, item2, item3, item4, item5] - helpers.batchBulkPut(helpers.testRangeNTable, items, function(err) { + it('should return items in reverse order with Limit for numbers', function (done) { + var item = { a: { S: helpers.randomString() }, b: { N: '0' } }, + item2 = { a: item.a, b: { N: '99.1' }, c: { S: 'c' } }, + item3 = { a: item.a, b: { N: '10.9' }, c: { S: 'c' } }, + item4 = { a: item.a, b: { N: '9.1' }, c: { S: 'c' } }, + item5 = { a: item.a, b: { N: '0.9' }, c: { S: 'c' } }, + items = [ item, item2, item3, item4, item5 ] + helpers.batchBulkPut(helpers.testRangeNTable, items, function (err) { if (err) return done(err) - request(opts({TableName: helpers.testRangeNTable, ConsistentRead: true, KeyConditions: { - a: {ComparisonOperator: 'EQ', AttributeValueList: [item.a]}, - }, ScanIndexForward: false, Limit: 3}), function(err, res) { + request(opts({ TableName: helpers.testRangeNTable, ConsistentRead: true, KeyConditions: { + a: { ComparisonOperator: 'EQ', AttributeValueList: [ item.a ] }, + }, ScanIndexForward: false, Limit: 3 }), function (err, res) { if (err) return done(err) res.statusCode.should.equal(200) - res.body.should.eql({Count: 3, ScannedCount: 3, Items: [item2, item3, item4], LastEvaluatedKey: {a: item4.a, b: item4.b}}) + res.body.should.eql({ Count: 3, ScannedCount: 3, Items: [ item2, item3, item4 ], LastEvaluatedKey: { a: item4.a, b: item4.b } }) done() }) }) }) - it('should return items in reverse order for binary', function(done) { - var item = {a: {S: helpers.randomString()}, b: {B: '1Py5xA=='}}, - item2 = {a: item.a, b: {B: 'JA=='}}, - item3 = {a: item.a, b: {B: '2w=='}}, - item4 = {a: item.a, b: {B: 'cAeRhZE='}}, - item5 = {a: item.a, b: {B: '6piVtA=='}}, - item6 = {a: item.a, b: {B: 'MjA0'}}, - item7 = {a: item.a, b: {B: '1g=='}}, - item8 = {a: item.a, b: {B: 'ER/jLQ=='}}, - item9 = {a: item.a, b: {B: 'T7MzEUw='}}, - items = [item, item2, item3, item4, item5, item6, item7, item8, item9] - helpers.batchBulkPut(helpers.testRangeBTable, items, function(err) { + it('should return items in reverse order for binary', function (done) { + var item = { a: { S: helpers.randomString() }, b: { B: '1Py5xA==' } }, + item2 = { a: item.a, b: { B: 'JA==' } }, + item3 = { a: item.a, b: { B: '2w==' } }, + item4 = { a: item.a, b: { B: 'cAeRhZE=' } }, + item5 = { a: item.a, b: { B: '6piVtA==' } }, + item6 = { a: item.a, b: { B: 'MjA0' } }, + item7 = { a: item.a, b: { B: '1g==' } }, + item8 = { a: item.a, b: { B: 'ER/jLQ==' } }, + item9 = { a: item.a, b: { B: 'T7MzEUw=' } }, + items = [ item, item2, item3, item4, item5, item6, item7, item8, item9 ] + helpers.batchBulkPut(helpers.testRangeBTable, items, function (err) { if (err) return done(err) - request(opts({TableName: helpers.testRangeBTable, ConsistentRead: true, KeyConditions: { - a: {ComparisonOperator: 'EQ', AttributeValueList: [item.a]}, - }, ScanIndexForward: false}), function(err, res) { + request(opts({ TableName: helpers.testRangeBTable, ConsistentRead: true, KeyConditions: { + a: { ComparisonOperator: 'EQ', AttributeValueList: [ item.a ] }, + }, ScanIndexForward: false }), function (err, res) { if (err) return done(err) res.statusCode.should.equal(200) - res.body.should.eql({Count: 9, ScannedCount: 9, Items: [item5, item3, item7, item, item4, item9, - item6, item2, item8]}) + res.body.should.eql({ Count: 9, ScannedCount: 9, Items: [ item5, item3, item7, item, item4, item9, + item6, item2, item8 ] }) done() }) }) }) - it('should return items in reverse order with Limit for binary', function(done) { - var item = {a: {S: helpers.randomString()}, b: {B: '1Py5xA=='}}, - item2 = {a: item.a, b: {B: 'JA=='}}, - item3 = {a: item.a, b: {B: '2w=='}}, - item4 = {a: item.a, b: {B: 'cAeRhZE='}}, - item5 = {a: item.a, b: {B: '6piVtA=='}}, - items = [item, item2, item3, item4, item5] - helpers.batchBulkPut(helpers.testRangeBTable, items, function(err) { + it('should return items in reverse order with Limit for binary', function (done) { + var item = { a: { S: helpers.randomString() }, b: { B: '1Py5xA==' } }, + item2 = { a: item.a, b: { B: 'JA==' } }, + item3 = { a: item.a, b: { B: '2w==' } }, + item4 = { a: item.a, b: { B: 'cAeRhZE=' } }, + item5 = { a: item.a, b: { B: '6piVtA==' } }, + items = [ item, item2, item3, item4, item5 ] + helpers.batchBulkPut(helpers.testRangeBTable, items, function (err) { if (err) return done(err) - request(opts({TableName: helpers.testRangeBTable, ConsistentRead: true, KeyConditions: { - a: {ComparisonOperator: 'EQ', AttributeValueList: [item.a]}, - }, ScanIndexForward: false, Limit: 3}), function(err, res) { + request(opts({ TableName: helpers.testRangeBTable, ConsistentRead: true, KeyConditions: { + a: { ComparisonOperator: 'EQ', AttributeValueList: [ item.a ] }, + }, ScanIndexForward: false, Limit: 3 }), function (err, res) { if (err) return done(err) res.statusCode.should.equal(200) - res.body.should.eql({Count: 3, ScannedCount: 3, Items: [item5, item3, item], LastEvaluatedKey: {a: item.a, b: item.b}}) + res.body.should.eql({ Count: 3, ScannedCount: 3, Items: [ item5, item3, item ], LastEvaluatedKey: { a: item.a, b: item.b } }) done() }) }) }) - it('should query on basic hash global index', function(done) { - var item = {a: {S: 'a'}, b: {S: 'a'}, c: {S: helpers.randomString()}, d: {S: 'a'}}, - item2 = {a: {S: 'b'}, b: {S: 'b'}, c: item.c, d: {S: 'a'}}, - item3 = {a: {S: 'c'}, b: {S: 'e'}, c: item.c, d: {S: 'a'}}, - item4 = {a: {S: 'c'}, b: {S: 'd'}, c: item.c, d: {S: 'a'}}, - item5 = {a: {S: 'c'}, b: {S: 'c'}, c: {S: 'c'}, d: {S: 'a'}}, - item6 = {a: {S: 'd'}, b: {S: 'a'}, c: item.c, d: {S: 'a'}}, - item7 = {a: {S: 'e'}, b: {S: 'a'}, c: item.c, d: {S: 'a'}}, - items = [item, item2, item3, item4, item5, item6, item7] - helpers.batchBulkPut(helpers.testRangeTable, items, function(err) { + it('should query on basic hash global index', function (done) { + var item = { a: { S: 'a' }, b: { S: 'a' }, c: { S: helpers.randomString() }, d: { S: 'a' } }, + item2 = { a: { S: 'b' }, b: { S: 'b' }, c: item.c, d: { S: 'a' } }, + item3 = { a: { S: 'c' }, b: { S: 'e' }, c: item.c, d: { S: 'a' } }, + item4 = { a: { S: 'c' }, b: { S: 'd' }, c: item.c, d: { S: 'a' } }, + item5 = { a: { S: 'c' }, b: { S: 'c' }, c: { S: 'c' }, d: { S: 'a' } }, + item6 = { a: { S: 'd' }, b: { S: 'a' }, c: item.c, d: { S: 'a' } }, + item7 = { a: { S: 'e' }, b: { S: 'a' }, c: item.c, d: { S: 'a' } }, + items = [ item, item2, item3, item4, item5, item6, item7 ] + helpers.batchBulkPut(helpers.testRangeTable, items, function (err) { if (err) return done(err) - var req = {TableName: helpers.testRangeTable, - KeyConditions: {c: {ComparisonOperator: 'EQ', AttributeValueList: [item.c]}}, - IndexName: 'index3', Limit: 4, ReturnConsumedCapacity: 'TOTAL'} - request(opts(req), function(err, res) { + var req = { TableName: helpers.testRangeTable, + KeyConditions: { c: { ComparisonOperator: 'EQ', AttributeValueList: [ item.c ] } }, + IndexName: 'index3', Limit: 4, ReturnConsumedCapacity: 'TOTAL' } + request(opts(req), function (err, res) { if (err) return done(err) res.statusCode.should.equal(200) res.body.should.eql({ Count: 4, ScannedCount: 4, - Items: [item2, item, item3, item7], - LastEvaluatedKey: {a: item7.a, b: item7.b, c: item7.c}, - ConsumedCapacity: {CapacityUnits: 0.5, TableName: helpers.testRangeTable}, + Items: [ item2, item, item3, item7 ], + LastEvaluatedKey: { a: item7.a, b: item7.b, c: item7.c }, + ConsumedCapacity: { CapacityUnits: 0.5, TableName: helpers.testRangeTable }, }) req.ReturnConsumedCapacity = 'INDEXES' - request(opts(req), function(err, res) { + request(opts(req), function (err, res) { if (err) return done(err) res.statusCode.should.equal(200) res.body.should.eql({ Count: 4, ScannedCount: 4, - Items: [item2, item, item3, item7], - LastEvaluatedKey: {a: item7.a, b: item7.b, c: item7.c}, + Items: [ item2, item, item3, item7 ], + LastEvaluatedKey: { a: item7.a, b: item7.b, c: item7.c }, ConsumedCapacity: { CapacityUnits: 0.5, TableName: helpers.testRangeTable, - Table: {CapacityUnits: 0}, - GlobalSecondaryIndexes: {index3: {CapacityUnits: 0.5}}, + Table: { CapacityUnits: 0 }, + GlobalSecondaryIndexes: { index3: { CapacityUnits: 0.5 } }, }, }) done() @@ -2955,33 +2955,33 @@ describe('query', function() { }) }) - it('should query in reverse on basic hash global index', function(done) { - var item = {a: {S: 'a'}, b: {S: 'a'}, c: {S: helpers.randomString()}}, - item2 = {a: {S: 'b'}, b: {S: 'b'}, c: item.c}, - item3 = {a: {S: 'c'}, b: {S: 'e'}, c: item.c}, - item4 = {a: {S: 'c'}, b: {S: 'd'}, c: item.c}, - item5 = {a: {S: 'c'}, b: {S: 'c'}, c: {S: 'c'}}, - item6 = {a: {S: 'd'}, b: {S: 'a'}, c: item.c}, - item7 = {a: {S: 'e'}, b: {S: 'a'}, c: item.c}, - items = [item, item2, item3, item4, item5, item6, item7] - helpers.batchBulkPut(helpers.testRangeTable, items, function(err) { + it('should query in reverse on basic hash global index', function (done) { + var item = { a: { S: 'a' }, b: { S: 'a' }, c: { S: helpers.randomString() } }, + item2 = { a: { S: 'b' }, b: { S: 'b' }, c: item.c }, + item3 = { a: { S: 'c' }, b: { S: 'e' }, c: item.c }, + item4 = { a: { S: 'c' }, b: { S: 'd' }, c: item.c }, + item5 = { a: { S: 'c' }, b: { S: 'c' }, c: { S: 'c' } }, + item6 = { a: { S: 'd' }, b: { S: 'a' }, c: item.c }, + item7 = { a: { S: 'e' }, b: { S: 'a' }, c: item.c }, + items = [ item, item2, item3, item4, item5, item6, item7 ] + helpers.batchBulkPut(helpers.testRangeTable, items, function (err) { if (err) return done(err) - var req = {TableName: helpers.testRangeTable, - KeyConditions: {c: {ComparisonOperator: 'EQ', AttributeValueList: [item.c]}}, - IndexName: 'index3', ScanIndexForward: false, Limit: 4, ReturnConsumedCapacity: 'INDEXES'} - request(opts(req), function(err, res) { + var req = { TableName: helpers.testRangeTable, + KeyConditions: { c: { ComparisonOperator: 'EQ', AttributeValueList: [ item.c ] } }, + IndexName: 'index3', ScanIndexForward: false, Limit: 4, ReturnConsumedCapacity: 'INDEXES' } + request(opts(req), function (err, res) { if (err) return done(err) res.statusCode.should.equal(200) res.body.should.eql({ Count: 4, ScannedCount: 4, - Items: [item4, item6, item7, item3], - LastEvaluatedKey: {a: item3.a, b: item3.b, c: item3.c}, + Items: [ item4, item6, item7, item3 ], + LastEvaluatedKey: { a: item3.a, b: item3.b, c: item3.c }, ConsumedCapacity: { CapacityUnits: 0.5, TableName: helpers.testRangeTable, - Table: {CapacityUnits: 0}, - GlobalSecondaryIndexes: {index3: {CapacityUnits: 0.5}}, + Table: { CapacityUnits: 0 }, + GlobalSecondaryIndexes: { index3: { CapacityUnits: 0.5 } }, }, }) done() @@ -2989,21 +2989,21 @@ describe('query', function() { }) }) - it('should query on range global index', function(done) { - var item = {a: {S: 'a'}, b: {S: 'a'}, c: {S: helpers.randomString()}, d: {S: 'f'}, e: {S: 'a'}, f: {S: 'a'}}, - item2 = {a: {S: 'b'}, b: {S: 'b'}, c: item.c, d: {S: 'a'}, e: {S: 'a'}, f: {S: 'a'}}, - item3 = {a: {S: 'c'}, b: {S: 'e'}, c: item.c, d: {S: 'b'}, e: {S: 'a'}, f: {S: 'a'}}, - item4 = {a: {S: 'c'}, b: {S: 'd'}, c: item.c, d: {S: 'c'}, e: {S: 'a'}, f: {S: 'a'}}, - item5 = {a: {S: 'c'}, b: {S: 'c'}, c: {S: 'c'}, d: {S: 'd'}, e: {S: 'a'}, f: {S: 'a'}}, - item6 = {a: {S: 'd'}, b: {S: 'a'}, c: item.c, d: {S: 'e'}, e: {S: 'a'}, f: {S: 'a'}}, - item7 = {a: {S: 'e'}, b: {S: 'a'}, c: item.c, d: {S: 'f'}, e: {S: 'a'}, f: {S: 'a'}}, - items = [item, item2, item3, item4, item5, item6, item7] - helpers.batchBulkPut(helpers.testRangeTable, items, function(err) { + it('should query on range global index', function (done) { + var item = { a: { S: 'a' }, b: { S: 'a' }, c: { S: helpers.randomString() }, d: { S: 'f' }, e: { S: 'a' }, f: { S: 'a' } }, + item2 = { a: { S: 'b' }, b: { S: 'b' }, c: item.c, d: { S: 'a' }, e: { S: 'a' }, f: { S: 'a' } }, + item3 = { a: { S: 'c' }, b: { S: 'e' }, c: item.c, d: { S: 'b' }, e: { S: 'a' }, f: { S: 'a' } }, + item4 = { a: { S: 'c' }, b: { S: 'd' }, c: item.c, d: { S: 'c' }, e: { S: 'a' }, f: { S: 'a' } }, + item5 = { a: { S: 'c' }, b: { S: 'c' }, c: { S: 'c' }, d: { S: 'd' }, e: { S: 'a' }, f: { S: 'a' } }, + item6 = { a: { S: 'd' }, b: { S: 'a' }, c: item.c, d: { S: 'e' }, e: { S: 'a' }, f: { S: 'a' } }, + item7 = { a: { S: 'e' }, b: { S: 'a' }, c: item.c, d: { S: 'f' }, e: { S: 'a' }, f: { S: 'a' } }, + items = [ item, item2, item3, item4, item5, item6, item7 ] + helpers.batchBulkPut(helpers.testRangeTable, items, function (err) { if (err) return done(err) - request(opts({TableName: helpers.testRangeTable, KeyConditions: { - c: {ComparisonOperator: 'EQ', AttributeValueList: [item.c]}, - d: {ComparisonOperator: 'LT', AttributeValueList: [item.d]}, - }, IndexName: 'index4', Limit: 3, ReturnConsumedCapacity: 'INDEXES'}), function(err, res) { + request(opts({ TableName: helpers.testRangeTable, KeyConditions: { + c: { ComparisonOperator: 'EQ', AttributeValueList: [ item.c ] }, + d: { ComparisonOperator: 'LT', AttributeValueList: [ item.d ] }, + }, IndexName: 'index4', Limit: 3, ReturnConsumedCapacity: 'INDEXES' }), function (err, res) { if (err) return done(err) res.statusCode.should.equal(200) delete item2.f @@ -3012,13 +3012,13 @@ describe('query', function() { res.body.should.eql({ Count: 3, ScannedCount: 3, - Items: [item2, item3, item4], - LastEvaluatedKey: {a: item4.a, b: item4.b, c: item4.c, d: item4.d}, + Items: [ item2, item3, item4 ], + LastEvaluatedKey: { a: item4.a, b: item4.b, c: item4.c, d: item4.d }, ConsumedCapacity: { CapacityUnits: 0.5, TableName: helpers.testRangeTable, - Table: {CapacityUnits: 0}, - GlobalSecondaryIndexes: {index4: {CapacityUnits: 0.5}}, + Table: { CapacityUnits: 0 }, + GlobalSecondaryIndexes: { index4: { CapacityUnits: 0.5 } }, }, }) done() @@ -3026,33 +3026,33 @@ describe('query', function() { }) }) - it('should query in reverse on range global index', function(done) { - var item = {a: {S: 'a'}, b: {S: 'a'}, c: {S: helpers.randomString()}, d: {S: 'f'}}, - item2 = {a: {S: 'b'}, b: {S: 'b'}, c: item.c, d: {S: 'a'}}, - item3 = {a: {S: 'c'}, b: {S: 'e'}, c: item.c, d: {S: 'b'}}, - item4 = {a: {S: 'c'}, b: {S: 'd'}, c: item.c, d: {S: 'c'}}, - item5 = {a: {S: 'c'}, b: {S: 'c'}, c: {S: 'c'}, d: {S: 'd'}}, - item6 = {a: {S: 'd'}, b: {S: 'a'}, c: item.c, d: {S: 'e'}}, - item7 = {a: {S: 'e'}, b: {S: 'a'}, c: item.c, d: {S: 'f'}}, - items = [item, item2, item3, item4, item5, item6, item7] - helpers.batchBulkPut(helpers.testRangeTable, items, function(err) { + it('should query in reverse on range global index', function (done) { + var item = { a: { S: 'a' }, b: { S: 'a' }, c: { S: helpers.randomString() }, d: { S: 'f' } }, + item2 = { a: { S: 'b' }, b: { S: 'b' }, c: item.c, d: { S: 'a' } }, + item3 = { a: { S: 'c' }, b: { S: 'e' }, c: item.c, d: { S: 'b' } }, + item4 = { a: { S: 'c' }, b: { S: 'd' }, c: item.c, d: { S: 'c' } }, + item5 = { a: { S: 'c' }, b: { S: 'c' }, c: { S: 'c' }, d: { S: 'd' } }, + item6 = { a: { S: 'd' }, b: { S: 'a' }, c: item.c, d: { S: 'e' } }, + item7 = { a: { S: 'e' }, b: { S: 'a' }, c: item.c, d: { S: 'f' } }, + items = [ item, item2, item3, item4, item5, item6, item7 ] + helpers.batchBulkPut(helpers.testRangeTable, items, function (err) { if (err) return done(err) - request(opts({TableName: helpers.testRangeTable, KeyConditions: { - c: {ComparisonOperator: 'EQ', AttributeValueList: [item.c]}, - d: {ComparisonOperator: 'LT', AttributeValueList: [item.d]}, - }, IndexName: 'index4', ScanIndexForward: false, Limit: 3, ReturnConsumedCapacity: 'INDEXES'}), function(err, res) { + request(opts({ TableName: helpers.testRangeTable, KeyConditions: { + c: { ComparisonOperator: 'EQ', AttributeValueList: [ item.c ] }, + d: { ComparisonOperator: 'LT', AttributeValueList: [ item.d ] }, + }, IndexName: 'index4', ScanIndexForward: false, Limit: 3, ReturnConsumedCapacity: 'INDEXES' }), function (err, res) { if (err) return done(err) res.statusCode.should.equal(200) res.body.should.eql({ Count: 3, ScannedCount: 3, - Items: [item6, item4, item3], - LastEvaluatedKey: {a: item3.a, b: item3.b, c: item3.c, d: item3.d}, + Items: [ item6, item4, item3 ], + LastEvaluatedKey: { a: item3.a, b: item3.b, c: item3.c, d: item3.d }, ConsumedCapacity: { CapacityUnits: 0.5, TableName: helpers.testRangeTable, - Table: {CapacityUnits: 0}, - GlobalSecondaryIndexes: {index4: {CapacityUnits: 0.5}}, + Table: { CapacityUnits: 0 }, + GlobalSecondaryIndexes: { index4: { CapacityUnits: 0.5 } }, }, }) done() @@ -3060,33 +3060,33 @@ describe('query', function() { }) }) - it('should query with ExclusiveStartKey on basic hash global index', function(done) { - var item = {a: {S: 'a'}, b: {S: 'a'}, c: {S: helpers.randomString()}, d: {S: 'a'}}, - item2 = {a: {S: 'b'}, b: {S: 'b'}, c: item.c, d: {S: 'a'}}, - item3 = {a: {S: 'c'}, b: {S: 'e'}, c: item.c, d: {S: 'a'}}, - item4 = {a: {S: 'c'}, b: {S: 'd'}, c: item.c, d: {S: 'a'}}, - item5 = {a: {S: 'c'}, b: {S: 'c'}, c: {S: 'c'}, d: {S: 'a'}}, - item6 = {a: {S: 'd'}, b: {S: 'a'}, c: item.c, d: {S: 'a'}}, - item7 = {a: {S: 'e'}, b: {S: 'a'}, c: item.c, d: {S: 'a'}}, - items = [item, item2, item3, item4, item5, item6, item7] - helpers.batchBulkPut(helpers.testRangeTable, items, function(err) { + it('should query with ExclusiveStartKey on basic hash global index', function (done) { + var item = { a: { S: 'a' }, b: { S: 'a' }, c: { S: helpers.randomString() }, d: { S: 'a' } }, + item2 = { a: { S: 'b' }, b: { S: 'b' }, c: item.c, d: { S: 'a' } }, + item3 = { a: { S: 'c' }, b: { S: 'e' }, c: item.c, d: { S: 'a' } }, + item4 = { a: { S: 'c' }, b: { S: 'd' }, c: item.c, d: { S: 'a' } }, + item5 = { a: { S: 'c' }, b: { S: 'c' }, c: { S: 'c' }, d: { S: 'a' } }, + item6 = { a: { S: 'd' }, b: { S: 'a' }, c: item.c, d: { S: 'a' } }, + item7 = { a: { S: 'e' }, b: { S: 'a' }, c: item.c, d: { S: 'a' } }, + items = [ item, item2, item3, item4, item5, item6, item7 ] + helpers.batchBulkPut(helpers.testRangeTable, items, function (err) { if (err) return done(err) delete item3.d - request(opts({TableName: helpers.testRangeTable, KeyConditions: { - c: {ComparisonOperator: 'EQ', AttributeValueList: [item.c]}, - }, IndexName: 'index3', Limit: 2, ExclusiveStartKey: item3, ReturnConsumedCapacity: 'INDEXES'}), function(err, res) { + request(opts({ TableName: helpers.testRangeTable, KeyConditions: { + c: { ComparisonOperator: 'EQ', AttributeValueList: [ item.c ] }, + }, IndexName: 'index3', Limit: 2, ExclusiveStartKey: item3, ReturnConsumedCapacity: 'INDEXES' }), function (err, res) { if (err) return done(err) res.statusCode.should.equal(200) res.body.should.eql({ Count: 2, ScannedCount: 2, - Items: [item7, item6], - LastEvaluatedKey: {a: item6.a, b: item6.b, c: item6.c}, + Items: [ item7, item6 ], + LastEvaluatedKey: { a: item6.a, b: item6.b, c: item6.c }, ConsumedCapacity: { CapacityUnits: 0.5, TableName: helpers.testRangeTable, - Table: {CapacityUnits: 0}, - GlobalSecondaryIndexes: {index3: {CapacityUnits: 0.5}}, + Table: { CapacityUnits: 0 }, + GlobalSecondaryIndexes: { index3: { CapacityUnits: 0.5 } }, }, }) done() @@ -3094,33 +3094,33 @@ describe('query', function() { }) }) - it('should query in reverse with ExclusiveStartKey on basic hash global index', function(done) { - var item = {a: {S: 'a'}, b: {S: 'a'}, c: {S: helpers.randomString()}}, - item2 = {a: {S: 'b'}, b: {S: 'b'}, c: item.c}, - item3 = {a: {S: 'c'}, b: {S: 'e'}, c: item.c}, - item4 = {a: {S: 'c'}, b: {S: 'd'}, c: item.c}, - item5 = {a: {S: 'c'}, b: {S: 'c'}, c: {S: 'c'}}, - item6 = {a: {S: 'd'}, b: {S: 'a'}, c: item.c}, - item7 = {a: {S: 'e'}, b: {S: 'a'}, c: item.c}, - items = [item, item2, item3, item4, item5, item6, item7] - helpers.batchBulkPut(helpers.testRangeTable, items, function(err) { + it('should query in reverse with ExclusiveStartKey on basic hash global index', function (done) { + var item = { a: { S: 'a' }, b: { S: 'a' }, c: { S: helpers.randomString() } }, + item2 = { a: { S: 'b' }, b: { S: 'b' }, c: item.c }, + item3 = { a: { S: 'c' }, b: { S: 'e' }, c: item.c }, + item4 = { a: { S: 'c' }, b: { S: 'd' }, c: item.c }, + item5 = { a: { S: 'c' }, b: { S: 'c' }, c: { S: 'c' } }, + item6 = { a: { S: 'd' }, b: { S: 'a' }, c: item.c }, + item7 = { a: { S: 'e' }, b: { S: 'a' }, c: item.c }, + items = [ item, item2, item3, item4, item5, item6, item7 ] + helpers.batchBulkPut(helpers.testRangeTable, items, function (err) { if (err) return done(err) delete item7.d - request(opts({TableName: helpers.testRangeTable, KeyConditions: { - c: {ComparisonOperator: 'EQ', AttributeValueList: [item.c]}, - }, IndexName: 'index3', ScanIndexForward: false, Limit: 2, ExclusiveStartKey: item7, ReturnConsumedCapacity: 'INDEXES'}), function(err, res) { + request(opts({ TableName: helpers.testRangeTable, KeyConditions: { + c: { ComparisonOperator: 'EQ', AttributeValueList: [ item.c ] }, + }, IndexName: 'index3', ScanIndexForward: false, Limit: 2, ExclusiveStartKey: item7, ReturnConsumedCapacity: 'INDEXES' }), function (err, res) { if (err) return done(err) res.statusCode.should.equal(200) res.body.should.eql({ Count: 2, ScannedCount: 2, - Items: [item3, item], - LastEvaluatedKey: {a: item.a, b: item.b, c: item.c}, + Items: [ item3, item ], + LastEvaluatedKey: { a: item.a, b: item.b, c: item.c }, ConsumedCapacity: { CapacityUnits: 0.5, TableName: helpers.testRangeTable, - Table: {CapacityUnits: 0}, - GlobalSecondaryIndexes: {index3: {CapacityUnits: 0.5}}, + Table: { CapacityUnits: 0 }, + GlobalSecondaryIndexes: { index3: { CapacityUnits: 0.5 } }, }, }) done() @@ -3128,36 +3128,36 @@ describe('query', function() { }) }) - it('should query with ExclusiveStartKey on range global index', function(done) { - var item = {a: {S: 'a'}, b: {S: 'a'}, c: {S: helpers.randomString()}, d: {S: 'f'}, e: {S: 'a'}, f: {S: 'a'}}, - item2 = {a: {S: 'b'}, b: {S: 'b'}, c: item.c, d: {S: 'a'}, e: {S: 'a'}, f: {S: 'a'}}, - item3 = {a: {S: 'c'}, b: {S: 'e'}, c: item.c, d: {S: 'b'}, e: {S: 'a'}, f: {S: 'a'}}, - item4 = {a: {S: 'c'}, b: {S: 'd'}, c: item.c, d: {S: 'c'}, e: {S: 'a'}, f: {S: 'a'}}, - item5 = {a: {S: 'c'}, b: {S: 'c'}, c: {S: 'c'}, d: {S: 'd'}, e: {S: 'a'}, f: {S: 'a'}}, - item6 = {a: {S: 'd'}, b: {S: 'a'}, c: item.c, d: {S: 'e'}, e: {S: 'a'}, f: {S: 'a'}}, - item7 = {a: {S: 'e'}, b: {S: 'a'}, c: item.c, d: {S: 'f'}, e: {S: 'a'}, f: {S: 'a'}}, - items = [item, item2, item3, item4, item5, item6, item7] - helpers.batchBulkPut(helpers.testRangeTable, items, function(err) { + it('should query with ExclusiveStartKey on range global index', function (done) { + var item = { a: { S: 'a' }, b: { S: 'a' }, c: { S: helpers.randomString() }, d: { S: 'f' }, e: { S: 'a' }, f: { S: 'a' } }, + item2 = { a: { S: 'b' }, b: { S: 'b' }, c: item.c, d: { S: 'a' }, e: { S: 'a' }, f: { S: 'a' } }, + item3 = { a: { S: 'c' }, b: { S: 'e' }, c: item.c, d: { S: 'b' }, e: { S: 'a' }, f: { S: 'a' } }, + item4 = { a: { S: 'c' }, b: { S: 'd' }, c: item.c, d: { S: 'c' }, e: { S: 'a' }, f: { S: 'a' } }, + item5 = { a: { S: 'c' }, b: { S: 'c' }, c: { S: 'c' }, d: { S: 'd' }, e: { S: 'a' }, f: { S: 'a' } }, + item6 = { a: { S: 'd' }, b: { S: 'a' }, c: item.c, d: { S: 'e' }, e: { S: 'a' }, f: { S: 'a' } }, + item7 = { a: { S: 'e' }, b: { S: 'a' }, c: item.c, d: { S: 'f' }, e: { S: 'a' }, f: { S: 'a' } }, + items = [ item, item2, item3, item4, item5, item6, item7 ] + helpers.batchBulkPut(helpers.testRangeTable, items, function (err) { if (err) return done(err) delete item3.e delete item3.f delete item4.f - request(opts({TableName: helpers.testRangeTable, KeyConditions: { - c: {ComparisonOperator: 'EQ', AttributeValueList: [item.c]}, - d: {ComparisonOperator: 'LT', AttributeValueList: [item.d]}, - }, IndexName: 'index4', Limit: 1, ExclusiveStartKey: item3, ReturnConsumedCapacity: 'INDEXES'}), function(err, res) { + request(opts({ TableName: helpers.testRangeTable, KeyConditions: { + c: { ComparisonOperator: 'EQ', AttributeValueList: [ item.c ] }, + d: { ComparisonOperator: 'LT', AttributeValueList: [ item.d ] }, + }, IndexName: 'index4', Limit: 1, ExclusiveStartKey: item3, ReturnConsumedCapacity: 'INDEXES' }), function (err, res) { if (err) return done(err) res.statusCode.should.equal(200) res.body.should.eql({ Count: 1, ScannedCount: 1, - Items: [item4], - LastEvaluatedKey: {a: item4.a, b: item4.b, c: item4.c, d: item4.d}, + Items: [ item4 ], + LastEvaluatedKey: { a: item4.a, b: item4.b, c: item4.c, d: item4.d }, ConsumedCapacity: { CapacityUnits: 0.5, TableName: helpers.testRangeTable, - Table: {CapacityUnits: 0}, - GlobalSecondaryIndexes: {index4: {CapacityUnits: 0.5}}, + Table: { CapacityUnits: 0 }, + GlobalSecondaryIndexes: { index4: { CapacityUnits: 0.5 } }, }, }) done() @@ -3165,36 +3165,36 @@ describe('query', function() { }) }) - it('should query in reverse with ExclusiveStartKey on range global index', function(done) { - var item = {a: {S: 'a'}, b: {S: 'a'}, c: {S: helpers.randomString()}, d: {S: 'f'}, e: {S: 'a'}, f: {S: 'a'}}, - item2 = {a: {S: 'b'}, b: {S: 'b'}, c: item.c, d: {S: 'a'}, e: {S: 'a'}, f: {S: 'a'}}, - item3 = {a: {S: 'c'}, b: {S: 'e'}, c: item.c, d: {S: 'b'}, e: {S: 'a'}, f: {S: 'a'}}, - item4 = {a: {S: 'c'}, b: {S: 'd'}, c: item.c, d: {S: 'c'}, e: {S: 'a'}, f: {S: 'a'}}, - item5 = {a: {S: 'c'}, b: {S: 'c'}, c: {S: 'c'}, d: {S: 'd'}, e: {S: 'a'}, f: {S: 'a'}}, - item6 = {a: {S: 'd'}, b: {S: 'a'}, c: item.c, d: {S: 'e'}, e: {S: 'a'}, f: {S: 'a'}}, - item7 = {a: {S: 'e'}, b: {S: 'a'}, c: item.c, d: {S: 'f'}, e: {S: 'a'}, f: {S: 'a'}}, - items = [item, item2, item3, item4, item5, item6, item7] - helpers.batchBulkPut(helpers.testRangeTable, items, function(err) { + it('should query in reverse with ExclusiveStartKey on range global index', function (done) { + var item = { a: { S: 'a' }, b: { S: 'a' }, c: { S: helpers.randomString() }, d: { S: 'f' }, e: { S: 'a' }, f: { S: 'a' } }, + item2 = { a: { S: 'b' }, b: { S: 'b' }, c: item.c, d: { S: 'a' }, e: { S: 'a' }, f: { S: 'a' } }, + item3 = { a: { S: 'c' }, b: { S: 'e' }, c: item.c, d: { S: 'b' }, e: { S: 'a' }, f: { S: 'a' } }, + item4 = { a: { S: 'c' }, b: { S: 'd' }, c: item.c, d: { S: 'c' }, e: { S: 'a' }, f: { S: 'a' } }, + item5 = { a: { S: 'c' }, b: { S: 'c' }, c: { S: 'c' }, d: { S: 'd' }, e: { S: 'a' }, f: { S: 'a' } }, + item6 = { a: { S: 'd' }, b: { S: 'a' }, c: item.c, d: { S: 'e' }, e: { S: 'a' }, f: { S: 'a' } }, + item7 = { a: { S: 'e' }, b: { S: 'a' }, c: item.c, d: { S: 'f' }, e: { S: 'a' }, f: { S: 'a' } }, + items = [ item, item2, item3, item4, item5, item6, item7 ] + helpers.batchBulkPut(helpers.testRangeTable, items, function (err) { if (err) return done(err) delete item4.e delete item4.f delete item3.f - request(opts({TableName: helpers.testRangeTable, KeyConditions: { - c: {ComparisonOperator: 'EQ', AttributeValueList: [item.c]}, - d: {ComparisonOperator: 'LT', AttributeValueList: [item.d]}, - }, IndexName: 'index4', Limit: 1, ScanIndexForward: false, ExclusiveStartKey: item4, ReturnConsumedCapacity: 'INDEXES'}), function(err, res) { + request(opts({ TableName: helpers.testRangeTable, KeyConditions: { + c: { ComparisonOperator: 'EQ', AttributeValueList: [ item.c ] }, + d: { ComparisonOperator: 'LT', AttributeValueList: [ item.d ] }, + }, IndexName: 'index4', Limit: 1, ScanIndexForward: false, ExclusiveStartKey: item4, ReturnConsumedCapacity: 'INDEXES' }), function (err, res) { if (err) return done(err) res.statusCode.should.equal(200) res.body.should.eql({ Count: 1, ScannedCount: 1, - Items: [item3], - LastEvaluatedKey: {a: item3.a, b: item3.b, c: item3.c, d: item3.d}, + Items: [ item3 ], + LastEvaluatedKey: { a: item3.a, b: item3.b, c: item3.c, d: item3.d }, ConsumedCapacity: { CapacityUnits: 0.5, TableName: helpers.testRangeTable, - Table: {CapacityUnits: 0}, - GlobalSecondaryIndexes: {index4: {CapacityUnits: 0.5}}, + Table: { CapacityUnits: 0 }, + GlobalSecondaryIndexes: { index4: { CapacityUnits: 0.5 } }, }, }) done() @@ -3202,30 +3202,30 @@ describe('query', function() { }) }) - it('should query on a global index if values are equal', function(done) { - var item = {a: {S: 'a'}, b: {S: 'a'}, c: {S: helpers.randomString()}, d: {S: 'a'}}, - item2 = {a: {S: 'b'}, b: {S: 'a'}, c: item.c, d: {S: 'a'}}, - item3 = {a: {S: 'c'}, b: {S: 'a'}, c: item.c, d: {S: 'a'}}, - item4 = {a: {S: 'c'}, b: {S: 'b'}, c: item.c, d: {S: 'a'}}, - item5 = {a: {S: 'd'}, b: {S: 'a'}, c: item.c, d: {S: 'a'}}, - item6 = {a: {S: 'd'}, b: {S: 'b'}, c: item.c, d: {S: 'a'}}, - items = [item, item2, item3, item4, item5, item6] - helpers.batchBulkPut(helpers.testRangeTable, items, function(err) { + it('should query on a global index if values are equal', function (done) { + var item = { a: { S: 'a' }, b: { S: 'a' }, c: { S: helpers.randomString() }, d: { S: 'a' } }, + item2 = { a: { S: 'b' }, b: { S: 'a' }, c: item.c, d: { S: 'a' } }, + item3 = { a: { S: 'c' }, b: { S: 'a' }, c: item.c, d: { S: 'a' } }, + item4 = { a: { S: 'c' }, b: { S: 'b' }, c: item.c, d: { S: 'a' } }, + item5 = { a: { S: 'd' }, b: { S: 'a' }, c: item.c, d: { S: 'a' } }, + item6 = { a: { S: 'd' }, b: { S: 'b' }, c: item.c, d: { S: 'a' } }, + items = [ item, item2, item3, item4, item5, item6 ] + helpers.batchBulkPut(helpers.testRangeTable, items, function (err) { if (err) return done(err) - request(opts({TableName: helpers.testRangeTable, KeyConditions: { - c: {ComparisonOperator: 'EQ', AttributeValueList: [item.c]}, - }, IndexName: 'index4', ExclusiveStartKey: item, ReturnConsumedCapacity: 'INDEXES'}), function(err, res) { + request(opts({ TableName: helpers.testRangeTable, KeyConditions: { + c: { ComparisonOperator: 'EQ', AttributeValueList: [ item.c ] }, + }, IndexName: 'index4', ExclusiveStartKey: item, ReturnConsumedCapacity: 'INDEXES' }), function (err, res) { if (err) return done(err) res.statusCode.should.equal(200) res.body.should.eql({ Count: 5, ScannedCount: 5, - Items: [item5, item2, item3, item6, item4], + Items: [ item5, item2, item3, item6, item4 ], ConsumedCapacity: { CapacityUnits: 0.5, TableName: helpers.testRangeTable, - Table: {CapacityUnits: 0}, - GlobalSecondaryIndexes: {index4: {CapacityUnits: 0.5}}, + Table: { CapacityUnits: 0 }, + GlobalSecondaryIndexes: { index4: { CapacityUnits: 0.5 } }, }, }) done() @@ -3235,26 +3235,26 @@ describe('query', function() { // High capacity (~100 or more) needed to run this quickly if (runSlowTests) { - it('should not return LastEvaluatedKey if just under limit', function(done) { + it('should not return LastEvaluatedKey if just under limit', function (done) { this.timeout(200000) var i, items = [], id = helpers.randomString(), e = new Array(41646).join('e'), eAttr = e.slice(0, 255) for (i = 0; i < 25; i++) { - var item = {a: {S: id}, b: {S: ('0' + i).slice(-2)}} - item[eAttr] = {S: e} + var item = { a: { S: id }, b: { S: ('0' + i).slice(-2) } } + item[eAttr] = { S: e } items.push(item) } - helpers.replaceTable(helpers.testRangeTable, ['a', 'b'], items, function(err) { + helpers.replaceTable(helpers.testRangeTable, [ 'a', 'b' ], items, function (err) { if (err) return done(err) request(opts({ TableName: helpers.testRangeTable, - KeyConditions: {a: {ComparisonOperator: 'EQ', AttributeValueList: [{S: id}]}}, + KeyConditions: { a: { ComparisonOperator: 'EQ', AttributeValueList: [ { S: id } ] } }, Select: 'COUNT', ReturnConsumedCapacity: 'INDEXES', Limit: 26, // Limit of 25 includes LastEvaluatedKey, leaving this out does not - }), function(err, res) { + }), function (err, res) { if (err) return done(err) res.statusCode.should.equal(200) res.body.should.eql({ @@ -3262,32 +3262,32 @@ describe('query', function() { ScannedCount: 25, ConsumedCapacity: { CapacityUnits: 128, - Table: {CapacityUnits: 128}, + Table: { CapacityUnits: 128 }, TableName: helpers.testRangeTable, }, }) - helpers.clearTable(helpers.testRangeTable, ['a', 'b'], done) + helpers.clearTable(helpers.testRangeTable, [ 'a', 'b' ], done) }) }) }) - it('should return LastEvaluatedKey if just over limit', function(done) { + it('should return LastEvaluatedKey if just over limit', function (done) { this.timeout(200000) var i, items = [], id = helpers.randomString(), e = new Array(41646).join('e') for (i = 0; i < 25; i++) - items.push({a: {S: id}, b: {S: ('0' + i).slice(-2)}, e: {S: e}}) + items.push({ a: { S: id }, b: { S: ('0' + i).slice(-2) }, e: { S: e } }) items[24].e.S = new Array(41647).join('e') - helpers.replaceTable(helpers.testRangeTable, ['a', 'b'], items, function(err) { + helpers.replaceTable(helpers.testRangeTable, [ 'a', 'b' ], items, function (err) { if (err) return done(err) request(opts({ TableName: helpers.testRangeTable, - KeyConditions: {a: {ComparisonOperator: 'EQ', AttributeValueList: [{S: id}]}}, + KeyConditions: { a: { ComparisonOperator: 'EQ', AttributeValueList: [ { S: id } ] } }, Select: 'COUNT', ReturnConsumedCapacity: 'INDEXES', - }), function(err, res) { + }), function (err, res) { if (err) return done(err) res.statusCode.should.equal(200) res.body.should.eql({ @@ -3295,77 +3295,77 @@ describe('query', function() { ScannedCount: 25, ConsumedCapacity: { CapacityUnits: 127.5, - Table: {CapacityUnits: 127.5}, + Table: { CapacityUnits: 127.5 }, TableName: helpers.testRangeTable, }, - LastEvaluatedKey: {a: items[24].a, b: items[24].b}, + LastEvaluatedKey: { a: items[24].a, b: items[24].b }, }) - helpers.clearTable(helpers.testRangeTable, ['a', 'b'], done) + helpers.clearTable(helpers.testRangeTable, [ 'a', 'b' ], done) }) }) }) - it('should return all if just under limit', function(done) { + it('should return all if just under limit', function (done) { this.timeout(200000) var i, items = [], id = helpers.randomString(), e = new Array(43373).join('e'), eAttr = e.slice(0, 255) for (i = 0; i < 25; i++) { - var item = {a: {S: id}, b: {S: ('0' + i).slice(-2)}} - item[eAttr] = {S: e} + var item = { a: { S: id }, b: { S: ('0' + i).slice(-2) } } + item[eAttr] = { S: e } items.push(item) } items[23][eAttr].S = new Array(43388).join('e') items[24][eAttr].S = new Array(45000).join('e') - helpers.replaceTable(helpers.testRangeTable, ['a', 'b'], items, function(err) { + helpers.replaceTable(helpers.testRangeTable, [ 'a', 'b' ], items, function (err) { if (err) return done(err) request(opts({ TableName: helpers.testRangeTable, - KeyConditions: {a: {ComparisonOperator: 'EQ', AttributeValueList: [{S: id}]}}, + KeyConditions: { a: { ComparisonOperator: 'EQ', AttributeValueList: [ { S: id } ] } }, Select: 'COUNT', ReturnConsumedCapacity: 'TOTAL', - }), function(err, res) { + }), function (err, res) { if (err) return done(err) res.statusCode.should.equal(200) res.body.should.eql({ Count: 25, ScannedCount: 25, - ConsumedCapacity: {CapacityUnits: 133.5, TableName: helpers.testRangeTable}, - LastEvaluatedKey: {a: items[24].a, b: items[24].b}, + ConsumedCapacity: { CapacityUnits: 133.5, TableName: helpers.testRangeTable }, + LastEvaluatedKey: { a: items[24].a, b: items[24].b }, }) - helpers.clearTable(helpers.testRangeTable, ['a', 'b'], done) + helpers.clearTable(helpers.testRangeTable, [ 'a', 'b' ], done) }) }) }) - it('should return one less than all if just over limit', function(done) { + it('should return one less than all if just over limit', function (done) { this.timeout(200000) var i, items = [], id = helpers.randomString(), e = new Array(43373).join('e') for (i = 0; i < 25; i++) - items.push({a: {S: id}, b: {S: ('0' + i).slice(-2)}, e: {S: e}}) + items.push({ a: { S: id }, b: { S: ('0' + i).slice(-2) }, e: { S: e } }) items[23].e.S = new Array(43389).join('e') items[24].e.S = new Array(45000).join('e') - helpers.replaceTable(helpers.testRangeTable, ['a', 'b'], items, function(err) { + helpers.replaceTable(helpers.testRangeTable, [ 'a', 'b' ], items, function (err) { if (err) return done(err) request(opts({ TableName: helpers.testRangeTable, - KeyConditions: {a: {ComparisonOperator: 'EQ', AttributeValueList: [{S: id}]}}, + KeyConditions: { a: { ComparisonOperator: 'EQ', AttributeValueList: [ { S: id } ] } }, Select: 'COUNT', ReturnConsumedCapacity: 'TOTAL', - }), function(err, res) { + }), function (err, res) { if (err) return done(err) res.statusCode.should.equal(200) res.body.should.eql({ Count: 24, ScannedCount: 24, - ConsumedCapacity: {CapacityUnits: 127.5, TableName: helpers.testRangeTable}, - LastEvaluatedKey: {a: items[23].a, b: items[23].b}, + ConsumedCapacity: { CapacityUnits: 127.5, TableName: helpers.testRangeTable }, + LastEvaluatedKey: { a: items[23].a, b: items[23].b }, }) - helpers.clearTable(helpers.testRangeTable, ['a', 'b'], done) + helpers.clearTable(helpers.testRangeTable, [ 'a', 'b' ], done) }) }) }) diff --git a/test/scan.js b/test/scan.js index 44016d5..e09cd0d 100644 --- a/test/scan.js +++ b/test/scan.js @@ -1,123 +1,123 @@ var helpers = require('./helpers'), - should = require('should'), - async = require('async') + should = require('should'), + async = require('async') var target = 'Scan', - request = helpers.request, - opts = helpers.opts.bind(null, target), - assertType = helpers.assertType.bind(null, target), - assertValidation = helpers.assertValidation.bind(null, target), - assertNotFound = helpers.assertNotFound.bind(null, target), - runSlowTests = helpers.runSlowTests + request = helpers.request, + opts = helpers.opts.bind(null, target), + assertType = helpers.assertType.bind(null, target), + assertValidation = helpers.assertValidation.bind(null, target), + assertNotFound = helpers.assertNotFound.bind(null, target), + runSlowTests = helpers.runSlowTests -describe('scan', function() { +describe('scan', function () { - describe('serializations', function() { + describe('serializations', function () { - it('should return SerializationException when TableName is not a string', function(done) { + it('should return SerializationException when TableName is not a string', function (done) { assertType('TableName', 'String', done) }) - it('should return SerializationException when ExclusiveStartKey is not a map', function(done) { + it('should return SerializationException when ExclusiveStartKey is not a map', function (done) { assertType('ExclusiveStartKey', 'Map', done) }) - it('should return SerializationException when ExclusiveStartKey.Attr is not an attr struct', function(done) { + it('should return SerializationException when ExclusiveStartKey.Attr is not an attr struct', function (done) { this.timeout(60000) assertType('ExclusiveStartKey.Attr', 'AttrStruct', done) }) - it('should return SerializationException when AttributesToGet is not a list', function(done) { + it('should return SerializationException when AttributesToGet is not a list', function (done) { assertType('AttributesToGet', 'List', done) }) - it('should return SerializationException when ReturnConsumedCapacity is not a string', function(done) { + it('should return SerializationException when ReturnConsumedCapacity is not a string', function (done) { assertType('ReturnConsumedCapacity', 'String', done) }) - it('should return SerializationException when Select is not a string', function(done) { + it('should return SerializationException when Select is not a string', function (done) { assertType('Select', 'String', done) }) - it('should return SerializationException when Limit is not an integer', function(done) { + it('should return SerializationException when Limit is not an integer', function (done) { assertType('Limit', 'Integer', done) }) - it('should return SerializationException when Segment is not an integer', function(done) { + it('should return SerializationException when Segment is not an integer', function (done) { assertType('Segment', 'Integer', done) }) - it('should return SerializationException when ConditionalOperator is not a string', function(done) { + it('should return SerializationException when ConditionalOperator is not a string', function (done) { assertType('ConditionalOperator', 'String', done) }) - it('should return SerializationException when TotalSegments is not an integer', function(done) { + it('should return SerializationException when TotalSegments is not an integer', function (done) { assertType('TotalSegments', 'Integer', done) }) - it('should return SerializationException when ScanFilter is not a map', function(done) { + it('should return SerializationException when ScanFilter is not a map', function (done) { assertType('ScanFilter', 'Map', done) }) - it('should return SerializationException when ScanFilter.Attr is not a struct', function(done) { + it('should return SerializationException when ScanFilter.Attr is not a struct', function (done) { assertType('ScanFilter.Attr', 'ValueStruct', done) }) - it('should return SerializationException when ScanFilter.Attr.ComparisonOperator is not a string', function(done) { + it('should return SerializationException when ScanFilter.Attr.ComparisonOperator is not a string', function (done) { assertType('ScanFilter.Attr.ComparisonOperator', 'String', done) }) - it('should return SerializationException when ScanFilter.Attr.AttributeValueList is not a list', function(done) { + it('should return SerializationException when ScanFilter.Attr.AttributeValueList is not a list', function (done) { assertType('ScanFilter.Attr.AttributeValueList', 'List', done) }) - it('should return SerializationException when ScanFilter.Attr.AttributeValueList.0 is not an attr struct', function(done) { + it('should return SerializationException when ScanFilter.Attr.AttributeValueList.0 is not an attr struct', function (done) { this.timeout(60000) assertType('ScanFilter.Attr.AttributeValueList.0', 'AttrStruct', done) }) - it('should return SerializationException when FilterExpression is not a string', function(done) { + it('should return SerializationException when FilterExpression is not a string', function (done) { assertType('FilterExpression', 'String', done) }) - it('should return SerializationException when ExpressionAttributeValues is not a map', function(done) { + it('should return SerializationException when ExpressionAttributeValues is not a map', function (done) { assertType('ExpressionAttributeValues', 'Map', done) }) - it('should return SerializationException when ExpressionAttributeValues.Attr is not an attr struct', function(done) { + it('should return SerializationException when ExpressionAttributeValues.Attr is not an attr struct', function (done) { this.timeout(60000) assertType('ExpressionAttributeValues.Attr', 'AttrStruct', done) }) - it('should return SerializationException when ExpressionAttributeNames is not a map', function(done) { + it('should return SerializationException when ExpressionAttributeNames is not a map', function (done) { assertType('ExpressionAttributeNames', 'Map', done) }) - it('should return SerializationException when ExpressionAttributeNames.Attr is not a string', function(done) { + it('should return SerializationException when ExpressionAttributeNames.Attr is not a string', function (done) { assertType('ExpressionAttributeNames.Attr', 'String', done) }) - it('should return SerializationException when ProjectionExpression is not a string', function(done) { + it('should return SerializationException when ProjectionExpression is not a string', function (done) { assertType('ProjectionExpression', 'String', done) }) - it('should return SerializationException when IndexName is not a string', function(done) { + it('should return SerializationException when IndexName is not a string', function (done) { assertType('IndexName', 'String', done) }) }) - describe('validations', function() { + describe('validations', function () { - it('should return ValidationException for no TableName', function(done) { + it('should return ValidationException for no TableName', function (done) { assertValidation({}, '1 validation error detected: ' + 'Value null at \'tableName\' failed to satisfy constraint: ' + 'Member must not be null', done) }) - it('should return ValidationException for empty TableName', function(done) { - assertValidation({TableName: ''}, [ + it('should return ValidationException for empty TableName', function (done) { + assertValidation({ TableName: '' }, [ 'Value \'\' at \'tableName\' failed to satisfy constraint: ' + 'Member must satisfy regular expression pattern: [a-zA-Z0-9_.-]+', 'Value \'\' at \'tableName\' failed to satisfy constraint: ' + @@ -125,8 +125,8 @@ describe('scan', function() { ], done) }) - it('should return ValidationException for short TableName', function(done) { - assertValidation({TableName: 'a;'}, [ + it('should return ValidationException for short TableName', function (done) { + assertValidation({ TableName: 'a;' }, [ 'Value \'a;\' at \'tableName\' failed to satisfy constraint: ' + 'Member must satisfy regular expression pattern: [a-zA-Z0-9_.-]+', 'Value \'a;\' at \'tableName\' failed to satisfy constraint: ' + @@ -134,49 +134,49 @@ describe('scan', function() { ], done) }) - it('should return ValidationException for long TableName', function(done) { + it('should return ValidationException for long TableName', function (done) { var name = new Array(256 + 1).join('a') - assertValidation({TableName: name}, + assertValidation({ TableName: name }, '1 validation error detected: ' + 'Value \'' + name + '\' at \'tableName\' failed to satisfy constraint: ' + 'Member must have length less than or equal to 255', done) }) - it('should return ValidationException for incorrect attributes', function(done) { - assertValidation({TableName: 'abc;', ReturnConsumedCapacity: 'hi', AttributesToGet: [], - IndexName: 'abc;', Segment: -1, TotalSegments: -1, Select: 'hi', Limit: -1, ScanFilter: {a: {}, b: {ComparisonOperator: ''}}, - ConditionalOperator: 'AN', ExpressionAttributeNames: {}, ExpressionAttributeValues: {}, ProjectionExpression: ''}, [ - 'Value \'hi\' at \'select\' failed to satisfy constraint: ' + + it('should return ValidationException for incorrect attributes', function (done) { + assertValidation({ TableName: 'abc;', ReturnConsumedCapacity: 'hi', AttributesToGet: [], + IndexName: 'abc;', Segment: -1, TotalSegments: -1, Select: 'hi', Limit: -1, ScanFilter: { a: {}, b: { ComparisonOperator: '' } }, + ConditionalOperator: 'AN', ExpressionAttributeNames: {}, ExpressionAttributeValues: {}, ProjectionExpression: '' }, [ + 'Value \'hi\' at \'select\' failed to satisfy constraint: ' + 'Member must satisfy enum value set: [SPECIFIC_ATTRIBUTES, COUNT, ALL_ATTRIBUTES, ALL_PROJECTED_ATTRIBUTES]', - 'Value \'abc;\' at \'indexName\' failed to satisfy constraint: ' + + 'Value \'abc;\' at \'indexName\' failed to satisfy constraint: ' + 'Member must satisfy regular expression pattern: [a-zA-Z0-9_.-]+', - 'Value \'-1\' at \'totalSegments\' failed to satisfy constraint: ' + + 'Value \'-1\' at \'totalSegments\' failed to satisfy constraint: ' + 'Member must have value greater than or equal to 1', - 'Value \'hi\' at \'returnConsumedCapacity\' failed to satisfy constraint: ' + + 'Value \'hi\' at \'returnConsumedCapacity\' failed to satisfy constraint: ' + 'Member must satisfy enum value set: [INDEXES, TOTAL, NONE]', - 'Value \'abc;\' at \'tableName\' failed to satisfy constraint: ' + + 'Value \'abc;\' at \'tableName\' failed to satisfy constraint: ' + 'Member must satisfy regular expression pattern: [a-zA-Z0-9_.-]+', - 'Value \'AN\' at \'conditionalOperator\' failed to satisfy constraint: ' + + 'Value \'AN\' at \'conditionalOperator\' failed to satisfy constraint: ' + 'Member must satisfy enum value set: [OR, AND]', - 'Value null at \'scanFilter.a.member.comparisonOperator\' failed to satisfy constraint: ' + + 'Value null at \'scanFilter.a.member.comparisonOperator\' failed to satisfy constraint: ' + 'Member must not be null', - 'Value \'\' at \'scanFilter.b.member.comparisonOperator\' failed to satisfy constraint: ' + + 'Value \'\' at \'scanFilter.b.member.comparisonOperator\' failed to satisfy constraint: ' + 'Member must satisfy enum value set: [IN, NULL, BETWEEN, LT, NOT_CONTAINS, EQ, GT, NOT_NULL, NE, LE, BEGINS_WITH, GE, CONTAINS]', - 'Value \'-1\' at \'segment\' failed to satisfy constraint: ' + + 'Value \'-1\' at \'segment\' failed to satisfy constraint: ' + 'Member must have value greater than or equal to 0', - 'Value \'-1\' at \'limit\' failed to satisfy constraint: ' + + 'Value \'-1\' at \'limit\' failed to satisfy constraint: ' + 'Member must have value greater than or equal to 1', - ], done) + ], done) }) - it('should return ValidationException if expression and non-expression', function(done) { + it('should return ValidationException if expression and non-expression', function (done) { assertValidation({ TableName: 'abc', - ScanFilter: {a: {ComparisonOperator: 'EQ', AttributeValueList: [{}]}}, + ScanFilter: { a: { ComparisonOperator: 'EQ', AttributeValueList: [ {} ] } }, Segment: 1, Limit: 1, - AttributesToGet: ['a', 'a'], - ExclusiveStartKey: {a: {}}, + AttributesToGet: [ 'a', 'a' ], + ExclusiveStartKey: { a: {} }, ConditionalOperator: 'OR', Select: 'SPECIFIC_ATTRIBUTES', FilterExpression: '', @@ -188,14 +188,14 @@ describe('scan', function() { 'Expression parameters: {ProjectionExpression, FilterExpression}', done) }) - it('should return ValidationException if ExpressionAttributeNames but no FilterExpression', function(done) { + it('should return ValidationException if ExpressionAttributeNames but no FilterExpression', function (done) { assertValidation({ TableName: 'abc', - ScanFilter: {a: {ComparisonOperator: 'EQ', AttributeValueList: [{}]}}, + ScanFilter: { a: { ComparisonOperator: 'EQ', AttributeValueList: [ {} ] } }, Segment: 1, Limit: 1, - AttributesToGet: ['a', 'a'], - ExclusiveStartKey: {a: {}}, + AttributesToGet: [ 'a', 'a' ], + ExclusiveStartKey: { a: {} }, ConditionalOperator: 'OR', Select: 'SPECIFIC_ATTRIBUTES', ExpressionAttributeNames: {}, @@ -203,156 +203,156 @@ describe('scan', function() { }, 'ExpressionAttributeNames can only be specified when using expressions', done) }) - it('should return ValidationException if ExpressionAttributeValues but no FilterExpression', function(done) { + it('should return ValidationException if ExpressionAttributeValues but no FilterExpression', function (done) { assertValidation({ TableName: 'abc', - ScanFilter: {a: {ComparisonOperator: 'EQ', AttributeValueList: [{}]}}, + ScanFilter: { a: { ComparisonOperator: 'EQ', AttributeValueList: [ {} ] } }, Segment: 1, Limit: 1, - AttributesToGet: ['a', 'a'], - ExclusiveStartKey: {a: {}}, + AttributesToGet: [ 'a', 'a' ], + ExclusiveStartKey: { a: {} }, ConditionalOperator: 'OR', Select: 'SPECIFIC_ATTRIBUTES', ExpressionAttributeValues: {}, }, 'ExpressionAttributeValues can only be specified when using expressions: FilterExpression is null', done) }) - it('should return ValidationException for duplicate values in AttributesToGet', function(done) { + it('should return ValidationException for duplicate values in AttributesToGet', function (done) { assertValidation({ TableName: 'abc', Segment: 1, - ScanFilter: {a: {ComparisonOperator: 'EQ', AttributeValueList: [{}, {a: ''}, {S: ''}]}}, - ExclusiveStartKey: {a: {}}, - AttributesToGet: ['a', 'a'], + ScanFilter: { a: { ComparisonOperator: 'EQ', AttributeValueList: [ {}, { a: '' }, { S: '' } ] } }, + ExclusiveStartKey: { a: {} }, + AttributesToGet: [ 'a', 'a' ], }, 'One or more parameter values were invalid: Duplicate value in attribute name: a', done) }) - it('should return ValidationException for bad attribute values in ScanFilter', function(done) { + it('should return ValidationException for bad attribute values in ScanFilter', function (done) { async.forEach([ {}, - {a: ''}, - ], function(expr, cb) { + { a: '' }, + ], function (expr, cb) { assertValidation({ TableName: 'abc', Segment: 1, - ExclusiveStartKey: {a: {}}, - ScanFilter: {a: {ComparisonOperator: 'EQ', AttributeValueList: [expr, {S: ''}]}}, + ExclusiveStartKey: { a: {} }, + ScanFilter: { a: { ComparisonOperator: 'EQ', AttributeValueList: [ expr, { S: '' } ] } }, }, 'Supplied AttributeValue is empty, must contain exactly one of the supported datatypes', cb) }, done) }) - it('should return ValidationException for invalid values in ScanFilter', function(done) { + it('should return ValidationException for invalid values in ScanFilter', function (done) { async.forEach([ - [{NULL: 'no'}, 'Null attribute value types must have the value of true'], - [{SS: []}, 'An string set may not be empty'], - [{NS: []}, 'An number set may not be empty'], - [{BS: []}, 'Binary sets should not be empty'], - [{SS: ['a', 'a']}, 'Input collection [a, a] contains duplicates.'], - [{BS: ['Yg==', 'Yg==']}, 'Input collection [Yg==, Yg==]of type BS contains duplicates.'], - ], function(expr, cb) { + [ { NULL: 'no' }, 'Null attribute value types must have the value of true' ], + [ { SS: [] }, 'An string set may not be empty' ], + [ { NS: [] }, 'An number set may not be empty' ], + [ { BS: [] }, 'Binary sets should not be empty' ], + [ { SS: [ 'a', 'a' ] }, 'Input collection [a, a] contains duplicates.' ], + [ { BS: [ 'Yg==', 'Yg==' ] }, 'Input collection [Yg==, Yg==]of type BS contains duplicates.' ], + ], function (expr, cb) { assertValidation({ TableName: 'abc', Segment: 1, - ExclusiveStartKey: {a: {}}, - ScanFilter: {a: {ComparisonOperator: 'EQ', AttributeValueList: [{N: '1'}, expr[0], {}]}}, + ExclusiveStartKey: { a: {} }, + ScanFilter: { a: { ComparisonOperator: 'EQ', AttributeValueList: [ { N: '1' }, expr[0], {} ] } }, }, 'One or more parameter values were invalid: ' + expr[1], cb) }, done) }) - it('should return ValidationException for empty/invalid numbers in ScanFilter', function(done) { + it('should return ValidationException for empty/invalid numbers in ScanFilter', function (done) { async.forEach([ - [{S: '', N: ''}, 'The parameter cannot be converted to a numeric value'], - [{S: 'a', N: ''}, 'The parameter cannot be converted to a numeric value'], - [{S: 'a', N: 'b'}, 'The parameter cannot be converted to a numeric value: b'], - [{NS: ['1', '']}, 'The parameter cannot be converted to a numeric value'], - [{NS: ['1', 'b']}, 'The parameter cannot be converted to a numeric value: b'], - [{NS: ['1', '1']}, 'Input collection contains duplicates'], - [{N: '123456789012345678901234567890123456789'}, 'Attempting to store more than 38 significant digits in a Number'], - [{N: '-1.23456789012345678901234567890123456789'}, 'Attempting to store more than 38 significant digits in a Number'], - [{N: '1e126'}, 'Number overflow. Attempting to store a number with magnitude larger than supported range'], - [{N: '-1e126'}, 'Number overflow. Attempting to store a number with magnitude larger than supported range'], - [{N: '1e-131'}, 'Number underflow. Attempting to store a number with magnitude smaller than supported range'], - [{N: '-1e-131'}, 'Number underflow. Attempting to store a number with magnitude smaller than supported range'], - ], function(expr, cb) { + [ { S: '', N: '' }, 'The parameter cannot be converted to a numeric value' ], + [ { S: 'a', N: '' }, 'The parameter cannot be converted to a numeric value' ], + [ { S: 'a', N: 'b' }, 'The parameter cannot be converted to a numeric value: b' ], + [ { NS: [ '1', '' ] }, 'The parameter cannot be converted to a numeric value' ], + [ { NS: [ '1', 'b' ] }, 'The parameter cannot be converted to a numeric value: b' ], + [ { NS: [ '1', '1' ] }, 'Input collection contains duplicates' ], + [ { N: '123456789012345678901234567890123456789' }, 'Attempting to store more than 38 significant digits in a Number' ], + [ { N: '-1.23456789012345678901234567890123456789' }, 'Attempting to store more than 38 significant digits in a Number' ], + [ { N: '1e126' }, 'Number overflow. Attempting to store a number with magnitude larger than supported range' ], + [ { N: '-1e126' }, 'Number overflow. Attempting to store a number with magnitude larger than supported range' ], + [ { N: '1e-131' }, 'Number underflow. Attempting to store a number with magnitude smaller than supported range' ], + [ { N: '-1e-131' }, 'Number underflow. Attempting to store a number with magnitude smaller than supported range' ], + ], function (expr, cb) { assertValidation({ TableName: 'abc', Segment: 1, - ExclusiveStartKey: {a: {}}, - ScanFilter: {a: {ComparisonOperator: 'EQ', AttributeValueList: [{N: '1'}, expr[0]]}}, + ExclusiveStartKey: { a: {} }, + ScanFilter: { a: { ComparisonOperator: 'EQ', AttributeValueList: [ { N: '1' }, expr[0] ] } }, }, expr[1], cb) }, done) }) - it('should return ValidationException for multiple datatypes in ScanFilter', function(done) { + it('should return ValidationException for multiple datatypes in ScanFilter', function (done) { assertValidation({ TableName: 'abc', Segment: 1, - ExclusiveStartKey: {a: {}}, - ScanFilter: {a: {ComparisonOperator: 'EQ', AttributeValueList: [{N: '1'}, {S: 'a', N: '1'}]}}, + ExclusiveStartKey: { a: {} }, + ScanFilter: { a: { ComparisonOperator: 'EQ', AttributeValueList: [ { N: '1' }, { S: 'a', N: '1' } ] } }, }, 'Supplied AttributeValue has more than one datatypes set, must contain exactly one of the supported datatypes', done) }) - it('should return ValidationException for incorrect number of ScanFilter arguments', function(done) { + it('should return ValidationException for incorrect number of ScanFilter arguments', function (done) { async.forEach([ - {a: {ComparisonOperator: 'EQ'}, b: {ComparisonOperator: 'NULL'}, c: {ComparisonOperator: 'NULL'}}, - {a: {ComparisonOperator: 'EQ'}}, - {a: {ComparisonOperator: 'EQ', AttributeValueList: []}}, - {a: {ComparisonOperator: 'NE'}}, - {a: {ComparisonOperator: 'LE'}}, - {a: {ComparisonOperator: 'LT'}}, - {a: {ComparisonOperator: 'GE'}}, - {a: {ComparisonOperator: 'GT'}}, - {a: {ComparisonOperator: 'CONTAINS'}}, - {a: {ComparisonOperator: 'NOT_CONTAINS'}}, - {a: {ComparisonOperator: 'BEGINS_WITH'}}, - {a: {ComparisonOperator: 'IN'}}, - {a: {ComparisonOperator: 'BETWEEN'}}, - {a: {ComparisonOperator: 'NULL', AttributeValueList: [{S: 'a'}]}}, - {a: {ComparisonOperator: 'NOT_NULL', AttributeValueList: [{S: 'a'}]}}, - {a: {ComparisonOperator: 'EQ', AttributeValueList: [{S: 'a'}, {S: 'a'}]}}, - {a: {ComparisonOperator: 'NE', AttributeValueList: [{S: 'a'}, {S: 'a'}]}}, - {a: {ComparisonOperator: 'LE', AttributeValueList: [{S: 'a'}, {S: 'a'}]}}, - {a: {ComparisonOperator: 'LT', AttributeValueList: [{S: 'a'}, {S: 'a'}]}}, - {a: {ComparisonOperator: 'GE', AttributeValueList: [{S: 'a'}, {S: 'a'}]}}, - {a: {ComparisonOperator: 'GT', AttributeValueList: [{S: 'a'}, {S: 'a'}]}}, - {a: {ComparisonOperator: 'CONTAINS', AttributeValueList: [{S: 'a'}, {S: 'a'}]}}, - {a: {ComparisonOperator: 'NOT_CONTAINS', AttributeValueList: [{S: 'a'}, {S: 'a'}]}}, - {a: {ComparisonOperator: 'NULL', AttributeValueList: [{S: 'a'}, {S: 'a'}]}}, - {a: {ComparisonOperator: 'NOT_NULL', AttributeValueList: [{S: 'a'}, {S: 'a'}]}}, - {a: {ComparisonOperator: 'BETWEEN', AttributeValueList: [{S: 'a'}, {S: 'a'}, {S: 'a'}]}}, - ], function(expr, cb) { + { a: { ComparisonOperator: 'EQ' }, b: { ComparisonOperator: 'NULL' }, c: { ComparisonOperator: 'NULL' } }, + { a: { ComparisonOperator: 'EQ' } }, + { a: { ComparisonOperator: 'EQ', AttributeValueList: [] } }, + { a: { ComparisonOperator: 'NE' } }, + { a: { ComparisonOperator: 'LE' } }, + { a: { ComparisonOperator: 'LT' } }, + { a: { ComparisonOperator: 'GE' } }, + { a: { ComparisonOperator: 'GT' } }, + { a: { ComparisonOperator: 'CONTAINS' } }, + { a: { ComparisonOperator: 'NOT_CONTAINS' } }, + { a: { ComparisonOperator: 'BEGINS_WITH' } }, + { a: { ComparisonOperator: 'IN' } }, + { a: { ComparisonOperator: 'BETWEEN' } }, + { a: { ComparisonOperator: 'NULL', AttributeValueList: [ { S: 'a' } ] } }, + { a: { ComparisonOperator: 'NOT_NULL', AttributeValueList: [ { S: 'a' } ] } }, + { a: { ComparisonOperator: 'EQ', AttributeValueList: [ { S: 'a' }, { S: 'a' } ] } }, + { a: { ComparisonOperator: 'NE', AttributeValueList: [ { S: 'a' }, { S: 'a' } ] } }, + { a: { ComparisonOperator: 'LE', AttributeValueList: [ { S: 'a' }, { S: 'a' } ] } }, + { a: { ComparisonOperator: 'LT', AttributeValueList: [ { S: 'a' }, { S: 'a' } ] } }, + { a: { ComparisonOperator: 'GE', AttributeValueList: [ { S: 'a' }, { S: 'a' } ] } }, + { a: { ComparisonOperator: 'GT', AttributeValueList: [ { S: 'a' }, { S: 'a' } ] } }, + { a: { ComparisonOperator: 'CONTAINS', AttributeValueList: [ { S: 'a' }, { S: 'a' } ] } }, + { a: { ComparisonOperator: 'NOT_CONTAINS', AttributeValueList: [ { S: 'a' }, { S: 'a' } ] } }, + { a: { ComparisonOperator: 'NULL', AttributeValueList: [ { S: 'a' }, { S: 'a' } ] } }, + { a: { ComparisonOperator: 'NOT_NULL', AttributeValueList: [ { S: 'a' }, { S: 'a' } ] } }, + { a: { ComparisonOperator: 'BETWEEN', AttributeValueList: [ { S: 'a' }, { S: 'a' }, { S: 'a' } ] } }, + ], function (expr, cb) { assertValidation({ TableName: 'abc', Segment: 1, - ExclusiveStartKey: {a: {}}, + ExclusiveStartKey: { a: {} }, ScanFilter: expr, }, 'One or more parameter values were invalid: Invalid number of argument(s) for the ' + expr.a.ComparisonOperator + ' ComparisonOperator', cb) }, done) }) - it('should return ValidationException for invalid ComparisonOperator types', function(done) { + it('should return ValidationException for invalid ComparisonOperator types', function (done) { async.forEach([ 'LT', 'LE', 'GT', 'GE', 'IN', - ], function(cond, cb) { + ], function (cond, cb) { async.forEach([ - [{BOOL: true}], - [{NULL: true}], - [{SS: ['a']}], - [{NS: ['1']}], - [{BS: ['abcd']}], - [{M: {}}], - [{L: []}], - ], function(list, cb) { + [ { BOOL: true } ], + [ { NULL: true } ], + [ { SS: [ 'a' ] } ], + [ { NS: [ '1' ] } ], + [ { BS: [ 'abcd' ] } ], + [ { M: {} } ], + [ { L: [] } ], + ], function (list, cb) { assertValidation({ TableName: 'abc', Segment: 1, - ExclusiveStartKey: {a: {}}, - ScanFilter: {a: {ComparisonOperator: cond, AttributeValueList: list}}, + ExclusiveStartKey: { a: {} }, + ScanFilter: { a: { ComparisonOperator: cond, AttributeValueList: list } }, }, 'One or more parameter values were invalid: ' + 'ComparisonOperator ' + cond + ' is not valid for ' + Object.keys(list[0])[0] + ' AttributeValue type', cb) @@ -360,23 +360,23 @@ describe('scan', function() { }, done) }) - it('should return ValidationException for invalid CONTAINS ComparisonOperator types', function(done) { + it('should return ValidationException for invalid CONTAINS ComparisonOperator types', function (done) { async.forEach([ 'CONTAINS', 'NOT_CONTAINS', - ], function(cond, cb) { + ], function (cond, cb) { async.forEach([ - [{SS: ['a']}], - [{NS: ['1']}], - [{BS: ['abcd']}], - [{M: {}}], - [{L: []}], - ], function(list, cb) { + [ { SS: [ 'a' ] } ], + [ { NS: [ '1' ] } ], + [ { BS: [ 'abcd' ] } ], + [ { M: {} } ], + [ { L: [] } ], + ], function (list, cb) { assertValidation({ TableName: 'abc', Segment: 1, - ExclusiveStartKey: {a: {}}, - ScanFilter: {a: {ComparisonOperator: cond, AttributeValueList: list}}, + ExclusiveStartKey: { a: {} }, + ScanFilter: { a: { ComparisonOperator: cond, AttributeValueList: list } }, }, 'One or more parameter values were invalid: ' + 'ComparisonOperator ' + cond + ' is not valid for ' + Object.keys(list[0])[0] + ' AttributeValue type', cb) @@ -384,153 +384,153 @@ describe('scan', function() { }, done) }) - it('should return ValidationException for invalid BETWEEN ComparisonOperator types', function(done) { + it('should return ValidationException for invalid BETWEEN ComparisonOperator types', function (done) { async.forEach([ - [{BOOL: true}, {BOOL: true}], - [{NULL: true}, {NULL: true}], - [{SS: ['a']}, {SS: ['a']}], - [{NS: ['1']}, {NS: ['1']}], - [{BS: ['abcd']}, {BS: ['abcd']}], - [{M: {}}, {M: {}}], - [{L: []}, {L: []}], - ], function(list, cb) { + [ { BOOL: true }, { BOOL: true } ], + [ { NULL: true }, { NULL: true } ], + [ { SS: [ 'a' ] }, { SS: [ 'a' ] } ], + [ { NS: [ '1' ] }, { NS: [ '1' ] } ], + [ { BS: [ 'abcd' ] }, { BS: [ 'abcd' ] } ], + [ { M: {} }, { M: {} } ], + [ { L: [] }, { L: [] } ], + ], function (list, cb) { assertValidation({ TableName: 'abc', Segment: 1, - ExclusiveStartKey: {a: {}}, - ScanFilter: {a: {ComparisonOperator: 'BETWEEN', AttributeValueList: list}}, + ExclusiveStartKey: { a: {} }, + ScanFilter: { a: { ComparisonOperator: 'BETWEEN', AttributeValueList: list } }, }, 'One or more parameter values were invalid: ' + 'ComparisonOperator BETWEEN is not valid for ' + Object.keys(list[0])[0] + ' AttributeValue type', cb) }, done) }) - it('should return ValidationException for invalid BEGINS_WITH ComparisonOperator types', function(done) { + it('should return ValidationException for invalid BEGINS_WITH ComparisonOperator types', function (done) { async.forEach([ - [{N: '1'}], + [ { N: '1' } ], // [{B: 'YQ=='}], // B is fine - [{BOOL: true}], - [{NULL: true}], - [{SS: ['a']}], - [{NS: ['1']}], - [{BS: ['abcd']}], - [{M: {}}], - [{L: []}], - ], function(list, cb) { + [ { BOOL: true } ], + [ { NULL: true } ], + [ { SS: [ 'a' ] } ], + [ { NS: [ '1' ] } ], + [ { BS: [ 'abcd' ] } ], + [ { M: {} } ], + [ { L: [] } ], + ], function (list, cb) { assertValidation({ TableName: 'abc', Segment: 1, - ExclusiveStartKey: {a: {}}, - ScanFilter: {a: {ComparisonOperator: 'BEGINS_WITH', AttributeValueList: list}}, + ExclusiveStartKey: { a: {} }, + ScanFilter: { a: { ComparisonOperator: 'BEGINS_WITH', AttributeValueList: list } }, }, 'One or more parameter values were invalid: ' + 'ComparisonOperator BEGINS_WITH is not valid for ' + Object.keys(list[0])[0] + ' AttributeValue type', cb) }, done) }) - it('should return ValidationException on ExclusiveStartKey if ScanFilter ok with EQ on type SS when table does not exist', function(done) { + it('should return ValidationException on ExclusiveStartKey if ScanFilter ok with EQ on type SS when table does not exist', function (done) { assertValidation({ TableName: 'abc', Segment: 1, - ExclusiveStartKey: {a: {}}, - ScanFilter: {a: {ComparisonOperator: 'EQ', AttributeValueList: [{SS: ['a']}]}}, + ExclusiveStartKey: { a: {} }, + ScanFilter: { a: { ComparisonOperator: 'EQ', AttributeValueList: [ { SS: [ 'a' ] } ] } }, }, 'The provided starting key is invalid: Supplied AttributeValue is empty, must contain exactly one of the supported datatypes', done) }) - it('should return ValidationException for unsupported datatype in ExclusiveStartKey', function(done) { + it('should return ValidationException for unsupported datatype in ExclusiveStartKey', function (done) { async.forEach([ {}, - {a: ''}, - {M: {a: {}}}, - {L: [{}]}, - {L: [{a: {}}]}, - ], function(expr, cb) { + { a: '' }, + { M: { a: {} } }, + { L: [ {} ] }, + { L: [ { a: {} } ] }, + ], function (expr, cb) { assertValidation({ TableName: 'abc', Segment: 1, FilterExpression: '', ExpressionAttributeNames: {}, ExpressionAttributeValues: {}, - ExclusiveStartKey: {a: expr}, + ExclusiveStartKey: { a: expr }, }, 'The provided starting key is invalid: ' + 'Supplied AttributeValue is empty, must contain exactly one of the supported datatypes', cb) }, done) }) - it('should return ValidationException for invalid values in ExclusiveStartKey', function(done) { + it('should return ValidationException for invalid values in ExclusiveStartKey', function (done) { async.forEach([ - [{NULL: 'no'}, 'Null attribute value types must have the value of true'], - [{SS: []}, 'An string set may not be empty'], - [{BS: []}, 'Binary sets should not be empty'], - ], function(expr, cb) { + [ { NULL: 'no' }, 'Null attribute value types must have the value of true' ], + [ { SS: [] }, 'An string set may not be empty' ], + [ { BS: [] }, 'Binary sets should not be empty' ], + ], function (expr, cb) { assertValidation({ TableName: 'abc', Segment: 1, FilterExpression: '', ExpressionAttributeNames: {}, ExpressionAttributeValues: {}, - ExclusiveStartKey: {a: expr[0]}, + ExclusiveStartKey: { a: expr[0] }, }, 'The provided starting key is invalid: ' + 'One or more parameter values were invalid: ' + expr[1], cb) }, done) }) - it('should return ValidationException for invalid values in ExclusiveStartKey with no provided message', function(done) { + it('should return ValidationException for invalid values in ExclusiveStartKey with no provided message', function (done) { async.forEach([ - [{NS: []}, 'An number set may not be empty'], - [{SS: ['a', 'a']}, 'Input collection [a, a] contains duplicates.'], - [{BS: ['Yg==', 'Yg==']}, 'Input collection [Yg==, Yg==]of type BS contains duplicates.'], - ], function(expr, cb) { + [ { NS: [] }, 'An number set may not be empty' ], + [ { SS: [ 'a', 'a' ] }, 'Input collection [a, a] contains duplicates.' ], + [ { BS: [ 'Yg==', 'Yg==' ] }, 'Input collection [Yg==, Yg==]of type BS contains duplicates.' ], + ], function (expr, cb) { assertValidation({ TableName: 'abc', Segment: 1, FilterExpression: '', ExpressionAttributeNames: {}, ExpressionAttributeValues: {}, - ExclusiveStartKey: {a: expr[0]}, + ExclusiveStartKey: { a: expr[0] }, }, 'One or more parameter values were invalid: ' + expr[1], cb) }, done) }) - it('should return ValidationException for empty/invalid numbers in ExclusiveStartKey', function(done) { + it('should return ValidationException for empty/invalid numbers in ExclusiveStartKey', function (done) { async.forEach([ - [{S: '', N: ''}, 'The parameter cannot be converted to a numeric value'], - [{S: 'a', N: ''}, 'The parameter cannot be converted to a numeric value'], - [{S: 'a', N: 'b'}, 'The parameter cannot be converted to a numeric value: b'], - [{NS: ['1', '']}, 'The parameter cannot be converted to a numeric value'], - [{NS: ['1', 'b']}, 'The parameter cannot be converted to a numeric value: b'], - [{NS: ['1', '1']}, 'Input collection contains duplicates'], - [{N: '123456789012345678901234567890123456789'}, 'Attempting to store more than 38 significant digits in a Number'], - [{N: '-1.23456789012345678901234567890123456789'}, 'Attempting to store more than 38 significant digits in a Number'], - [{N: '1e126'}, 'Number overflow. Attempting to store a number with magnitude larger than supported range'], - [{N: '-1e126'}, 'Number overflow. Attempting to store a number with magnitude larger than supported range'], - [{N: '1e-131'}, 'Number underflow. Attempting to store a number with magnitude smaller than supported range'], - [{N: '-1e-131'}, 'Number underflow. Attempting to store a number with magnitude smaller than supported range'], - ], function(expr, cb) { + [ { S: '', N: '' }, 'The parameter cannot be converted to a numeric value' ], + [ { S: 'a', N: '' }, 'The parameter cannot be converted to a numeric value' ], + [ { S: 'a', N: 'b' }, 'The parameter cannot be converted to a numeric value: b' ], + [ { NS: [ '1', '' ] }, 'The parameter cannot be converted to a numeric value' ], + [ { NS: [ '1', 'b' ] }, 'The parameter cannot be converted to a numeric value: b' ], + [ { NS: [ '1', '1' ] }, 'Input collection contains duplicates' ], + [ { N: '123456789012345678901234567890123456789' }, 'Attempting to store more than 38 significant digits in a Number' ], + [ { N: '-1.23456789012345678901234567890123456789' }, 'Attempting to store more than 38 significant digits in a Number' ], + [ { N: '1e126' }, 'Number overflow. Attempting to store a number with magnitude larger than supported range' ], + [ { N: '-1e126' }, 'Number overflow. Attempting to store a number with magnitude larger than supported range' ], + [ { N: '1e-131' }, 'Number underflow. Attempting to store a number with magnitude smaller than supported range' ], + [ { N: '-1e-131' }, 'Number underflow. Attempting to store a number with magnitude smaller than supported range' ], + ], function (expr, cb) { assertValidation({ TableName: 'abc', Segment: 1, FilterExpression: '', ExpressionAttributeNames: {}, ExpressionAttributeValues: {}, - ExclusiveStartKey: {a: expr[0]}, + ExclusiveStartKey: { a: expr[0] }, }, expr[1], cb) }, done) }) - it('should return ValidationException for multiple datatypes in ExclusiveStartKey', function(done) { + it('should return ValidationException for multiple datatypes in ExclusiveStartKey', function (done) { assertValidation({ TableName: 'abc', TotalSegments: 1, FilterExpression: '', ExpressionAttributeNames: {}, ExpressionAttributeValues: {}, - ExclusiveStartKey: {a: {S: 'a', N: '1'}}, + ExclusiveStartKey: { a: { S: 'a', N: '1' } }, }, 'The provided starting key is invalid: ' + 'Supplied AttributeValue has more than one datatypes set, must contain exactly one of the supported datatypes', done) }) - it('should return ValidationException for missing TotalSegments', function(done) { + it('should return ValidationException for missing TotalSegments', function (done) { assertValidation({ TableName: 'abc', Segment: 1, @@ -540,7 +540,7 @@ describe('scan', function() { }, 'The TotalSegments parameter is required but was not present in the request when Segment parameter is present', done) }) - it('should return ValidationException for missing Segment', function(done) { + it('should return ValidationException for missing Segment', function (done) { assertValidation({ TableName: 'abc', TotalSegments: 1, @@ -550,7 +550,7 @@ describe('scan', function() { }, 'The Segment parameter is required but was not present in the request when parameter TotalSegments is present', done) }) - it('should return ValidationException for Segment more than TotalSegments', function(done) { + it('should return ValidationException for Segment more than TotalSegments', function (done) { assertValidation({ TableName: 'abc', Segment: 1, @@ -561,7 +561,7 @@ describe('scan', function() { }, 'The Segment parameter is zero-based and must be less than parameter TotalSegments: Segment: 1 is not less than TotalSegments: 1', done) }) - it('should return ValidationException for empty ExpressionAttributeNames', function(done) { + it('should return ValidationException for empty ExpressionAttributeNames', function (done) { assertValidation({ TableName: 'abc', FilterExpression: '', @@ -570,16 +570,16 @@ describe('scan', function() { }, 'ExpressionAttributeNames must not be empty', done) }) - it('should return ValidationException for invalid ExpressionAttributeNames', function(done) { + it('should return ValidationException for invalid ExpressionAttributeNames', function (done) { assertValidation({ TableName: 'abc', FilterExpression: '', - ExpressionAttributeNames: {'a': 'a'}, + ExpressionAttributeNames: { 'a': 'a' }, ExpressionAttributeValues: {}, }, 'ExpressionAttributeNames contains invalid key: Syntax error; key: "a"', done) }) - it('should return ValidationException for empty ExpressionAttributeValues', function(done) { + it('should return ValidationException for empty ExpressionAttributeValues', function (done) { assertValidation({ TableName: 'abc', FilterExpression: '', @@ -587,24 +587,24 @@ describe('scan', function() { }, 'ExpressionAttributeValues must not be empty', done) }) - it('should return ValidationException for invalid ExpressionAttributeValues', function(done) { + it('should return ValidationException for invalid ExpressionAttributeValues', function (done) { assertValidation({ TableName: 'abc', FilterExpression: '', - ExpressionAttributeValues: {'a': {S: 'b'}}, + ExpressionAttributeValues: { 'a': { S: 'b' } }, }, 'ExpressionAttributeValues contains invalid key: Syntax error; key: "a"', done) }) - it('should return ValidationException for empty FilterExpression', function(done) { + it('should return ValidationException for empty FilterExpression', function (done) { assertValidation({ TableName: 'abc', FilterExpression: '', ProjectionExpression: '', - ExpressionAttributeValues: {':0': {S: 'b'}}, + ExpressionAttributeValues: { ':0': { S: 'b' } }, }, 'Invalid FilterExpression: The expression can not be empty;', done) }) - it('should return ValidationException for empty ProjectionExpression', function(done) { + it('should return ValidationException for empty ProjectionExpression', function (done) { assertValidation({ TableName: 'abc', FilterExpression: 'a > b', @@ -612,7 +612,7 @@ describe('scan', function() { }, 'Invalid ProjectionExpression: The expression can not be empty;', done) }) - it('should return ValidationException for syntax errors', function(done) { + it('should return ValidationException for syntax errors', function (done) { var expressions = [ 'things are not gonna be ok', 'a > 4', @@ -640,7 +640,7 @@ describe('scan', function() { 'size(a)[0] > a', '(size(a))[0] > a', ] - async.forEach(expressions, function(expression, cb) { + async.forEach(expressions, function (expression, cb) { assertValidation({ TableName: 'abc', FilterExpression: expression, @@ -648,7 +648,7 @@ describe('scan', function() { }, done) }) - it('should return ValidationException for redundant parentheses', function(done) { + it('should return ValidationException for redundant parentheses', function (done) { var expressions = [ 'a=a and a > ((views))', '(a)between(((b.c)).d)and(c)', @@ -658,7 +658,7 @@ describe('scan', function() { 'a=a AND ((a=a AND (a=a AND a=a)))', 'a=a OR ((a=a OR (a=a OR a=a)))', ] - async.forEach(expressions, function(expression, cb) { + async.forEach(expressions, function (expression, cb) { assertValidation({ TableName: 'abc', FilterExpression: expression, @@ -666,12 +666,12 @@ describe('scan', function() { }, done) }) - it('should return ValidationException for invalid function names', function(done) { + it('should return ValidationException for invalid function names', function (done) { var expressions = [ - ['a=a and whatever((:things)) > a', 'whatever'], - ['attRIbute_exIsts((views), #a)', 'attRIbute_exIsts'], + [ 'a=a and whatever((:things)) > a', 'whatever' ], + [ 'attRIbute_exIsts((views), #a)', 'attRIbute_exIsts' ], ] - async.forEach(expressions, function(expr, cb) { + async.forEach(expressions, function (expr, cb) { assertValidation({ TableName: 'abc', FilterExpression: expr[0], @@ -679,19 +679,19 @@ describe('scan', function() { }, done) }) - it('should return ValidationException for functions used incorrectly', function(done) { + it('should return ValidationException for functions used incorrectly', function (done) { var expressions = [ - ['a=a and attribute_exists((views), (#a)) > b', 'attribute_exists'], - ['attribute_not_exists(things) > b', 'attribute_not_exists'], - ['attribute_type(things, :a) > b', 'attribute_type'], - ['begins_with(things, a) > b', 'begins_with'], - ['contains(:things, c) > b', 'contains'], - ['size(contains(a, b)) > a', 'contains'], - ['size(things)', 'size'], - ['a between b and attribute_exists(things)', 'attribute_exists'], - ['a in (b, attribute_exists(things))', 'attribute_exists'], + [ 'a=a and attribute_exists((views), (#a)) > b', 'attribute_exists' ], + [ 'attribute_not_exists(things) > b', 'attribute_not_exists' ], + [ 'attribute_type(things, :a) > b', 'attribute_type' ], + [ 'begins_with(things, a) > b', 'begins_with' ], + [ 'contains(:things, c) > b', 'contains' ], + [ 'size(contains(a, b)) > a', 'contains' ], + [ 'size(things)', 'size' ], + [ 'a between b and attribute_exists(things)', 'attribute_exists' ], + [ 'a in (b, attribute_exists(things))', 'attribute_exists' ], ] - async.forEach(expressions, function(expr, cb) { + async.forEach(expressions, function (expr, cb) { assertValidation({ TableName: 'abc', FilterExpression: expr[0], @@ -699,12 +699,12 @@ describe('scan', function() { }, done) }) - it('should return ValidationException for reserved keywords', function(done) { + it('should return ValidationException for reserved keywords', function (done) { var expressions = [ - ['attribute_exists(views, #a)', 'views'], - [':a < abOrT', 'abOrT'], + [ 'attribute_exists(views, #a)', 'views' ], + [ ':a < abOrT', 'abOrT' ], ] - async.forEach(expressions, function(expr, cb) { + async.forEach(expressions, function (expr, cb) { assertValidation({ TableName: 'abc', FilterExpression: expr[0], @@ -714,16 +714,16 @@ describe('scan', function() { // All checks below here are done on a per-expression basis - it('should return ValidationException for missing attribute names', function(done) { + it('should return ValidationException for missing attribute names', function (done) { var expressions = [ - ['attribute_exists(#Pictures.RearView, :a) and a=a', '#Pictures'], - ['begins_with(Pictures.#RearView)', '#RearView'], - ['(#P between :lo and :hi) and (#PC in (:cat1, :cat2))', '#P'], - ['#4g > a', '#4g'], - ['#_ > a', '#_'], - ['(a)between(b.c[45].#d)and(:a)', '#d'], + [ 'attribute_exists(#Pictures.RearView, :a) and a=a', '#Pictures' ], + [ 'begins_with(Pictures.#RearView)', '#RearView' ], + [ '(#P between :lo and :hi) and (#PC in (:cat1, :cat2))', '#P' ], + [ '#4g > a', '#4g' ], + [ '#_ > a', '#_' ], + [ '(a)between(b.c[45].#d)and(:a)', '#d' ], ] - async.forEach(expressions, function(expr, cb) { + async.forEach(expressions, function (expr, cb) { assertValidation({ TableName: 'abc', FilterExpression: expr[0], @@ -731,13 +731,13 @@ describe('scan', function() { }, done) }) - it('should return ValidationException for missing attribute values', function(done) { + it('should return ValidationException for missing attribute values', function (done) { var expressions = [ - ['begins_with(:hello, #a, #b)', ':hello'], - [':a < :b', ':a'], - [':_ > a', ':_'], + [ 'begins_with(:hello, #a, #b)', ':hello' ], + [ ':a < :b', ':a' ], + [ ':_ > a', ':_' ], ] - async.forEach(expressions, function(expr, cb) { + async.forEach(expressions, function (expr, cb) { assertValidation({ TableName: 'abc', FilterExpression: expr[0], @@ -745,121 +745,121 @@ describe('scan', function() { }, done) }) - it('should return ValidationException for functions with incorrect operands', function(done) { + it('should return ValidationException for functions with incorrect operands', function (done) { var expressions = [ - ['attribute_exists(things, a) and a=a', 'attribute_exists', 2], - ['attribute_not_exists(things, b)', 'attribute_not_exists', 2], - ['attribute_type(things)', 'attribute_type', 1], - ['begins_with(things)', 'begins_with', 1], - ['begins_with(things, size(a), b)', 'begins_with', 3], - ['contains(things)', 'contains', 1], - ['size(things, a) > b', 'size', 2], + [ 'attribute_exists(things, a) and a=a', 'attribute_exists', 2 ], + [ 'attribute_not_exists(things, b)', 'attribute_not_exists', 2 ], + [ 'attribute_type(things)', 'attribute_type', 1 ], + [ 'begins_with(things)', 'begins_with', 1 ], + [ 'begins_with(things, size(a), b)', 'begins_with', 3 ], + [ 'contains(things)', 'contains', 1 ], + [ 'size(things, a) > b', 'size', 2 ], ] - async.forEach(expressions, function(expr, cb) { + async.forEach(expressions, function (expr, cb) { assertValidation({ TableName: 'abc', FilterExpression: expr[0], }, 'Invalid FilterExpression: Incorrect number of operands for operator or function; operator or function: ' + - expr[1] +', number of operands: ' + expr[2], cb) + expr[1] + ', number of operands: ' + expr[2], cb) }, done) }) - it('should return ValidationException for functions with incorrect operand type', function(done) { + it('should return ValidationException for functions with incorrect operand type', function (done) { var expressions = [ // Order of the {...} args is non-deterministic // ['attribute_type(ab.bc[1].a, SS)', 'attribute_type', '{NS,SS,L,BS,N,M,B,BOOL,NULL,S}'], - ['attribute_type(a, size(a)) and a=a and a=:a', 'attribute_type', {'N': '1'}], - ['attribute_type(a, :a)', 'attribute_type', {'N': '1'}], - ['attribute_type(a, :a)', 'attribute_type', {'B': 'YQ=='}], - ['attribute_type(a, :a)', 'attribute_type', {'BOOL': true}], - ['attribute_type(a, :a)', 'attribute_type', {'NULL': true}], - ['attribute_type(a, :a)', 'attribute_type', {'L': []}], - ['attribute_type(a, :a)', 'attribute_type', {'M': {}}], - ['attribute_type(a, :a)', 'attribute_type', {'SS': ['1']}], - ['attribute_type(a, :a)', 'attribute_type', {'NS': ['1']}], - ['attribute_type(a, :a)', 'attribute_type', {'BS': ['YQ==']}], - ['begins_with(a, size(a)) and a=:a', 'begins_with', {'N': '1'}], - ['begins_with(a, :a)', 'begins_with', {'N': '1'}], - ['begins_with(a, :a)', 'begins_with', {'BOOL': true}], - ['begins_with(a, :a)', 'begins_with', {'NULL': true}], - ['begins_with(a, :a)', 'begins_with', {'L': []}], - ['begins_with(a, :a)', 'begins_with', {'M': {}}], - ['begins_with(a, :a)', 'begins_with', {'SS': ['1']}], - ['begins_with(a, :a)', 'begins_with', {'NS': ['1']}], - ['begins_with(a, :a)', 'begins_with', {'BS': ['YQ==']}], - ['begins_with(:a, a)', 'begins_with', {'N': '1'}], - ['begins_with(:a, a)', 'begins_with', {'BOOL': true}], - ['begins_with(:a, a)', 'begins_with', {'NULL': true}], - ['begins_with(:a, a)', 'begins_with', {'L': []}], - ['begins_with(:a, a)', 'begins_with', {'M': {}}], - ['begins_with(:a, a)', 'begins_with', {'SS': ['1']}], - ['begins_with(:a, a)', 'begins_with', {'NS': ['1']}], - ['begins_with(:a, a)', 'begins_with', {'BS': ['YQ==']}], - ['size(size(a)) > :a', 'size', {'N': '1'}], - ['attribute_not_exists(size(:a))', 'size', {'N': '1'}], - ['size(:a) > a', 'size', {'BOOL': true}], - ['size(:a) > a', 'size', {'NULL': true}], + [ 'attribute_type(a, size(a)) and a=a and a=:a', 'attribute_type', { 'N': '1' } ], + [ 'attribute_type(a, :a)', 'attribute_type', { 'N': '1' } ], + [ 'attribute_type(a, :a)', 'attribute_type', { 'B': 'YQ==' } ], + [ 'attribute_type(a, :a)', 'attribute_type', { 'BOOL': true } ], + [ 'attribute_type(a, :a)', 'attribute_type', { 'NULL': true } ], + [ 'attribute_type(a, :a)', 'attribute_type', { 'L': [] } ], + [ 'attribute_type(a, :a)', 'attribute_type', { 'M': {} } ], + [ 'attribute_type(a, :a)', 'attribute_type', { 'SS': [ '1' ] } ], + [ 'attribute_type(a, :a)', 'attribute_type', { 'NS': [ '1' ] } ], + [ 'attribute_type(a, :a)', 'attribute_type', { 'BS': [ 'YQ==' ] } ], + [ 'begins_with(a, size(a)) and a=:a', 'begins_with', { 'N': '1' } ], + [ 'begins_with(a, :a)', 'begins_with', { 'N': '1' } ], + [ 'begins_with(a, :a)', 'begins_with', { 'BOOL': true } ], + [ 'begins_with(a, :a)', 'begins_with', { 'NULL': true } ], + [ 'begins_with(a, :a)', 'begins_with', { 'L': [] } ], + [ 'begins_with(a, :a)', 'begins_with', { 'M': {} } ], + [ 'begins_with(a, :a)', 'begins_with', { 'SS': [ '1' ] } ], + [ 'begins_with(a, :a)', 'begins_with', { 'NS': [ '1' ] } ], + [ 'begins_with(a, :a)', 'begins_with', { 'BS': [ 'YQ==' ] } ], + [ 'begins_with(:a, a)', 'begins_with', { 'N': '1' } ], + [ 'begins_with(:a, a)', 'begins_with', { 'BOOL': true } ], + [ 'begins_with(:a, a)', 'begins_with', { 'NULL': true } ], + [ 'begins_with(:a, a)', 'begins_with', { 'L': [] } ], + [ 'begins_with(:a, a)', 'begins_with', { 'M': {} } ], + [ 'begins_with(:a, a)', 'begins_with', { 'SS': [ '1' ] } ], + [ 'begins_with(:a, a)', 'begins_with', { 'NS': [ '1' ] } ], + [ 'begins_with(:a, a)', 'begins_with', { 'BS': [ 'YQ==' ] } ], + [ 'size(size(a)) > :a', 'size', { 'N': '1' } ], + [ 'attribute_not_exists(size(:a))', 'size', { 'N': '1' } ], + [ 'size(:a) > a', 'size', { 'BOOL': true } ], + [ 'size(:a) > a', 'size', { 'NULL': true } ], ] - async.forEach(expressions, function(expr, cb) { + async.forEach(expressions, function (expr, cb) { assertValidation({ TableName: 'abc', FilterExpression: expr[0], - ExpressionAttributeValues: {':a': expr[2]}, + ExpressionAttributeValues: { ':a': expr[2] }, }, 'Invalid FilterExpression: Incorrect operand type for operator or function; operator or function: ' + expr[1] + ', operand type: ' + Object.keys(expr[2])[0], cb) }, done) }) - it('should return ValidationException for attribute_type with incorrect value', function(done) { + it('should return ValidationException for attribute_type with incorrect value', function (done) { assertValidation({ TableName: 'abc', FilterExpression: 'attribute_type(a, :a)', - ExpressionAttributeValues: {':a': {'S': '1'}}, + ExpressionAttributeValues: { ':a': { 'S': '1' } }, }, /^Invalid FilterExpression: Invalid attribute type name found; type: 1, valid types: {((B|NULL|SS|BOOL|L|BS|N|NS|S|M),?){10}}$/, done) }) - it('should return ValidationException for functions with attr values instead of paths', function(done) { + it('should return ValidationException for functions with attr values instead of paths', function (done) { var expressions = [ - ['attribute_exists(:a) and a=a', 'attribute_exists'], - ['attribute_not_exists(size(:a))', 'attribute_not_exists'], + [ 'attribute_exists(:a) and a=a', 'attribute_exists' ], + [ 'attribute_not_exists(size(:a))', 'attribute_not_exists' ], ] - async.forEach(expressions, function(expr, cb) { + async.forEach(expressions, function (expr, cb) { assertValidation({ TableName: 'abc', FilterExpression: expr[0], - ExpressionAttributeValues: {':a': {'S': '1'}}, + ExpressionAttributeValues: { ':a': { 'S': '1' } }, }, 'Invalid FilterExpression: Operator or function requires a document path; operator or function: ' + expr[1], cb) }, done) }) - it('should return ValidationException for non-distinct expressions', function(done) { + it('should return ValidationException for non-distinct expressions', function (done) { var expressions = [ - ['a = a AND #a = b AND :views > a', '=', '[a]'], - ['#a <> a', '<>', '[a]'], - ['a > #a', '>', '[a]'], - ['((a=a) OR (a=a))', '=', '[a]'], - ['((a=a) AND (a=a))', '=', '[a]'], - ['contains(ab.bc[1].a, ab.bc[1].#a)', 'contains', '[ab, bc, [1], a]'], - ['attribute_type(ab.bc[1].#a, ab.bc[1].a)', 'attribute_type', '[ab, bc, [1], a]'], - ['begins_with(ab.bc[1].a, ab.bc[1].#a)', 'begins_with', '[ab, bc, [1], a]'], + [ 'a = a AND #a = b AND :views > a', '=', '[a]' ], + [ '#a <> a', '<>', '[a]' ], + [ 'a > #a', '>', '[a]' ], + [ '((a=a) OR (a=a))', '=', '[a]' ], + [ '((a=a) AND (a=a))', '=', '[a]' ], + [ 'contains(ab.bc[1].a, ab.bc[1].#a)', 'contains', '[ab, bc, [1], a]' ], + [ 'attribute_type(ab.bc[1].#a, ab.bc[1].a)', 'attribute_type', '[ab, bc, [1], a]' ], + [ 'begins_with(ab.bc[1].a, ab.bc[1].#a)', 'begins_with', '[ab, bc, [1], a]' ], // ':a > :a', ... is ok ] - async.forEach(expressions, function(expr, cb) { + async.forEach(expressions, function (expr, cb) { assertValidation({ TableName: 'abc', FilterExpression: expr[0], - ExpressionAttributeNames: {'#a': 'a'}, + ExpressionAttributeNames: { '#a': 'a' }, }, 'Invalid FilterExpression: The first operand must be distinct from the remaining operands for this operator or function; operator: ' + expr[1] + ', first operand: ' + expr[2], cb) }, done) }) - it('should check table exists before checking key validity', function(done) { + it('should check table exists before checking key validity', function (done) { async.forEach([ {}, - {b: {S: 'a'}}, - {a: {S: 'a'}, b: {S: 'a'}}, - ], function(expr, cb) { + { b: { S: 'a' } }, + { a: { S: 'a' }, b: { S: 'a' } }, + ], function (expr, cb) { assertNotFound({ TableName: 'abc', ExclusiveStartKey: expr, @@ -867,14 +867,14 @@ describe('scan', function() { }, done) }) - it('should return ValidationException if unknown index and bad ExclusiveStartKey in hash table', function(done) { + it('should return ValidationException if unknown index and bad ExclusiveStartKey in hash table', function (done) { async.forEach([ {}, // {z: {S: 'a'}}, // Returns a 500 // {a: {S: 'a'}, b: {S: 'a'}}, // Returns a 500 - {a: {S: 'a'}, b: {S: 'a'}, c: {S: 'a'}}, - {z: {S: 'a'}, y: {S: 'a'}, x: {S: 'a'}}, - ], function(expr, cb) { + { a: { S: 'a' }, b: { S: 'a' }, c: { S: 'a' } }, + { z: { S: 'a' }, y: { S: 'a' }, x: { S: 'a' } }, + ], function (expr, cb) { assertValidation({ TableName: helpers.testHashTable, IndexName: 'whatever', @@ -884,14 +884,14 @@ describe('scan', function() { }, done) }) - it('should return ValidationException if unknown index and bad ExclusiveStartKey in range table', function(done) { + it('should return ValidationException if unknown index and bad ExclusiveStartKey in range table', function (done) { async.forEach([ {}, - {z: {S: 'a'}}, + { z: { S: 'a' } }, // {a: {S: 'a'}, b: {S: 'a'}}, // Returns a 500 - {a: {S: 'a'}, b: {S: 'a'}, c: {S: 'a'}}, - {z: {S: 'a'}, y: {S: 'a'}, x: {S: 'a'}, w: {S: 'a'}}, - ], function(expr, cb) { + { a: { S: 'a' }, b: { S: 'a' }, c: { S: 'a' } }, + { z: { S: 'a' }, y: { S: 'a' }, x: { S: 'a' }, w: { S: 'a' } }, + ], function (expr, cb) { assertValidation({ TableName: helpers.testRangeTable, IndexName: 'whatever', @@ -901,19 +901,19 @@ describe('scan', function() { }, done) }) - it('should return ValidationException if ExclusiveStartKey is invalid for local index', function(done) { + it('should return ValidationException if ExclusiveStartKey is invalid for local index', function (done) { async.forEach([ {}, - {z: {N: '1'}}, - {a: {B: 'abcd'}}, - {a: {S: 'a'}}, - {a: {S: 'a'}, b: {S: 'a'}}, - {a: {S: 'a'}, c: {S: 'a'}}, - {b: {S: 'a'}, c: {S: 'a'}}, - {a: {S: 'a'}, c: {N: '1'}}, - {a: {S: 'a'}, z: {S: '1'}}, - {a: {S: 'a'}, b: {S: '1'}, c: {S: '1'}, d: {S: '1'}}, - ], function(expr, cb) { + { z: { N: '1' } }, + { a: { B: 'abcd' } }, + { a: { S: 'a' } }, + { a: { S: 'a' }, b: { S: 'a' } }, + { a: { S: 'a' }, c: { S: 'a' } }, + { b: { S: 'a' }, c: { S: 'a' } }, + { a: { S: 'a' }, c: { N: '1' } }, + { a: { S: 'a' }, z: { S: '1' } }, + { a: { S: 'a' }, b: { S: '1' }, c: { S: '1' }, d: { S: '1' } }, + ], function (expr, cb) { assertValidation({ TableName: helpers.testRangeTable, IndexName: 'index1', @@ -922,19 +922,19 @@ describe('scan', function() { }, done) }) - it('should return ValidationException if ExclusiveStartKey is invalid for global index', function(done) { + it('should return ValidationException if ExclusiveStartKey is invalid for global index', function (done) { async.forEach([ {}, - {z: {N: '1'}}, - {a: {B: 'abcd'}}, - {a: {S: 'a'}}, - {c: {N: '1'}}, - {c: {S: '1'}}, - {a: {S: 'a'}, b: {S: 'a'}}, - {a: {S: 'a'}, c: {S: 'a'}}, - {a: {S: 'a'}, b: {S: 'a'}, z: {S: 'a'}}, - {a: {S: 'a'}, b: {S: 'a'}, c: {S: 'a'}, z: {S: 'a'}}, - ], function(expr, cb) { + { z: { N: '1' } }, + { a: { B: 'abcd' } }, + { a: { S: 'a' } }, + { c: { N: '1' } }, + { c: { S: '1' } }, + { a: { S: 'a' }, b: { S: 'a' } }, + { a: { S: 'a' }, c: { S: 'a' } }, + { a: { S: 'a' }, b: { S: 'a' }, z: { S: 'a' } }, + { a: { S: 'a' }, b: { S: 'a' }, c: { S: 'a' }, z: { S: 'a' } }, + ], function (expr, cb) { assertValidation({ TableName: helpers.testRangeTable, IndexName: 'index3', @@ -943,14 +943,14 @@ describe('scan', function() { }, done) }) - it('should return ValidationException if global range in ExclusiveStartKey is invalid', function(done) { + it('should return ValidationException if global range in ExclusiveStartKey is invalid', function (done) { async.forEach([ - {c: {S: '1'}}, - {a: {N: '1'}, c: {S: '1'}}, - {a: {N: '1'}, b: {N: '1'}, c: {S: '1'}}, - {a: {N: '1'}, b: {N: '1'}, c: {S: '1'}, e: {N: '1'}}, - {a: {S: 'a'}, b: {S: '1'}, c: {S: '1'}, d: {S: '1'}, e: {S: '1'}}, - ], function(expr, cb) { + { c: { S: '1' } }, + { a: { N: '1' }, c: { S: '1' } }, + { a: { N: '1' }, b: { N: '1' }, c: { S: '1' } }, + { a: { N: '1' }, b: { N: '1' }, c: { S: '1' }, e: { N: '1' } }, + { a: { S: 'a' }, b: { S: '1' }, c: { S: '1' }, d: { S: '1' }, e: { S: '1' } }, + ], function (expr, cb) { assertValidation({ TableName: helpers.testRangeTable, IndexName: 'index4', @@ -960,11 +960,11 @@ describe('scan', function() { }, done) }) - it('should return ValidationException for non-existent index name', function(done) { + it('should return ValidationException for non-existent index name', function (done) { async.forEach([ helpers.testHashTable, helpers.testRangeTable, - ], function(table, cb) { + ], function (table, cb) { assertValidation({ TableName: table, IndexName: 'whatever', @@ -973,27 +973,27 @@ describe('scan', function() { }, done) }) - it('should return ValidationException for specifying ALL_ATTRIBUTES when global index does not have ALL', function(done) { + it('should return ValidationException for specifying ALL_ATTRIBUTES when global index does not have ALL', function (done) { assertValidation({ TableName: helpers.testRangeTable, FilterExpression: 'attribute_exists(a.b.c)', IndexName: 'index4', Select: 'ALL_ATTRIBUTES', - ExclusiveStartKey: {x: {N: '1'}, y: {N: '1'}, c: {S: 'a'}, d: {S: 'a'}}, + ExclusiveStartKey: { x: { N: '1' }, y: { N: '1' }, c: { S: 'a' }, d: { S: 'a' } }, }, 'One or more parameter values were invalid: ' + 'Select type ALL_ATTRIBUTES is not supported for global secondary index index4 ' + 'because its projection type is not ALL', done) }) - it('should return ValidationException if ExclusiveStartKey does not match schema for local index', function(done) { + it('should return ValidationException if ExclusiveStartKey does not match schema for local index', function (done) { async.forEach([ - {a: {N: '1'}, x: {S: '1'}, y: {S: '1'}}, - {a: {B: 'YQ=='}, b: {S: '1'}, c: {S: '1'}}, - {a: {S: 'a'}, b: {N: '1'}, c: {N: '1'}}, - {a: {S: 'a'}, b: {B: 'YQ=='}, c: {N: '1'}}, - {a: {S: 'a'}, b: {S: 'a'}, c: {N: '1'}}, - {a: {S: 'a'}, b: {S: 'a'}, c: {B: 'YQ=='}}, - ], function(expr, cb) { + { a: { N: '1' }, x: { S: '1' }, y: { S: '1' } }, + { a: { B: 'YQ==' }, b: { S: '1' }, c: { S: '1' } }, + { a: { S: 'a' }, b: { N: '1' }, c: { N: '1' } }, + { a: { S: 'a' }, b: { B: 'YQ==' }, c: { N: '1' } }, + { a: { S: 'a' }, b: { S: 'a' }, c: { N: '1' } }, + { a: { S: 'a' }, b: { S: 'a' }, c: { B: 'YQ==' } }, + ], function (expr, cb) { assertValidation({ TableName: helpers.testRangeTable, IndexName: 'index1', @@ -1002,11 +1002,11 @@ describe('scan', function() { }, done) }) - it('should return ValidationException if ExclusiveStartKey does not match schema for global index', function(done) { + it('should return ValidationException if ExclusiveStartKey does not match schema for global index', function (done) { async.forEach([ - {x: {S: '1'}, y: {S: '1'}, c: {N: '1'}}, - {a: {S: '1'}, b: {S: '1'}, c: {B: 'YQ=='}}, - ], function(expr, cb) { + { x: { S: '1' }, y: { S: '1' }, c: { N: '1' } }, + { a: { S: '1' }, b: { S: '1' }, c: { B: 'YQ==' } }, + ], function (expr, cb) { assertValidation({ TableName: helpers.testRangeTable, IndexName: 'index3', @@ -1015,11 +1015,11 @@ describe('scan', function() { }, done) }) - it('should return ValidationException if ExclusiveStartKey does not match schema for global compound index', function(done) { + it('should return ValidationException if ExclusiveStartKey does not match schema for global compound index', function (done) { async.forEach([ - {x: {N: '1'}, y: {N: '1'}, c: {S: '1'}, d: {N: '1'}}, - {x: {N: '1'}, y: {N: '1'}, c: {N: '1'}, d: {S: '1'}}, - ], function(expr, cb) { + { x: { N: '1' }, y: { N: '1' }, c: { S: '1' }, d: { N: '1' } }, + { x: { N: '1' }, y: { N: '1' }, c: { N: '1' }, d: { S: '1' } }, + ], function (expr, cb) { assertValidation({ TableName: helpers.testRangeTable, IndexName: 'index4', @@ -1028,21 +1028,21 @@ describe('scan', function() { }, done) }) - it('should return ValidationException if ExclusiveStartKey does not match schema', function(done) { + it('should return ValidationException if ExclusiveStartKey does not match schema', function (done) { async.forEach([ {}, - {b: {S: 'a'}}, - {a: {S: 'a'}, b: {S: 'a'}}, - {a: {B: 'abcd'}}, - {a: {N: '1'}}, - {a: {BOOL: true}}, - {a: {NULL: true}}, - {a: {SS: ['a']}}, - {a: {NS: ['1']}}, - {a: {BS: ['aaaa']}}, - {a: {M: {}}}, - {a: {L: []}}, - ], function(expr, cb) { + { b: { S: 'a' } }, + { a: { S: 'a' }, b: { S: 'a' } }, + { a: { B: 'abcd' } }, + { a: { N: '1' } }, + { a: { BOOL: true } }, + { a: { NULL: true } }, + { a: { SS: [ 'a' ] } }, + { a: { NS: [ '1' ] } }, + { a: { BS: [ 'aaaa' ] } }, + { a: { M: {} } }, + { a: { L: [] } }, + ], function (expr, cb) { assertValidation({ TableName: helpers.testHashTable, FilterExpression: 'attribute_exists(a.b.c)', @@ -1051,24 +1051,24 @@ describe('scan', function() { }, done) }) - it('should return ValidationException if ExclusiveStartKey for range table is invalid', function(done) { + it('should return ValidationException if ExclusiveStartKey for range table is invalid', function (done) { async.forEach([ {}, - {z: {N: '1'}}, - {b: {S: 'a'}, c: {S: 'b'}}, - {a: {B: 'abcd'}}, - {a: {S: 'a'}}, - {a: {N: '1'}, b: {S: 'a'}, c: {S: 'b'}}, - {a: {N: '1'}, b: {N: '1'}, z: {N: '1'}}, - {a: {N: '1'}, z: {S: 'a'}}, - {a: {B: 'YQ=='}, b: {S: 'a'}}, - {a: {S: 'a'}}, - {a: {S: 'a'}, c: {N: '1'}}, - {a: {S: 'a'}, z: {S: '1'}}, - {a: {S: 'a'}, b: {S: '1'}, c: {S: '1'}}, - {a: {S: 'a'}, b: {N: '1'}}, - {a: {S: 'a'}, b: {B: 'YQ=='}}, - ], function(expr, cb) { + { z: { N: '1' } }, + { b: { S: 'a' }, c: { S: 'b' } }, + { a: { B: 'abcd' } }, + { a: { S: 'a' } }, + { a: { N: '1' }, b: { S: 'a' }, c: { S: 'b' } }, + { a: { N: '1' }, b: { N: '1' }, z: { N: '1' } }, + { a: { N: '1' }, z: { S: 'a' } }, + { a: { B: 'YQ==' }, b: { S: 'a' } }, + { a: { S: 'a' } }, + { a: { S: 'a' }, c: { N: '1' } }, + { a: { S: 'a' }, z: { S: '1' } }, + { a: { S: 'a' }, b: { S: '1' }, c: { S: '1' } }, + { a: { S: 'a' }, b: { N: '1' } }, + { a: { S: 'a' }, b: { B: 'YQ==' } }, + ], function (expr, cb) { assertValidation({ TableName: helpers.testRangeTable, ExclusiveStartKey: expr, @@ -1076,11 +1076,11 @@ describe('scan', function() { }, done) }) - it('should return ValidationException if range in ExclusiveStartKey is invalid, but hash and local are ok', function(done) { + it('should return ValidationException if range in ExclusiveStartKey is invalid, but hash and local are ok', function (done) { async.forEach([ - {a: {S: '1'}, b: {N: '1'}, c: {S: 'a'}}, - {a: {S: '1'}, b: {B: 'YQ=='}, c: {S: 'a'}}, - ], function(expr, cb) { + { a: { S: '1' }, b: { N: '1' }, c: { S: 'a' } }, + { a: { S: '1' }, b: { B: 'YQ==' }, c: { S: 'a' } }, + ], function (expr, cb) { assertValidation({ TableName: helpers.testRangeTable, IndexName: 'index1', @@ -1089,12 +1089,12 @@ describe('scan', function() { }, done) }) - it('should return ValidationException if global hash in ExclusiveStartKey but bad in query', function(done) { + it('should return ValidationException if global hash in ExclusiveStartKey but bad in query', function (done) { async.forEach([ - {x: {N: '1'}, y: {N: '1'}, c: {S: 'a'}}, - {a: {N: '1'}, b: {S: '1'}, c: {S: 'a'}}, - {a: {S: '1'}, b: {N: '1'}, c: {S: 'a'}}, - ], function(expr, cb) { + { x: { N: '1' }, y: { N: '1' }, c: { S: 'a' } }, + { a: { N: '1' }, b: { S: '1' }, c: { S: 'a' } }, + { a: { S: '1' }, b: { N: '1' }, c: { S: 'a' } }, + ], function (expr, cb) { assertValidation({ TableName: helpers.testRangeTable, IndexName: 'index3', @@ -1103,12 +1103,12 @@ describe('scan', function() { }, done) }) - it('should return ValidationException if global range in ExclusiveStartKey but bad in query', function(done) { + it('should return ValidationException if global range in ExclusiveStartKey but bad in query', function (done) { async.forEach([ - {x: {N: '1'}, y: {N: '1'}, c: {S: 'a'}, d: {S: 'a'}}, - {a: {N: '1'}, b: {S: '1'}, c: {S: 'a'}, d: {S: 'a'}}, - {a: {S: '1'}, b: {N: '1'}, c: {S: 'a'}, d: {S: 'a'}}, - ], function(expr, cb) { + { x: { N: '1' }, y: { N: '1' }, c: { S: 'a' }, d: { S: 'a' } }, + { a: { N: '1' }, b: { S: '1' }, c: { S: 'a' }, d: { S: 'a' } }, + { a: { S: '1' }, b: { N: '1' }, c: { S: 'a' }, d: { S: 'a' } }, + ], function (expr, cb) { assertValidation({ TableName: helpers.testRangeTable, IndexName: 'index4', @@ -1117,60 +1117,60 @@ describe('scan', function() { }, done) }) - it('should return ValidationException if ExclusiveStartKey is from different segment', function(done) { - var i, items = [], batchReq = {RequestItems: {}} + it('should return ValidationException if ExclusiveStartKey is from different segment', function (done) { + var i, items = [], batchReq = { RequestItems: {} } for (i = 0; i < 10; i++) - items.push({a: {S: String(i)}}) + items.push({ a: { S: String(i) } }) - batchReq.RequestItems[helpers.testHashTable] = items.map(function(item) { return {PutRequest: {Item: item}} }) + batchReq.RequestItems[helpers.testHashTable] = items.map(function (item) { return { PutRequest: { Item: item } } }) - request(helpers.opts('BatchWriteItem', batchReq), function(err, res) { + request(helpers.opts('BatchWriteItem', batchReq), function (err, res) { if (err) return done(err) res.statusCode.should.equal(200) - request(opts({TableName: helpers.testHashTable, Segment: 1, TotalSegments: 2}), function(err, res) { + request(opts({ TableName: helpers.testHashTable, Segment: 1, TotalSegments: 2 }), function (err, res) { if (err) return done(err) res.statusCode.should.equal(200) res.body.Count.should.be.above(0) - assertValidation({TableName: helpers.testHashTable, + assertValidation({ TableName: helpers.testHashTable, Segment: 0, TotalSegments: 2, FilterExpression: 'attribute_exists(a.b.c)', - ExclusiveStartKey: {a: res.body.Items[0].a}}, - 'The provided starting key is invalid: ' + + ExclusiveStartKey: { a: res.body.Items[0].a } }, + 'The provided starting key is invalid: ' + 'Invalid ExclusiveStartKey. Please use ExclusiveStartKey with correct Segment. ' + 'TotalSegments: 2 Segment: 0', done) }) }) }) - it('should return ValidationException for non-scalar key access', function(done) { + it('should return ValidationException for non-scalar key access', function (done) { var expressions = [ 'attribute_exists(a.b.c) and #a = b', 'attribute_exists(#a.b.c)', 'attribute_exists(#a[0])', ] - async.forEach(expressions, function(expression, cb) { + async.forEach(expressions, function (expression, cb) { assertValidation({ TableName: helpers.testHashTable, FilterExpression: expression, - ExpressionAttributeNames: {'#a': 'a'}, + ExpressionAttributeNames: { '#a': 'a' }, }, 'Key attributes must be scalars; list random access \'[]\' and map lookup \'.\' are not allowed: Key: a', cb) }, done) }) }) - describe('functionality', function() { + describe('functionality', function () { - it('should scan with no filter', function(done) { - var item = {a: {S: helpers.randomString()}} - request(helpers.opts('PutItem', {TableName: helpers.testHashTable, Item: item}), function(err, res) { + it('should scan with no filter', function (done) { + var item = { a: { S: helpers.randomString() } } + request(helpers.opts('PutItem', { TableName: helpers.testHashTable, Item: item }), function (err, res) { if (err) return done(err) res.statusCode.should.equal(200) - request(opts({TableName: helpers.testHashTable}), function(err, res) { + request(opts({ TableName: helpers.testHashTable }), function (err, res) { if (err) return done(err) res.statusCode.should.equal(200) res.body.Items.should.containEql(item) @@ -1181,21 +1181,21 @@ describe('scan', function() { }) }) - it('should scan by id (type S)', function(done) { - var item = {a: {S: helpers.randomString()}} - request(helpers.opts('PutItem', {TableName: helpers.testHashTable, Item: item}), function(err, res) { + it('should scan by id (type S)', function (done) { + var item = { a: { S: helpers.randomString() } } + request(helpers.opts('PutItem', { TableName: helpers.testHashTable, Item: item }), function (err, res) { if (err) return done(err) res.statusCode.should.equal(200) async.forEach([ - {ScanFilter: {a: {ComparisonOperator: 'EQ', AttributeValueList: [item.a]}}}, - {FilterExpression: 'a = :a', ExpressionAttributeValues: {':a': item.a}}, - {FilterExpression: '#a = :a', ExpressionAttributeValues: {':a': item.a}, ExpressionAttributeNames: {'#a': 'a'}}, - ], function(scanOpts, cb) { + { ScanFilter: { a: { ComparisonOperator: 'EQ', AttributeValueList: [ item.a ] } } }, + { FilterExpression: 'a = :a', ExpressionAttributeValues: { ':a': item.a } }, + { FilterExpression: '#a = :a', ExpressionAttributeValues: { ':a': item.a }, ExpressionAttributeNames: { '#a': 'a' } }, + ], function (scanOpts, cb) { scanOpts.TableName = helpers.testHashTable - request(opts(scanOpts), function(err, res) { + request(opts(scanOpts), function (err, res) { if (err) return cb(err) res.statusCode.should.equal(200) - res.body.Items.should.eql([item]) + res.body.Items.should.eql([ item ]) res.body.Count.should.equal(1) res.body.ScannedCount.should.be.above(0) cb() @@ -1204,17 +1204,17 @@ describe('scan', function() { }) }) - it('should return empty if no match', function(done) { - var item = {a: {S: helpers.randomString()}} - request(helpers.opts('PutItem', {TableName: helpers.testHashTable, Item: item}), function(err, res) { + it('should return empty if no match', function (done) { + var item = { a: { S: helpers.randomString() } } + request(helpers.opts('PutItem', { TableName: helpers.testHashTable, Item: item }), function (err, res) { if (err) return done(err) res.statusCode.should.equal(200) async.forEach([ - {ScanFilter: {a: {ComparisonOperator: 'EQ', AttributeValueList: [{S: helpers.randomString()}]}}}, - {FilterExpression: 'a = :a', ExpressionAttributeValues: {':a': {S: helpers.randomString()}}}, - ], function(scanOpts, cb) { + { ScanFilter: { a: { ComparisonOperator: 'EQ', AttributeValueList: [ { S: helpers.randomString() } ] } } }, + { FilterExpression: 'a = :a', ExpressionAttributeValues: { ':a': { S: helpers.randomString() } } }, + ], function (scanOpts, cb) { scanOpts.TableName = helpers.testHashTable - request(opts(scanOpts), function(err, res) { + request(opts(scanOpts), function (err, res) { if (err) return cb(err) res.statusCode.should.equal(200) res.body.Items.should.eql([]) @@ -1226,25 +1226,25 @@ describe('scan', function() { }) }) - it('should scan by a non-id property (type N)', function(done) { - var item = {a: {S: helpers.randomString()}, b: {N: helpers.randomNumber()}}, - item2 = {a: {S: helpers.randomString()}, b: item.b}, - item3 = {a: {S: helpers.randomString()}, b: {N: helpers.randomNumber()}}, - batchReq = {RequestItems: {}} + it('should scan by a non-id property (type N)', function (done) { + var item = { a: { S: helpers.randomString() }, b: { N: helpers.randomNumber() } }, + item2 = { a: { S: helpers.randomString() }, b: item.b }, + item3 = { a: { S: helpers.randomString() }, b: { N: helpers.randomNumber() } }, + batchReq = { RequestItems: {} } batchReq.RequestItems[helpers.testHashTable] = [ - {PutRequest: {Item: item}}, - {PutRequest: {Item: item2}}, - {PutRequest: {Item: item3}}, + { PutRequest: { Item: item } }, + { PutRequest: { Item: item2 } }, + { PutRequest: { Item: item3 } }, ] - request(helpers.opts('BatchWriteItem', batchReq), function(err, res) { + request(helpers.opts('BatchWriteItem', batchReq), function (err, res) { if (err) return done(err) res.statusCode.should.equal(200) async.forEach([ - {ScanFilter: {b: {ComparisonOperator: 'EQ', AttributeValueList: [item.b]}}}, - {FilterExpression: 'b = :b', ExpressionAttributeValues: {':b': item.b}}, - ], function(scanOpts, cb) { + { ScanFilter: { b: { ComparisonOperator: 'EQ', AttributeValueList: [ item.b ] } } }, + { FilterExpression: 'b = :b', ExpressionAttributeValues: { ':b': item.b } }, + ], function (scanOpts, cb) { scanOpts.TableName = helpers.testHashTable - request(opts(scanOpts), function(err, res) { + request(opts(scanOpts), function (err, res) { if (err) return cb(err) res.statusCode.should.equal(200) res.body.Items.should.containEql(item) @@ -1257,31 +1257,31 @@ describe('scan', function() { }) }) - it('should scan by multiple properties', function(done) { - var item = {a: {S: helpers.randomString()}, date: {N: helpers.randomNumber()}, c: {N: helpers.randomNumber()}}, - item2 = {a: {S: helpers.randomString()}, date: item.date, c: item.c}, - item3 = {a: {S: helpers.randomString()}, date: item.date, c: {N: helpers.randomNumber()}}, - batchReq = {RequestItems: {}} + it('should scan by multiple properties', function (done) { + var item = { a: { S: helpers.randomString() }, date: { N: helpers.randomNumber() }, c: { N: helpers.randomNumber() } }, + item2 = { a: { S: helpers.randomString() }, date: item.date, c: item.c }, + item3 = { a: { S: helpers.randomString() }, date: item.date, c: { N: helpers.randomNumber() } }, + batchReq = { RequestItems: {} } batchReq.RequestItems[helpers.testHashTable] = [ - {PutRequest: {Item: item}}, - {PutRequest: {Item: item2}}, - {PutRequest: {Item: item3}}, + { PutRequest: { Item: item } }, + { PutRequest: { Item: item2 } }, + { PutRequest: { Item: item3 } }, ] - request(helpers.opts('BatchWriteItem', batchReq), function(err, res) { + request(helpers.opts('BatchWriteItem', batchReq), function (err, res) { if (err) return done(err) res.statusCode.should.equal(200) - async.forEach([{ + async.forEach([ { ScanFilter: { - date: {ComparisonOperator: 'EQ', AttributeValueList: [item.date]}, - c: {ComparisonOperator: 'EQ', AttributeValueList: [item.c]}, + date: { ComparisonOperator: 'EQ', AttributeValueList: [ item.date ] }, + c: { ComparisonOperator: 'EQ', AttributeValueList: [ item.c ] }, }, }, { FilterExpression: '#d = :date AND c = :c', - ExpressionAttributeValues: {':date': item.date, ':c': item.c}, - ExpressionAttributeNames: {'#d': 'date'}, - }], function(scanOpts, cb) { + ExpressionAttributeValues: { ':date': item.date, ':c': item.c }, + ExpressionAttributeNames: { '#d': 'date' }, + } ], function (scanOpts, cb) { scanOpts.TableName = helpers.testHashTable - request(opts(scanOpts), function(err, res) { + request(opts(scanOpts), function (err, res) { if (err) return cb(err) res.statusCode.should.equal(200, res.rawBody) res.body.Items.should.containEql(item) @@ -1294,30 +1294,30 @@ describe('scan', function() { }) }) - it('should scan by EQ on type B', function(done) { - var item = {a: {S: helpers.randomString()}, b: {B: 'abcd'}, c: {S: helpers.randomString()}}, - item2 = {a: {S: helpers.randomString()}, b: {B: 'abcd'}, c: item.c}, - item3 = {a: {S: helpers.randomString()}, b: {B: 'Yg=='}, c: item.c}, - batchReq = {RequestItems: {}} + it('should scan by EQ on type B', function (done) { + var item = { a: { S: helpers.randomString() }, b: { B: 'abcd' }, c: { S: helpers.randomString() } }, + item2 = { a: { S: helpers.randomString() }, b: { B: 'abcd' }, c: item.c }, + item3 = { a: { S: helpers.randomString() }, b: { B: 'Yg==' }, c: item.c }, + batchReq = { RequestItems: {} } batchReq.RequestItems[helpers.testHashTable] = [ - {PutRequest: {Item: item}}, - {PutRequest: {Item: item2}}, - {PutRequest: {Item: item3}}, + { PutRequest: { Item: item } }, + { PutRequest: { Item: item2 } }, + { PutRequest: { Item: item3 } }, ] - request(helpers.opts('BatchWriteItem', batchReq), function(err, res) { + request(helpers.opts('BatchWriteItem', batchReq), function (err, res) { if (err) return done(err) res.statusCode.should.equal(200) - async.forEach([{ + async.forEach([ { ScanFilter: { - b: {ComparisonOperator: 'EQ', AttributeValueList: [item.b]}, - c: {ComparisonOperator: 'EQ', AttributeValueList: [item.c]}, + b: { ComparisonOperator: 'EQ', AttributeValueList: [ item.b ] }, + c: { ComparisonOperator: 'EQ', AttributeValueList: [ item.c ] }, }, }, { FilterExpression: 'b = :b AND c = :c', - ExpressionAttributeValues: {':b': item.b, ':c': item.c}, - }], function(scanOpts, cb) { + ExpressionAttributeValues: { ':b': item.b, ':c': item.c }, + } ], function (scanOpts, cb) { scanOpts.TableName = helpers.testHashTable - request(opts(scanOpts), function(err, res) { + request(opts(scanOpts), function (err, res) { if (err) return cb(err) res.statusCode.should.equal(200) res.body.Items.should.containEql(item) @@ -1330,30 +1330,30 @@ describe('scan', function() { }) }) - it('should scan by EQ on type SS', function(done) { - var item = {a: {S: helpers.randomString()}, b: {SS: ['a', 'b']}, c: {S: helpers.randomString()}}, - item2 = {a: {S: helpers.randomString()}, b: {SS: ['a', 'b']}, c: item.c}, - item3 = {a: {S: helpers.randomString()}, b: {SS: ['a', 'b', 'c']}, c: item.c}, - batchReq = {RequestItems: {}} + it('should scan by EQ on type SS', function (done) { + var item = { a: { S: helpers.randomString() }, b: { SS: [ 'a', 'b' ] }, c: { S: helpers.randomString() } }, + item2 = { a: { S: helpers.randomString() }, b: { SS: [ 'a', 'b' ] }, c: item.c }, + item3 = { a: { S: helpers.randomString() }, b: { SS: [ 'a', 'b', 'c' ] }, c: item.c }, + batchReq = { RequestItems: {} } batchReq.RequestItems[helpers.testHashTable] = [ - {PutRequest: {Item: item}}, - {PutRequest: {Item: item2}}, - {PutRequest: {Item: item3}}, + { PutRequest: { Item: item } }, + { PutRequest: { Item: item2 } }, + { PutRequest: { Item: item3 } }, ] - request(helpers.opts('BatchWriteItem', batchReq), function(err, res) { + request(helpers.opts('BatchWriteItem', batchReq), function (err, res) { if (err) return done(err) res.statusCode.should.equal(200) - async.forEach([{ + async.forEach([ { ScanFilter: { - b: {ComparisonOperator: 'EQ', AttributeValueList: [{SS: ['b', 'a']}]}, - c: {ComparisonOperator: 'EQ', AttributeValueList: [item.c]}, + b: { ComparisonOperator: 'EQ', AttributeValueList: [ { SS: [ 'b', 'a' ] } ] }, + c: { ComparisonOperator: 'EQ', AttributeValueList: [ item.c ] }, }, }, { FilterExpression: 'b = :b AND c = :c', - ExpressionAttributeValues: {':b': {SS: ['b', 'a']}, ':c': item.c}, - }], function(scanOpts, cb) { + ExpressionAttributeValues: { ':b': { SS: [ 'b', 'a' ] }, ':c': item.c }, + } ], function (scanOpts, cb) { scanOpts.TableName = helpers.testHashTable - request(opts(scanOpts), function(err, res) { + request(opts(scanOpts), function (err, res) { if (err) return cb(err) res.statusCode.should.equal(200) res.body.Items.should.containEql(item) @@ -1366,33 +1366,33 @@ describe('scan', function() { }) }) - it('should scan by EQ on type NS', function(done) { - var item = {a: {S: helpers.randomString()}, b: {NS: ['1', '2']}, c: {S: helpers.randomString()}}, - item2 = {a: {S: helpers.randomString()}, b: {NS: ['1', '2']}, c: item.c}, - item3 = {a: {S: helpers.randomString()}, b: {NS: ['1', '2', '3']}, c: item.c}, - batchReq = {RequestItems: {}} + it('should scan by EQ on type NS', function (done) { + var item = { a: { S: helpers.randomString() }, b: { NS: [ '1', '2' ] }, c: { S: helpers.randomString() } }, + item2 = { a: { S: helpers.randomString() }, b: { NS: [ '1', '2' ] }, c: item.c }, + item3 = { a: { S: helpers.randomString() }, b: { NS: [ '1', '2', '3' ] }, c: item.c }, + batchReq = { RequestItems: {} } batchReq.RequestItems[helpers.testHashTable] = [ - {PutRequest: {Item: item}}, - {PutRequest: {Item: item2}}, - {PutRequest: {Item: item3}}, + { PutRequest: { Item: item } }, + { PutRequest: { Item: item2 } }, + { PutRequest: { Item: item3 } }, ] - request(helpers.opts('BatchWriteItem', batchReq), function(err, res) { + request(helpers.opts('BatchWriteItem', batchReq), function (err, res) { if (err) return done(err) res.statusCode.should.equal(200) - async.forEach([{ + async.forEach([ { ScanFilter: { - b: {ComparisonOperator: 'EQ', AttributeValueList: [{NS: ['2', '1']}]}, - c: {ComparisonOperator: 'EQ', AttributeValueList: [item.c]}, + b: { ComparisonOperator: 'EQ', AttributeValueList: [ { NS: [ '2', '1' ] } ] }, + c: { ComparisonOperator: 'EQ', AttributeValueList: [ item.c ] }, }, }, { FilterExpression: 'b = :b AND c = :c', - ExpressionAttributeValues: {':b': {NS: ['2', '1']}, ':c': item.c}, - }], function(scanOpts, cb) { + ExpressionAttributeValues: { ':b': { NS: [ '2', '1' ] }, ':c': item.c }, + } ], function (scanOpts, cb) { scanOpts.TableName = helpers.testHashTable - request(opts(scanOpts), function(err, res) { + request(opts(scanOpts), function (err, res) { if (err) return cb(err) res.statusCode.should.equal(200) - res.body.Items.forEach(function(item) { + res.body.Items.forEach(function (item) { item.b.NS.should.have.length(2) item.b.NS.should.containEql('1') item.b.NS.should.containEql('2') @@ -1410,30 +1410,30 @@ describe('scan', function() { }) }) - it('should scan by EQ on type BS', function(done) { - var item = {a: {S: helpers.randomString()}, b: {BS: ['Yg==', 'abcd']}, c: {S: helpers.randomString()}}, - item2 = {a: {S: helpers.randomString()}, b: {BS: ['Yg==', 'abcd']}, c: item.c}, - item3 = {a: {S: helpers.randomString()}, b: {BS: ['Yg==', 'abcd', '1234']}, c: item.c}, - batchReq = {RequestItems: {}} + it('should scan by EQ on type BS', function (done) { + var item = { a: { S: helpers.randomString() }, b: { BS: [ 'Yg==', 'abcd' ] }, c: { S: helpers.randomString() } }, + item2 = { a: { S: helpers.randomString() }, b: { BS: [ 'Yg==', 'abcd' ] }, c: item.c }, + item3 = { a: { S: helpers.randomString() }, b: { BS: [ 'Yg==', 'abcd', '1234' ] }, c: item.c }, + batchReq = { RequestItems: {} } batchReq.RequestItems[helpers.testHashTable] = [ - {PutRequest: {Item: item}}, - {PutRequest: {Item: item2}}, - {PutRequest: {Item: item3}}, + { PutRequest: { Item: item } }, + { PutRequest: { Item: item2 } }, + { PutRequest: { Item: item3 } }, ] - request(helpers.opts('BatchWriteItem', batchReq), function(err, res) { + request(helpers.opts('BatchWriteItem', batchReq), function (err, res) { if (err) return done(err) res.statusCode.should.equal(200) - async.forEach([{ + async.forEach([ { ScanFilter: { - b: {ComparisonOperator: 'EQ', AttributeValueList: [{BS: ['abcd', 'Yg==']}]}, - c: {ComparisonOperator: 'EQ', AttributeValueList: [item.c]}, + b: { ComparisonOperator: 'EQ', AttributeValueList: [ { BS: [ 'abcd', 'Yg==' ] } ] }, + c: { ComparisonOperator: 'EQ', AttributeValueList: [ item.c ] }, }, }, { FilterExpression: 'b = :b AND c = :c', - ExpressionAttributeValues: {':b': {BS: ['abcd', 'Yg==']}, ':c': item.c}, - }], function(scanOpts, cb) { + ExpressionAttributeValues: { ':b': { BS: [ 'abcd', 'Yg==' ] }, ':c': item.c }, + } ], function (scanOpts, cb) { scanOpts.TableName = helpers.testHashTable - request(opts(scanOpts), function(err, res) { + request(opts(scanOpts), function (err, res) { if (err) return cb(err) res.statusCode.should.equal(200) res.body.Items.should.containEql(item) @@ -1446,33 +1446,33 @@ describe('scan', function() { }) }) - it('should scan by EQ on different types', function(done) { - var item = {a: {S: helpers.randomString()}, b: {S: '1234'}, c: {S: helpers.randomString()}}, - item2 = {a: {S: helpers.randomString()}, b: {N: '1234'}, c: item.c}, - item3 = {a: {S: helpers.randomString()}, b: {B: '1234'}, c: item.c}, - batchReq = {RequestItems: {}} + it('should scan by EQ on different types', function (done) { + var item = { a: { S: helpers.randomString() }, b: { S: '1234' }, c: { S: helpers.randomString() } }, + item2 = { a: { S: helpers.randomString() }, b: { N: '1234' }, c: item.c }, + item3 = { a: { S: helpers.randomString() }, b: { B: '1234' }, c: item.c }, + batchReq = { RequestItems: {} } batchReq.RequestItems[helpers.testHashTable] = [ - {PutRequest: {Item: item}}, - {PutRequest: {Item: item2}}, - {PutRequest: {Item: item3}}, + { PutRequest: { Item: item } }, + { PutRequest: { Item: item2 } }, + { PutRequest: { Item: item3 } }, ] - request(helpers.opts('BatchWriteItem', batchReq), function(err, res) { + request(helpers.opts('BatchWriteItem', batchReq), function (err, res) { if (err) return done(err) res.statusCode.should.equal(200) - async.forEach([{ + async.forEach([ { ScanFilter: { - b: {ComparisonOperator: 'EQ', AttributeValueList: [item.b]}, - c: {ComparisonOperator: 'EQ', AttributeValueList: [item.c]}, + b: { ComparisonOperator: 'EQ', AttributeValueList: [ item.b ] }, + c: { ComparisonOperator: 'EQ', AttributeValueList: [ item.c ] }, }, }, { FilterExpression: 'b = :b AND c = :c', - ExpressionAttributeValues: {':b': item.b, ':c': item.c}, - }], function(scanOpts, cb) { + ExpressionAttributeValues: { ':b': item.b, ':c': item.c }, + } ], function (scanOpts, cb) { scanOpts.TableName = helpers.testHashTable - request(opts(scanOpts), function(err, res) { + request(opts(scanOpts), function (err, res) { if (err) return cb(err) res.statusCode.should.equal(200) - res.body.Items.should.eql([item]) + res.body.Items.should.eql([ item ]) res.body.Count.should.equal(1) cb() }) @@ -1480,30 +1480,30 @@ describe('scan', function() { }) }) - it('should scan by NE on different types', function(done) { - var item = {a: {S: helpers.randomString()}, b: {S: '1234'}, c: {S: helpers.randomString()}}, - item2 = {a: {S: helpers.randomString()}, b: {N: '1234'}, c: item.c}, - item3 = {a: {S: helpers.randomString()}, b: {B: '1234'}, c: item.c}, - batchReq = {RequestItems: {}} + it('should scan by NE on different types', function (done) { + var item = { a: { S: helpers.randomString() }, b: { S: '1234' }, c: { S: helpers.randomString() } }, + item2 = { a: { S: helpers.randomString() }, b: { N: '1234' }, c: item.c }, + item3 = { a: { S: helpers.randomString() }, b: { B: '1234' }, c: item.c }, + batchReq = { RequestItems: {} } batchReq.RequestItems[helpers.testHashTable] = [ - {PutRequest: {Item: item}}, - {PutRequest: {Item: item2}}, - {PutRequest: {Item: item3}}, + { PutRequest: { Item: item } }, + { PutRequest: { Item: item2 } }, + { PutRequest: { Item: item3 } }, ] - request(helpers.opts('BatchWriteItem', batchReq), function(err, res) { + request(helpers.opts('BatchWriteItem', batchReq), function (err, res) { if (err) return done(err) res.statusCode.should.equal(200) - async.forEach([{ + async.forEach([ { ScanFilter: { - b: {ComparisonOperator: 'NE', AttributeValueList: [item.b]}, - c: {ComparisonOperator: 'EQ', AttributeValueList: [item.c]}, + b: { ComparisonOperator: 'NE', AttributeValueList: [ item.b ] }, + c: { ComparisonOperator: 'EQ', AttributeValueList: [ item.c ] }, }, }, { FilterExpression: 'b <> :b AND c = :c', - ExpressionAttributeValues: {':b': item.b, ':c': item.c}, - }], function(scanOpts, cb) { + ExpressionAttributeValues: { ':b': item.b, ':c': item.c }, + } ], function (scanOpts, cb) { scanOpts.TableName = helpers.testHashTable - request(opts(scanOpts), function(err, res) { + request(opts(scanOpts), function (err, res) { if (err) return cb(err) res.statusCode.should.equal(200) res.body.Items.should.containEql(item2) @@ -1516,30 +1516,30 @@ describe('scan', function() { }) }) - it('should scan by NE on type SS', function(done) { - var item = {a: {S: helpers.randomString()}, b: {SS: ['a', 'b']}, c: {S: helpers.randomString()}}, - item2 = {a: {S: helpers.randomString()}, b: {SS: ['a', 'b']}, c: item.c}, - item3 = {a: {S: helpers.randomString()}, b: {SS: ['a', 'b', 'c']}, c: item.c}, - batchReq = {RequestItems: {}} + it('should scan by NE on type SS', function (done) { + var item = { a: { S: helpers.randomString() }, b: { SS: [ 'a', 'b' ] }, c: { S: helpers.randomString() } }, + item2 = { a: { S: helpers.randomString() }, b: { SS: [ 'a', 'b' ] }, c: item.c }, + item3 = { a: { S: helpers.randomString() }, b: { SS: [ 'a', 'b', 'c' ] }, c: item.c }, + batchReq = { RequestItems: {} } batchReq.RequestItems[helpers.testHashTable] = [ - {PutRequest: {Item: item}}, - {PutRequest: {Item: item2}}, - {PutRequest: {Item: item3}}, + { PutRequest: { Item: item } }, + { PutRequest: { Item: item2 } }, + { PutRequest: { Item: item3 } }, ] - request(helpers.opts('BatchWriteItem', batchReq), function(err, res) { + request(helpers.opts('BatchWriteItem', batchReq), function (err, res) { if (err) return done(err) res.statusCode.should.equal(200) - async.forEach([{ + async.forEach([ { ScanFilter: { - b: {ComparisonOperator: 'NE', AttributeValueList: [{SS: ['b', 'a']}]}, - c: {ComparisonOperator: 'EQ', AttributeValueList: [item.c]}, + b: { ComparisonOperator: 'NE', AttributeValueList: [ { SS: [ 'b', 'a' ] } ] }, + c: { ComparisonOperator: 'EQ', AttributeValueList: [ item.c ] }, }, }, { FilterExpression: 'b <> :b AND c = :c', - ExpressionAttributeValues: {':b': {SS: ['b', 'a']}, ':c': item.c}, - }], function(scanOpts, cb) { + ExpressionAttributeValues: { ':b': { SS: [ 'b', 'a' ] }, ':c': item.c }, + } ], function (scanOpts, cb) { scanOpts.TableName = helpers.testHashTable - request(opts(scanOpts), function(err, res) { + request(opts(scanOpts), function (err, res) { if (err) return cb(err) res.statusCode.should.equal(200) res.body.Items.should.containEql(item3) @@ -1551,30 +1551,30 @@ describe('scan', function() { }) }) - it('should scan by NE on type NS', function(done) { - var item = {a: {S: helpers.randomString()}, b: {NS: ['1', '2']}, c: {S: helpers.randomString()}}, - item2 = {a: {S: helpers.randomString()}, b: {NS: ['1', '2']}, c: item.c}, - item3 = {a: {S: helpers.randomString()}, b: {NS: ['3', '2', '1']}, c: item.c}, - batchReq = {RequestItems: {}} + it('should scan by NE on type NS', function (done) { + var item = { a: { S: helpers.randomString() }, b: { NS: [ '1', '2' ] }, c: { S: helpers.randomString() } }, + item2 = { a: { S: helpers.randomString() }, b: { NS: [ '1', '2' ] }, c: item.c }, + item3 = { a: { S: helpers.randomString() }, b: { NS: [ '3', '2', '1' ] }, c: item.c }, + batchReq = { RequestItems: {} } batchReq.RequestItems[helpers.testHashTable] = [ - {PutRequest: {Item: item}}, - {PutRequest: {Item: item2}}, - {PutRequest: {Item: item3}}, + { PutRequest: { Item: item } }, + { PutRequest: { Item: item2 } }, + { PutRequest: { Item: item3 } }, ] - request(helpers.opts('BatchWriteItem', batchReq), function(err, res) { + request(helpers.opts('BatchWriteItem', batchReq), function (err, res) { if (err) return done(err) res.statusCode.should.equal(200) - async.forEach([{ + async.forEach([ { ScanFilter: { - b: {ComparisonOperator: 'NE', AttributeValueList: [{NS: ['2', '1']}]}, - c: {ComparisonOperator: 'EQ', AttributeValueList: [item.c]}, + b: { ComparisonOperator: 'NE', AttributeValueList: [ { NS: [ '2', '1' ] } ] }, + c: { ComparisonOperator: 'EQ', AttributeValueList: [ item.c ] }, }, }, { FilterExpression: 'b <> :b AND c = :c', - ExpressionAttributeValues: {':b': {NS: ['2', '1']}, ':c': item.c}, - }], function(scanOpts, cb) { + ExpressionAttributeValues: { ':b': { NS: [ '2', '1' ] }, ':c': item.c }, + } ], function (scanOpts, cb) { scanOpts.TableName = helpers.testHashTable - request(opts(scanOpts), function(err, res) { + request(opts(scanOpts), function (err, res) { if (err) return cb(err) res.statusCode.should.equal(200) res.body.Items.should.containEql(item3) @@ -1586,30 +1586,30 @@ describe('scan', function() { }) }) - it('should scan by NE on type BS', function(done) { - var item = {a: {S: helpers.randomString()}, b: {BS: ['Yg==', 'abcd']}, c: {S: helpers.randomString()}}, - item2 = {a: {S: helpers.randomString()}, b: {BS: ['Yg==', 'abcd']}, c: item.c}, - item3 = {a: {S: helpers.randomString()}, b: {BS: ['Yg==', 'abcd', '1234']}, c: item.c}, - batchReq = {RequestItems: {}} + it('should scan by NE on type BS', function (done) { + var item = { a: { S: helpers.randomString() }, b: { BS: [ 'Yg==', 'abcd' ] }, c: { S: helpers.randomString() } }, + item2 = { a: { S: helpers.randomString() }, b: { BS: [ 'Yg==', 'abcd' ] }, c: item.c }, + item3 = { a: { S: helpers.randomString() }, b: { BS: [ 'Yg==', 'abcd', '1234' ] }, c: item.c }, + batchReq = { RequestItems: {} } batchReq.RequestItems[helpers.testHashTable] = [ - {PutRequest: {Item: item}}, - {PutRequest: {Item: item2}}, - {PutRequest: {Item: item3}}, + { PutRequest: { Item: item } }, + { PutRequest: { Item: item2 } }, + { PutRequest: { Item: item3 } }, ] - request(helpers.opts('BatchWriteItem', batchReq), function(err, res) { + request(helpers.opts('BatchWriteItem', batchReq), function (err, res) { if (err) return done(err) res.statusCode.should.equal(200) - async.forEach([{ + async.forEach([ { ScanFilter: { - b: {ComparisonOperator: 'NE', AttributeValueList: [{BS: ['abcd', 'Yg==']}]}, - c: {ComparisonOperator: 'EQ', AttributeValueList: [item.c]}, + b: { ComparisonOperator: 'NE', AttributeValueList: [ { BS: [ 'abcd', 'Yg==' ] } ] }, + c: { ComparisonOperator: 'EQ', AttributeValueList: [ item.c ] }, }, }, { FilterExpression: 'b <> :b AND c = :c', - ExpressionAttributeValues: {':b': {BS: ['abcd', 'Yg==']}, ':c': item.c}, - }], function(scanOpts, cb) { + ExpressionAttributeValues: { ':b': { BS: [ 'abcd', 'Yg==' ] }, ':c': item.c }, + } ], function (scanOpts, cb) { scanOpts.TableName = helpers.testHashTable - request(opts(scanOpts), function(err, res) { + request(opts(scanOpts), function (err, res) { if (err) return cb(err) res.statusCode.should.equal(200) res.body.Items.should.containEql(item3) @@ -1621,34 +1621,34 @@ describe('scan', function() { }) }) - it('should scan by LE on type S', function(done) { - var item = {a: {S: helpers.randomString()}, b: {S: 'abd'}, c: {S: helpers.randomString()}}, - item2 = {a: {S: helpers.randomString()}, b: {S: 'abc\xff'}, c: item.c}, - item3 = {a: {S: helpers.randomString()}, b: {S: 'abc'}, c: item.c}, - item4 = {a: {S: helpers.randomString()}, b: {S: 'abd\x00'}, c: item.c}, - item5 = {a: {S: helpers.randomString()}, b: {S: 'ab'}, c: item.c}, - batchReq = {RequestItems: {}} + it('should scan by LE on type S', function (done) { + var item = { a: { S: helpers.randomString() }, b: { S: 'abd' }, c: { S: helpers.randomString() } }, + item2 = { a: { S: helpers.randomString() }, b: { S: 'abc\xff' }, c: item.c }, + item3 = { a: { S: helpers.randomString() }, b: { S: 'abc' }, c: item.c }, + item4 = { a: { S: helpers.randomString() }, b: { S: 'abd\x00' }, c: item.c }, + item5 = { a: { S: helpers.randomString() }, b: { S: 'ab' }, c: item.c }, + batchReq = { RequestItems: {} } batchReq.RequestItems[helpers.testHashTable] = [ - {PutRequest: {Item: item}}, - {PutRequest: {Item: item2}}, - {PutRequest: {Item: item3}}, - {PutRequest: {Item: item4}}, - {PutRequest: {Item: item5}}, + { PutRequest: { Item: item } }, + { PutRequest: { Item: item2 } }, + { PutRequest: { Item: item3 } }, + { PutRequest: { Item: item4 } }, + { PutRequest: { Item: item5 } }, ] - request(helpers.opts('BatchWriteItem', batchReq), function(err, res) { + request(helpers.opts('BatchWriteItem', batchReq), function (err, res) { if (err) return done(err) res.statusCode.should.equal(200) - async.forEach([{ + async.forEach([ { ScanFilter: { - b: {ComparisonOperator: 'LE', AttributeValueList: [item.b]}, - c: {ComparisonOperator: 'EQ', AttributeValueList: [item.c]}, + b: { ComparisonOperator: 'LE', AttributeValueList: [ item.b ] }, + c: { ComparisonOperator: 'EQ', AttributeValueList: [ item.c ] }, }, }, { FilterExpression: 'b <= :b AND c = :c', - ExpressionAttributeValues: {':b': item.b, ':c': item.c}, - }], function(scanOpts, cb) { + ExpressionAttributeValues: { ':b': item.b, ':c': item.c }, + } ], function (scanOpts, cb) { scanOpts.TableName = helpers.testHashTable - request(opts(scanOpts), function(err, res) { + request(opts(scanOpts), function (err, res) { if (err) return cb(err) res.statusCode.should.equal(200) res.body.Items.should.containEql(item) @@ -1663,34 +1663,34 @@ describe('scan', function() { }) }) - it('should scan by LE on type N with decimals', function(done) { - var item = {a: {S: helpers.randomString()}, b: {N: '2'}, c: {S: helpers.randomString()}}, - item2 = {a: {S: helpers.randomString()}, b: {N: '1.9999'}, c: item.c}, - item3 = {a: {S: helpers.randomString()}, b: {N: '1'}, c: item.c}, - item4 = {a: {S: helpers.randomString()}, b: {N: '2.00000001'}, c: item.c}, - item5 = {a: {S: helpers.randomString()}, b: {N: '-0.5'}, c: item.c}, - batchReq = {RequestItems: {}} + it('should scan by LE on type N with decimals', function (done) { + var item = { a: { S: helpers.randomString() }, b: { N: '2' }, c: { S: helpers.randomString() } }, + item2 = { a: { S: helpers.randomString() }, b: { N: '1.9999' }, c: item.c }, + item3 = { a: { S: helpers.randomString() }, b: { N: '1' }, c: item.c }, + item4 = { a: { S: helpers.randomString() }, b: { N: '2.00000001' }, c: item.c }, + item5 = { a: { S: helpers.randomString() }, b: { N: '-0.5' }, c: item.c }, + batchReq = { RequestItems: {} } batchReq.RequestItems[helpers.testHashTable] = [ - {PutRequest: {Item: item}}, - {PutRequest: {Item: item2}}, - {PutRequest: {Item: item3}}, - {PutRequest: {Item: item4}}, - {PutRequest: {Item: item5}}, + { PutRequest: { Item: item } }, + { PutRequest: { Item: item2 } }, + { PutRequest: { Item: item3 } }, + { PutRequest: { Item: item4 } }, + { PutRequest: { Item: item5 } }, ] - request(helpers.opts('BatchWriteItem', batchReq), function(err, res) { + request(helpers.opts('BatchWriteItem', batchReq), function (err, res) { if (err) return done(err) res.statusCode.should.equal(200) - async.forEach([{ + async.forEach([ { ScanFilter: { - b: {ComparisonOperator: 'LE', AttributeValueList: [item.b]}, - c: {ComparisonOperator: 'EQ', AttributeValueList: [item.c]}, + b: { ComparisonOperator: 'LE', AttributeValueList: [ item.b ] }, + c: { ComparisonOperator: 'EQ', AttributeValueList: [ item.c ] }, }, }, { FilterExpression: 'b <= :b AND c = :c', - ExpressionAttributeValues: {':b': item.b, ':c': item.c}, - }], function(scanOpts, cb) { + ExpressionAttributeValues: { ':b': item.b, ':c': item.c }, + } ], function (scanOpts, cb) { scanOpts.TableName = helpers.testHashTable - request(opts(scanOpts), function(err, res) { + request(opts(scanOpts), function (err, res) { if (err) return cb(err) res.statusCode.should.equal(200) res.body.Items.should.containEql(item) @@ -1705,34 +1705,34 @@ describe('scan', function() { }) }) - it('should scan by LE on type N without decimals', function(done) { - var item = {a: {S: helpers.randomString()}, b: {N: '2'}, c: {S: helpers.randomString()}}, - item2 = {a: {S: helpers.randomString()}, b: {N: '19999'}, c: item.c}, - item3 = {a: {S: helpers.randomString()}, b: {N: '1'}, c: item.c}, - item4 = {a: {S: helpers.randomString()}, b: {N: '200000001'}, c: item.c}, - item5 = {a: {S: helpers.randomString()}, b: {N: '-5'}, c: item.c}, - batchReq = {RequestItems: {}} + it('should scan by LE on type N without decimals', function (done) { + var item = { a: { S: helpers.randomString() }, b: { N: '2' }, c: { S: helpers.randomString() } }, + item2 = { a: { S: helpers.randomString() }, b: { N: '19999' }, c: item.c }, + item3 = { a: { S: helpers.randomString() }, b: { N: '1' }, c: item.c }, + item4 = { a: { S: helpers.randomString() }, b: { N: '200000001' }, c: item.c }, + item5 = { a: { S: helpers.randomString() }, b: { N: '-5' }, c: item.c }, + batchReq = { RequestItems: {} } batchReq.RequestItems[helpers.testHashTable] = [ - {PutRequest: {Item: item}}, - {PutRequest: {Item: item2}}, - {PutRequest: {Item: item3}}, - {PutRequest: {Item: item4}}, - {PutRequest: {Item: item5}}, + { PutRequest: { Item: item } }, + { PutRequest: { Item: item2 } }, + { PutRequest: { Item: item3 } }, + { PutRequest: { Item: item4 } }, + { PutRequest: { Item: item5 } }, ] - request(helpers.opts('BatchWriteItem', batchReq), function(err, res) { + request(helpers.opts('BatchWriteItem', batchReq), function (err, res) { if (err) return done(err) res.statusCode.should.equal(200) - async.forEach([{ + async.forEach([ { ScanFilter: { - b: {ComparisonOperator: 'LE', AttributeValueList: [item.b]}, - c: {ComparisonOperator: 'EQ', AttributeValueList: [item.c]}, + b: { ComparisonOperator: 'LE', AttributeValueList: [ item.b ] }, + c: { ComparisonOperator: 'EQ', AttributeValueList: [ item.c ] }, }, }, { FilterExpression: 'b <= :b AND c = :c', - ExpressionAttributeValues: {':b': item.b, ':c': item.c}, - }], function(scanOpts, cb) { + ExpressionAttributeValues: { ':b': item.b, ':c': item.c }, + } ], function (scanOpts, cb) { scanOpts.TableName = helpers.testHashTable - request(opts(scanOpts), function(err, res) { + request(opts(scanOpts), function (err, res) { if (err) return cb(err) res.statusCode.should.equal(200) res.body.Items.should.containEql(item) @@ -1746,34 +1746,34 @@ describe('scan', function() { }) }) - it('should scan by LE on type B', function(done) { - var item = {a: {S: helpers.randomString()}, b: {B: Buffer.from('ce', 'hex').toString('base64')}, c: {S: helpers.randomString()}}, - item2 = {a: {S: helpers.randomString()}, b: {B: Buffer.from('d0', 'hex').toString('base64')}, c: item.c}, - item3 = {a: {S: helpers.randomString()}, b: {B: Buffer.from('cf', 'hex').toString('base64')}, c: item.c}, - item4 = {a: {S: helpers.randomString()}, b: {B: Buffer.from('d000', 'hex').toString('base64')}, c: item.c}, - item5 = {a: {S: helpers.randomString()}, b: {B: Buffer.from('cfff', 'hex').toString('base64')}, c: item.c}, - batchReq = {RequestItems: {}} + it('should scan by LE on type B', function (done) { + var item = { a: { S: helpers.randomString() }, b: { B: Buffer.from('ce', 'hex').toString('base64') }, c: { S: helpers.randomString() } }, + item2 = { a: { S: helpers.randomString() }, b: { B: Buffer.from('d0', 'hex').toString('base64') }, c: item.c }, + item3 = { a: { S: helpers.randomString() }, b: { B: Buffer.from('cf', 'hex').toString('base64') }, c: item.c }, + item4 = { a: { S: helpers.randomString() }, b: { B: Buffer.from('d000', 'hex').toString('base64') }, c: item.c }, + item5 = { a: { S: helpers.randomString() }, b: { B: Buffer.from('cfff', 'hex').toString('base64') }, c: item.c }, + batchReq = { RequestItems: {} } batchReq.RequestItems[helpers.testHashTable] = [ - {PutRequest: {Item: item}}, - {PutRequest: {Item: item2}}, - {PutRequest: {Item: item3}}, - {PutRequest: {Item: item4}}, - {PutRequest: {Item: item5}}, + { PutRequest: { Item: item } }, + { PutRequest: { Item: item2 } }, + { PutRequest: { Item: item3 } }, + { PutRequest: { Item: item4 } }, + { PutRequest: { Item: item5 } }, ] - request(helpers.opts('BatchWriteItem', batchReq), function(err, res) { + request(helpers.opts('BatchWriteItem', batchReq), function (err, res) { if (err) return done(err) res.statusCode.should.equal(200) - async.forEach([{ + async.forEach([ { ScanFilter: { - b: {ComparisonOperator: 'LE', AttributeValueList: [item2.b]}, - c: {ComparisonOperator: 'EQ', AttributeValueList: [item.c]}, + b: { ComparisonOperator: 'LE', AttributeValueList: [ item2.b ] }, + c: { ComparisonOperator: 'EQ', AttributeValueList: [ item.c ] }, }, }, { FilterExpression: 'b <= :b AND c = :c', - ExpressionAttributeValues: {':b': item2.b, ':c': item.c}, - }], function(scanOpts, cb) { + ExpressionAttributeValues: { ':b': item2.b, ':c': item.c }, + } ], function (scanOpts, cb) { scanOpts.TableName = helpers.testHashTable - request(opts(scanOpts), function(err, res) { + request(opts(scanOpts), function (err, res) { if (err) return cb(err) res.statusCode.should.equal(200) res.body.Items.should.containEql(item) @@ -1788,34 +1788,34 @@ describe('scan', function() { }) }) - it('should scan by LT on type S', function(done) { - var item = {a: {S: helpers.randomString()}, b: {S: 'abd'}, c: {S: helpers.randomString()}}, - item2 = {a: {S: helpers.randomString()}, b: {S: 'abc\xff'}, c: item.c}, - item3 = {a: {S: helpers.randomString()}, b: {S: 'abc'}, c: item.c}, - item4 = {a: {S: helpers.randomString()}, b: {S: 'abd\x00'}, c: item.c}, - item5 = {a: {S: helpers.randomString()}, b: {S: 'ab'}, c: item.c}, - batchReq = {RequestItems: {}} + it('should scan by LT on type S', function (done) { + var item = { a: { S: helpers.randomString() }, b: { S: 'abd' }, c: { S: helpers.randomString() } }, + item2 = { a: { S: helpers.randomString() }, b: { S: 'abc\xff' }, c: item.c }, + item3 = { a: { S: helpers.randomString() }, b: { S: 'abc' }, c: item.c }, + item4 = { a: { S: helpers.randomString() }, b: { S: 'abd\x00' }, c: item.c }, + item5 = { a: { S: helpers.randomString() }, b: { S: 'ab' }, c: item.c }, + batchReq = { RequestItems: {} } batchReq.RequestItems[helpers.testHashTable] = [ - {PutRequest: {Item: item}}, - {PutRequest: {Item: item2}}, - {PutRequest: {Item: item3}}, - {PutRequest: {Item: item4}}, - {PutRequest: {Item: item5}}, + { PutRequest: { Item: item } }, + { PutRequest: { Item: item2 } }, + { PutRequest: { Item: item3 } }, + { PutRequest: { Item: item4 } }, + { PutRequest: { Item: item5 } }, ] - request(helpers.opts('BatchWriteItem', batchReq), function(err, res) { + request(helpers.opts('BatchWriteItem', batchReq), function (err, res) { if (err) return done(err) res.statusCode.should.equal(200) - async.forEach([{ + async.forEach([ { ScanFilter: { - b: {ComparisonOperator: 'LT', AttributeValueList: [item.b]}, - c: {ComparisonOperator: 'EQ', AttributeValueList: [item.c]}, + b: { ComparisonOperator: 'LT', AttributeValueList: [ item.b ] }, + c: { ComparisonOperator: 'EQ', AttributeValueList: [ item.c ] }, }, }, { FilterExpression: 'b < :b AND c = :c', - ExpressionAttributeValues: {':b': item.b, ':c': item.c}, - }], function(scanOpts, cb) { + ExpressionAttributeValues: { ':b': item.b, ':c': item.c }, + } ], function (scanOpts, cb) { scanOpts.TableName = helpers.testHashTable - request(opts(scanOpts), function(err, res) { + request(opts(scanOpts), function (err, res) { if (err) return cb(err) res.statusCode.should.equal(200) res.body.Items.should.containEql(item2) @@ -1829,34 +1829,34 @@ describe('scan', function() { }) }) - it('should scan by LT on type N', function(done) { - var item = {a: {S: helpers.randomString()}, b: {N: '2'}, c: {S: helpers.randomString()}}, - item2 = {a: {S: helpers.randomString()}, b: {N: '1.9999'}, c: item.c}, - item3 = {a: {S: helpers.randomString()}, b: {N: '1'}, c: item.c}, - item4 = {a: {S: helpers.randomString()}, b: {N: '2.00000001'}, c: item.c}, - item5 = {a: {S: helpers.randomString()}, b: {N: '-0.5'}, c: item.c}, - batchReq = {RequestItems: {}} + it('should scan by LT on type N', function (done) { + var item = { a: { S: helpers.randomString() }, b: { N: '2' }, c: { S: helpers.randomString() } }, + item2 = { a: { S: helpers.randomString() }, b: { N: '1.9999' }, c: item.c }, + item3 = { a: { S: helpers.randomString() }, b: { N: '1' }, c: item.c }, + item4 = { a: { S: helpers.randomString() }, b: { N: '2.00000001' }, c: item.c }, + item5 = { a: { S: helpers.randomString() }, b: { N: '-0.5' }, c: item.c }, + batchReq = { RequestItems: {} } batchReq.RequestItems[helpers.testHashTable] = [ - {PutRequest: {Item: item}}, - {PutRequest: {Item: item2}}, - {PutRequest: {Item: item3}}, - {PutRequest: {Item: item4}}, - {PutRequest: {Item: item5}}, + { PutRequest: { Item: item } }, + { PutRequest: { Item: item2 } }, + { PutRequest: { Item: item3 } }, + { PutRequest: { Item: item4 } }, + { PutRequest: { Item: item5 } }, ] - request(helpers.opts('BatchWriteItem', batchReq), function(err, res) { + request(helpers.opts('BatchWriteItem', batchReq), function (err, res) { if (err) return done(err) res.statusCode.should.equal(200) - async.forEach([{ + async.forEach([ { ScanFilter: { - b: {ComparisonOperator: 'LT', AttributeValueList: [item.b]}, - c: {ComparisonOperator: 'EQ', AttributeValueList: [item.c]}, + b: { ComparisonOperator: 'LT', AttributeValueList: [ item.b ] }, + c: { ComparisonOperator: 'EQ', AttributeValueList: [ item.c ] }, }, }, { FilterExpression: 'b < :b AND c = :c', - ExpressionAttributeValues: {':b': item.b, ':c': item.c}, - }], function(scanOpts, cb) { + ExpressionAttributeValues: { ':b': item.b, ':c': item.c }, + } ], function (scanOpts, cb) { scanOpts.TableName = helpers.testHashTable - request(opts(scanOpts), function(err, res) { + request(opts(scanOpts), function (err, res) { if (err) return cb(err) res.statusCode.should.equal(200) res.body.Items.should.containEql(item2) @@ -1870,34 +1870,34 @@ describe('scan', function() { }) }) - it('should scan by LT on type B', function(done) { - var item = {a: {S: helpers.randomString()}, b: {B: Buffer.from('ce', 'hex').toString('base64')}, c: {S: helpers.randomString()}}, - item2 = {a: {S: helpers.randomString()}, b: {B: Buffer.from('d0', 'hex').toString('base64')}, c: item.c}, - item3 = {a: {S: helpers.randomString()}, b: {B: Buffer.from('cf', 'hex').toString('base64')}, c: item.c}, - item4 = {a: {S: helpers.randomString()}, b: {B: Buffer.from('d000', 'hex').toString('base64')}, c: item.c}, - item5 = {a: {S: helpers.randomString()}, b: {B: Buffer.from('cfff', 'hex').toString('base64')}, c: item.c}, - batchReq = {RequestItems: {}} + it('should scan by LT on type B', function (done) { + var item = { a: { S: helpers.randomString() }, b: { B: Buffer.from('ce', 'hex').toString('base64') }, c: { S: helpers.randomString() } }, + item2 = { a: { S: helpers.randomString() }, b: { B: Buffer.from('d0', 'hex').toString('base64') }, c: item.c }, + item3 = { a: { S: helpers.randomString() }, b: { B: Buffer.from('cf', 'hex').toString('base64') }, c: item.c }, + item4 = { a: { S: helpers.randomString() }, b: { B: Buffer.from('d000', 'hex').toString('base64') }, c: item.c }, + item5 = { a: { S: helpers.randomString() }, b: { B: Buffer.from('cfff', 'hex').toString('base64') }, c: item.c }, + batchReq = { RequestItems: {} } batchReq.RequestItems[helpers.testHashTable] = [ - {PutRequest: {Item: item}}, - {PutRequest: {Item: item2}}, - {PutRequest: {Item: item3}}, - {PutRequest: {Item: item4}}, - {PutRequest: {Item: item5}}, + { PutRequest: { Item: item } }, + { PutRequest: { Item: item2 } }, + { PutRequest: { Item: item3 } }, + { PutRequest: { Item: item4 } }, + { PutRequest: { Item: item5 } }, ] - request(helpers.opts('BatchWriteItem', batchReq), function(err, res) { + request(helpers.opts('BatchWriteItem', batchReq), function (err, res) { if (err) return done(err) res.statusCode.should.equal(200) - async.forEach([{ + async.forEach([ { ScanFilter: { - b: {ComparisonOperator: 'LT', AttributeValueList: [item2.b]}, - c: {ComparisonOperator: 'EQ', AttributeValueList: [item.c]}, + b: { ComparisonOperator: 'LT', AttributeValueList: [ item2.b ] }, + c: { ComparisonOperator: 'EQ', AttributeValueList: [ item.c ] }, }, }, { FilterExpression: 'b < :b AND c = :c', - ExpressionAttributeValues: {':b': item2.b, ':c': item.c}, - }], function(scanOpts, cb) { + ExpressionAttributeValues: { ':b': item2.b, ':c': item.c }, + } ], function (scanOpts, cb) { scanOpts.TableName = helpers.testHashTable - request(opts(scanOpts), function(err, res) { + request(opts(scanOpts), function (err, res) { if (err) return cb(err) res.statusCode.should.equal(200) res.body.Items.should.containEql(item) @@ -1911,34 +1911,34 @@ describe('scan', function() { }) }) - it('should scan by GE on type S', function(done) { - var item = {a: {S: helpers.randomString()}, b: {S: 'abd'}, c: {S: helpers.randomString()}}, - item2 = {a: {S: helpers.randomString()}, b: {S: 'abc\xff'}, c: item.c}, - item3 = {a: {S: helpers.randomString()}, b: {S: 'abc'}, c: item.c}, - item4 = {a: {S: helpers.randomString()}, b: {S: 'abd\x00'}, c: item.c}, - item5 = {a: {S: helpers.randomString()}, b: {S: 'ab'}, c: item.c}, - batchReq = {RequestItems: {}} + it('should scan by GE on type S', function (done) { + var item = { a: { S: helpers.randomString() }, b: { S: 'abd' }, c: { S: helpers.randomString() } }, + item2 = { a: { S: helpers.randomString() }, b: { S: 'abc\xff' }, c: item.c }, + item3 = { a: { S: helpers.randomString() }, b: { S: 'abc' }, c: item.c }, + item4 = { a: { S: helpers.randomString() }, b: { S: 'abd\x00' }, c: item.c }, + item5 = { a: { S: helpers.randomString() }, b: { S: 'ab' }, c: item.c }, + batchReq = { RequestItems: {} } batchReq.RequestItems[helpers.testHashTable] = [ - {PutRequest: {Item: item}}, - {PutRequest: {Item: item2}}, - {PutRequest: {Item: item3}}, - {PutRequest: {Item: item4}}, - {PutRequest: {Item: item5}}, + { PutRequest: { Item: item } }, + { PutRequest: { Item: item2 } }, + { PutRequest: { Item: item3 } }, + { PutRequest: { Item: item4 } }, + { PutRequest: { Item: item5 } }, ] - request(helpers.opts('BatchWriteItem', batchReq), function(err, res) { + request(helpers.opts('BatchWriteItem', batchReq), function (err, res) { if (err) return done(err) res.statusCode.should.equal(200) - async.forEach([{ + async.forEach([ { ScanFilter: { - b: {ComparisonOperator: 'GE', AttributeValueList: [item3.b]}, - c: {ComparisonOperator: 'EQ', AttributeValueList: [item.c]}, + b: { ComparisonOperator: 'GE', AttributeValueList: [ item3.b ] }, + c: { ComparisonOperator: 'EQ', AttributeValueList: [ item.c ] }, }, }, { FilterExpression: 'b >= :b AND c = :c', - ExpressionAttributeValues: {':b': item3.b, ':c': item.c}, - }], function(scanOpts, cb) { + ExpressionAttributeValues: { ':b': item3.b, ':c': item.c }, + } ], function (scanOpts, cb) { scanOpts.TableName = helpers.testHashTable - request(opts(scanOpts), function(err, res) { + request(opts(scanOpts), function (err, res) { if (err) return cb(err) res.statusCode.should.equal(200) res.body.Items.should.containEql(item) @@ -1953,34 +1953,34 @@ describe('scan', function() { }) }) - it('should scan by GE on type N', function(done) { - var item = {a: {S: helpers.randomString()}, b: {N: '2'}, c: {S: helpers.randomString()}}, - item2 = {a: {S: helpers.randomString()}, b: {N: '1.9999'}, c: item.c}, - item3 = {a: {S: helpers.randomString()}, b: {N: '1'}, c: item.c}, - item4 = {a: {S: helpers.randomString()}, b: {N: '2.00000001'}, c: item.c}, - item5 = {a: {S: helpers.randomString()}, b: {N: '-0.5'}, c: item.c}, - batchReq = {RequestItems: {}} + it('should scan by GE on type N', function (done) { + var item = { a: { S: helpers.randomString() }, b: { N: '2' }, c: { S: helpers.randomString() } }, + item2 = { a: { S: helpers.randomString() }, b: { N: '1.9999' }, c: item.c }, + item3 = { a: { S: helpers.randomString() }, b: { N: '1' }, c: item.c }, + item4 = { a: { S: helpers.randomString() }, b: { N: '2.00000001' }, c: item.c }, + item5 = { a: { S: helpers.randomString() }, b: { N: '-0.5' }, c: item.c }, + batchReq = { RequestItems: {} } batchReq.RequestItems[helpers.testHashTable] = [ - {PutRequest: {Item: item}}, - {PutRequest: {Item: item2}}, - {PutRequest: {Item: item3}}, - {PutRequest: {Item: item4}}, - {PutRequest: {Item: item5}}, + { PutRequest: { Item: item } }, + { PutRequest: { Item: item2 } }, + { PutRequest: { Item: item3 } }, + { PutRequest: { Item: item4 } }, + { PutRequest: { Item: item5 } }, ] - request(helpers.opts('BatchWriteItem', batchReq), function(err, res) { + request(helpers.opts('BatchWriteItem', batchReq), function (err, res) { if (err) return done(err) res.statusCode.should.equal(200) - async.forEach([{ + async.forEach([ { ScanFilter: { - b: {ComparisonOperator: 'GE', AttributeValueList: [item2.b]}, - c: {ComparisonOperator: 'EQ', AttributeValueList: [item.c]}, + b: { ComparisonOperator: 'GE', AttributeValueList: [ item2.b ] }, + c: { ComparisonOperator: 'EQ', AttributeValueList: [ item.c ] }, }, }, { FilterExpression: 'b >= :b AND c = :c', - ExpressionAttributeValues: {':b': item2.b, ':c': item.c}, - }], function(scanOpts, cb) { + ExpressionAttributeValues: { ':b': item2.b, ':c': item.c }, + } ], function (scanOpts, cb) { scanOpts.TableName = helpers.testHashTable - request(opts(scanOpts), function(err, res) { + request(opts(scanOpts), function (err, res) { if (err) return cb(err) res.statusCode.should.equal(200) res.body.Items.should.containEql(item) @@ -1994,34 +1994,34 @@ describe('scan', function() { }) }) - it('should scan by GE on type B', function(done) { - var item = {a: {S: helpers.randomString()}, b: {B: Buffer.from('ce', 'hex').toString('base64')}, c: {S: helpers.randomString()}}, - item2 = {a: {S: helpers.randomString()}, b: {B: Buffer.from('d0', 'hex').toString('base64')}, c: item.c}, - item3 = {a: {S: helpers.randomString()}, b: {B: Buffer.from('cf', 'hex').toString('base64')}, c: item.c}, - item4 = {a: {S: helpers.randomString()}, b: {B: Buffer.from('d000', 'hex').toString('base64')}, c: item.c}, - item5 = {a: {S: helpers.randomString()}, b: {B: Buffer.from('cfff', 'hex').toString('base64')}, c: item.c}, - batchReq = {RequestItems: {}} + it('should scan by GE on type B', function (done) { + var item = { a: { S: helpers.randomString() }, b: { B: Buffer.from('ce', 'hex').toString('base64') }, c: { S: helpers.randomString() } }, + item2 = { a: { S: helpers.randomString() }, b: { B: Buffer.from('d0', 'hex').toString('base64') }, c: item.c }, + item3 = { a: { S: helpers.randomString() }, b: { B: Buffer.from('cf', 'hex').toString('base64') }, c: item.c }, + item4 = { a: { S: helpers.randomString() }, b: { B: Buffer.from('d000', 'hex').toString('base64') }, c: item.c }, + item5 = { a: { S: helpers.randomString() }, b: { B: Buffer.from('cfff', 'hex').toString('base64') }, c: item.c }, + batchReq = { RequestItems: {} } batchReq.RequestItems[helpers.testHashTable] = [ - {PutRequest: {Item: item}}, - {PutRequest: {Item: item2}}, - {PutRequest: {Item: item3}}, - {PutRequest: {Item: item4}}, - {PutRequest: {Item: item5}}, + { PutRequest: { Item: item } }, + { PutRequest: { Item: item2 } }, + { PutRequest: { Item: item3 } }, + { PutRequest: { Item: item4 } }, + { PutRequest: { Item: item5 } }, ] - request(helpers.opts('BatchWriteItem', batchReq), function(err, res) { + request(helpers.opts('BatchWriteItem', batchReq), function (err, res) { if (err) return done(err) res.statusCode.should.equal(200) - async.forEach([{ + async.forEach([ { ScanFilter: { - b: {ComparisonOperator: 'GE', AttributeValueList: [item3.b]}, - c: {ComparisonOperator: 'EQ', AttributeValueList: [item.c]}, + b: { ComparisonOperator: 'GE', AttributeValueList: [ item3.b ] }, + c: { ComparisonOperator: 'EQ', AttributeValueList: [ item.c ] }, }, }, { FilterExpression: 'b >= :b AND c = :c', - ExpressionAttributeValues: {':b': item3.b, ':c': item.c}, - }], function(scanOpts, cb) { + ExpressionAttributeValues: { ':b': item3.b, ':c': item.c }, + } ], function (scanOpts, cb) { scanOpts.TableName = helpers.testHashTable - request(opts(scanOpts), function(err, res) { + request(opts(scanOpts), function (err, res) { if (err) return cb(err) res.statusCode.should.equal(200) res.body.Items.should.containEql(item2) @@ -2036,34 +2036,34 @@ describe('scan', function() { }) }) - it('should scan by GT on type S', function(done) { - var item = {a: {S: helpers.randomString()}, b: {S: 'abd'}, c: {S: helpers.randomString()}}, - item2 = {a: {S: helpers.randomString()}, b: {S: 'abc\xff'}, c: item.c}, - item3 = {a: {S: helpers.randomString()}, b: {S: 'abc'}, c: item.c}, - item4 = {a: {S: helpers.randomString()}, b: {S: 'abd\x00'}, c: item.c}, - item5 = {a: {S: helpers.randomString()}, b: {S: 'ab'}, c: item.c}, - batchReq = {RequestItems: {}} + it('should scan by GT on type S', function (done) { + var item = { a: { S: helpers.randomString() }, b: { S: 'abd' }, c: { S: helpers.randomString() } }, + item2 = { a: { S: helpers.randomString() }, b: { S: 'abc\xff' }, c: item.c }, + item3 = { a: { S: helpers.randomString() }, b: { S: 'abc' }, c: item.c }, + item4 = { a: { S: helpers.randomString() }, b: { S: 'abd\x00' }, c: item.c }, + item5 = { a: { S: helpers.randomString() }, b: { S: 'ab' }, c: item.c }, + batchReq = { RequestItems: {} } batchReq.RequestItems[helpers.testHashTable] = [ - {PutRequest: {Item: item}}, - {PutRequest: {Item: item2}}, - {PutRequest: {Item: item3}}, - {PutRequest: {Item: item4}}, - {PutRequest: {Item: item5}}, + { PutRequest: { Item: item } }, + { PutRequest: { Item: item2 } }, + { PutRequest: { Item: item3 } }, + { PutRequest: { Item: item4 } }, + { PutRequest: { Item: item5 } }, ] - request(helpers.opts('BatchWriteItem', batchReq), function(err, res) { + request(helpers.opts('BatchWriteItem', batchReq), function (err, res) { if (err) return done(err) res.statusCode.should.equal(200) - async.forEach([{ + async.forEach([ { ScanFilter: { - b: {ComparisonOperator: 'GT', AttributeValueList: [item3.b]}, - c: {ComparisonOperator: 'EQ', AttributeValueList: [item.c]}, + b: { ComparisonOperator: 'GT', AttributeValueList: [ item3.b ] }, + c: { ComparisonOperator: 'EQ', AttributeValueList: [ item.c ] }, }, }, { FilterExpression: 'b > :b AND c = :c', - ExpressionAttributeValues: {':b': item3.b, ':c': item.c}, - }], function(scanOpts, cb) { + ExpressionAttributeValues: { ':b': item3.b, ':c': item.c }, + } ], function (scanOpts, cb) { scanOpts.TableName = helpers.testHashTable - request(opts(scanOpts), function(err, res) { + request(opts(scanOpts), function (err, res) { if (err) return cb(err) res.statusCode.should.equal(200) res.body.Items.should.containEql(item) @@ -2077,34 +2077,34 @@ describe('scan', function() { }) }) - it('should scan by GT on type N', function(done) { - var item = {a: {S: helpers.randomString()}, b: {N: '2'}, c: {S: helpers.randomString()}}, - item2 = {a: {S: helpers.randomString()}, b: {N: '1.9999'}, c: item.c}, - item3 = {a: {S: helpers.randomString()}, b: {N: '1'}, c: item.c}, - item4 = {a: {S: helpers.randomString()}, b: {N: '2.00000001'}, c: item.c}, - item5 = {a: {S: helpers.randomString()}, b: {N: '-0.5'}, c: item.c}, - batchReq = {RequestItems: {}} + it('should scan by GT on type N', function (done) { + var item = { a: { S: helpers.randomString() }, b: { N: '2' }, c: { S: helpers.randomString() } }, + item2 = { a: { S: helpers.randomString() }, b: { N: '1.9999' }, c: item.c }, + item3 = { a: { S: helpers.randomString() }, b: { N: '1' }, c: item.c }, + item4 = { a: { S: helpers.randomString() }, b: { N: '2.00000001' }, c: item.c }, + item5 = { a: { S: helpers.randomString() }, b: { N: '-0.5' }, c: item.c }, + batchReq = { RequestItems: {} } batchReq.RequestItems[helpers.testHashTable] = [ - {PutRequest: {Item: item}}, - {PutRequest: {Item: item2}}, - {PutRequest: {Item: item3}}, - {PutRequest: {Item: item4}}, - {PutRequest: {Item: item5}}, + { PutRequest: { Item: item } }, + { PutRequest: { Item: item2 } }, + { PutRequest: { Item: item3 } }, + { PutRequest: { Item: item4 } }, + { PutRequest: { Item: item5 } }, ] - request(helpers.opts('BatchWriteItem', batchReq), function(err, res) { + request(helpers.opts('BatchWriteItem', batchReq), function (err, res) { if (err) return done(err) res.statusCode.should.equal(200) - async.forEach([{ + async.forEach([ { ScanFilter: { - b: {ComparisonOperator: 'GT', AttributeValueList: [item2.b]}, - c: {ComparisonOperator: 'EQ', AttributeValueList: [item.c]}, + b: { ComparisonOperator: 'GT', AttributeValueList: [ item2.b ] }, + c: { ComparisonOperator: 'EQ', AttributeValueList: [ item.c ] }, }, }, { FilterExpression: 'b > :b AND c = :c', - ExpressionAttributeValues: {':b': item2.b, ':c': item.c}, - }], function(scanOpts, cb) { + ExpressionAttributeValues: { ':b': item2.b, ':c': item.c }, + } ], function (scanOpts, cb) { scanOpts.TableName = helpers.testHashTable - request(opts(scanOpts), function(err, res) { + request(opts(scanOpts), function (err, res) { if (err) return cb(err) res.statusCode.should.equal(200) res.body.Items.should.containEql(item) @@ -2117,34 +2117,34 @@ describe('scan', function() { }) }) - it('should scan by GT on type B', function(done) { - var item = {a: {S: helpers.randomString()}, b: {B: Buffer.from('ce', 'hex').toString('base64')}, c: {S: helpers.randomString()}}, - item2 = {a: {S: helpers.randomString()}, b: {B: Buffer.from('d0', 'hex').toString('base64')}, c: item.c}, - item3 = {a: {S: helpers.randomString()}, b: {B: Buffer.from('cf', 'hex').toString('base64')}, c: item.c}, - item4 = {a: {S: helpers.randomString()}, b: {B: Buffer.from('d000', 'hex').toString('base64')}, c: item.c}, - item5 = {a: {S: helpers.randomString()}, b: {B: Buffer.from('cfff', 'hex').toString('base64')}, c: item.c}, - batchReq = {RequestItems: {}} + it('should scan by GT on type B', function (done) { + var item = { a: { S: helpers.randomString() }, b: { B: Buffer.from('ce', 'hex').toString('base64') }, c: { S: helpers.randomString() } }, + item2 = { a: { S: helpers.randomString() }, b: { B: Buffer.from('d0', 'hex').toString('base64') }, c: item.c }, + item3 = { a: { S: helpers.randomString() }, b: { B: Buffer.from('cf', 'hex').toString('base64') }, c: item.c }, + item4 = { a: { S: helpers.randomString() }, b: { B: Buffer.from('d000', 'hex').toString('base64') }, c: item.c }, + item5 = { a: { S: helpers.randomString() }, b: { B: Buffer.from('cfff', 'hex').toString('base64') }, c: item.c }, + batchReq = { RequestItems: {} } batchReq.RequestItems[helpers.testHashTable] = [ - {PutRequest: {Item: item}}, - {PutRequest: {Item: item2}}, - {PutRequest: {Item: item3}}, - {PutRequest: {Item: item4}}, - {PutRequest: {Item: item5}}, + { PutRequest: { Item: item } }, + { PutRequest: { Item: item2 } }, + { PutRequest: { Item: item3 } }, + { PutRequest: { Item: item4 } }, + { PutRequest: { Item: item5 } }, ] - request(helpers.opts('BatchWriteItem', batchReq), function(err, res) { + request(helpers.opts('BatchWriteItem', batchReq), function (err, res) { if (err) return done(err) res.statusCode.should.equal(200) - async.forEach([{ + async.forEach([ { ScanFilter: { - b: {ComparisonOperator: 'GT', AttributeValueList: [item3.b]}, - c: {ComparisonOperator: 'EQ', AttributeValueList: [item.c]}, + b: { ComparisonOperator: 'GT', AttributeValueList: [ item3.b ] }, + c: { ComparisonOperator: 'EQ', AttributeValueList: [ item.c ] }, }, }, { FilterExpression: 'b > :b AND c = :c', - ExpressionAttributeValues: {':b': item3.b, ':c': item.c}, - }], function(scanOpts, cb) { + ExpressionAttributeValues: { ':b': item3.b, ':c': item.c }, + } ], function (scanOpts, cb) { scanOpts.TableName = helpers.testHashTable - request(opts(scanOpts), function(err, res) { + request(opts(scanOpts), function (err, res) { if (err) return cb(err) res.statusCode.should.equal(200) res.body.Items.should.containEql(item2) @@ -2158,30 +2158,30 @@ describe('scan', function() { }) }) - it('should scan by NOT_NULL', function(done) { - var item = {a: {S: helpers.randomString()}, b: {S: helpers.randomString()}, c: {S: helpers.randomString()}}, - item2 = {a: {S: helpers.randomString()}, b: {S: helpers.randomString()}, c: item.c}, - item3 = {a: {S: helpers.randomString()}, c: item.c}, - batchReq = {RequestItems: {}} + it('should scan by NOT_NULL', function (done) { + var item = { a: { S: helpers.randomString() }, b: { S: helpers.randomString() }, c: { S: helpers.randomString() } }, + item2 = { a: { S: helpers.randomString() }, b: { S: helpers.randomString() }, c: item.c }, + item3 = { a: { S: helpers.randomString() }, c: item.c }, + batchReq = { RequestItems: {} } batchReq.RequestItems[helpers.testHashTable] = [ - {PutRequest: {Item: item}}, - {PutRequest: {Item: item2}}, - {PutRequest: {Item: item3}}, + { PutRequest: { Item: item } }, + { PutRequest: { Item: item2 } }, + { PutRequest: { Item: item3 } }, ] - request(helpers.opts('BatchWriteItem', batchReq), function(err, res) { + request(helpers.opts('BatchWriteItem', batchReq), function (err, res) { if (err) return done(err) res.statusCode.should.equal(200) - async.forEach([{ + async.forEach([ { ScanFilter: { - b: {ComparisonOperator: 'NOT_NULL'}, - c: {ComparisonOperator: 'EQ', AttributeValueList: [item.c]}, + b: { ComparisonOperator: 'NOT_NULL' }, + c: { ComparisonOperator: 'EQ', AttributeValueList: [ item.c ] }, }, }, { FilterExpression: 'attribute_exists(b) AND c = :c', - ExpressionAttributeValues: {':c': item.c}, - }], function(scanOpts, cb) { + ExpressionAttributeValues: { ':c': item.c }, + } ], function (scanOpts, cb) { scanOpts.TableName = helpers.testHashTable - request(opts(scanOpts), function(err, res) { + request(opts(scanOpts), function (err, res) { if (err) return cb(err) res.statusCode.should.equal(200) res.body.Items.should.containEql(item) @@ -2194,30 +2194,30 @@ describe('scan', function() { }) }) - it('should scan by NULL', function(done) { - var item = {a: {S: helpers.randomString()}, c: {S: helpers.randomString()}}, - item2 = {a: {S: helpers.randomString()}, c: item.c}, - item3 = {a: {S: helpers.randomString()}, b: {S: helpers.randomString()}, c: item.c}, - batchReq = {RequestItems: {}} + it('should scan by NULL', function (done) { + var item = { a: { S: helpers.randomString() }, c: { S: helpers.randomString() } }, + item2 = { a: { S: helpers.randomString() }, c: item.c }, + item3 = { a: { S: helpers.randomString() }, b: { S: helpers.randomString() }, c: item.c }, + batchReq = { RequestItems: {} } batchReq.RequestItems[helpers.testHashTable] = [ - {PutRequest: {Item: item}}, - {PutRequest: {Item: item2}}, - {PutRequest: {Item: item3}}, + { PutRequest: { Item: item } }, + { PutRequest: { Item: item2 } }, + { PutRequest: { Item: item3 } }, ] - request(helpers.opts('BatchWriteItem', batchReq), function(err, res) { + request(helpers.opts('BatchWriteItem', batchReq), function (err, res) { if (err) return done(err) res.statusCode.should.equal(200) - async.forEach([{ + async.forEach([ { ScanFilter: { - b: {ComparisonOperator: 'NULL'}, - c: {ComparisonOperator: 'EQ', AttributeValueList: [item.c]}, + b: { ComparisonOperator: 'NULL' }, + c: { ComparisonOperator: 'EQ', AttributeValueList: [ item.c ] }, }, }, { FilterExpression: 'attribute_not_exists(b) AND c = :c', - ExpressionAttributeValues: {':c': item.c}, - }], function(scanOpts, cb) { + ExpressionAttributeValues: { ':c': item.c }, + } ], function (scanOpts, cb) { scanOpts.TableName = helpers.testHashTable - request(opts(scanOpts), function(err, res) { + request(opts(scanOpts), function (err, res) { if (err) return cb(err) res.statusCode.should.equal(200) res.body.Items.should.containEql(item) @@ -2230,42 +2230,42 @@ describe('scan', function() { }) }) - it('should scan by CONTAINS on type S', function(done) { - var item = {a: {S: helpers.randomString()}, b: {S: 'abdef'}, c: {S: helpers.randomString()}}, - item2 = {a: {S: helpers.randomString()}, b: {SS: ['abd', 'bde']}, c: item.c}, - item3 = {a: {S: helpers.randomString()}, b: {B: Buffer.from('abdef').toString('base64')}, c: item.c}, - item4 = {a: {S: helpers.randomString()}, b: {BS: ['abcd', Buffer.from('bde').toString('base64')]}, c: item.c}, - item5 = {a: {S: helpers.randomString()}, b: {S: 'bde'}, c: item.c}, - item6 = {a: {S: helpers.randomString()}, b: {S: 'abd'}, c: item.c}, - item7 = {a: {S: helpers.randomString()}, b: {L: [{'N': '123'}, {'S': 'bde'}]}, c: item.c}, - item8 = {a: {S: helpers.randomString()}, b: {L: [{'S': 'abd'}]}, c: item.c}, - item9 = {a: {S: helpers.randomString()}, b: {L: [{'S': 'abde'}]}, c: item.c}, - batchReq = {RequestItems: {}} + it('should scan by CONTAINS on type S', function (done) { + var item = { a: { S: helpers.randomString() }, b: { S: 'abdef' }, c: { S: helpers.randomString() } }, + item2 = { a: { S: helpers.randomString() }, b: { SS: [ 'abd', 'bde' ] }, c: item.c }, + item3 = { a: { S: helpers.randomString() }, b: { B: Buffer.from('abdef').toString('base64') }, c: item.c }, + item4 = { a: { S: helpers.randomString() }, b: { BS: [ 'abcd', Buffer.from('bde').toString('base64') ] }, c: item.c }, + item5 = { a: { S: helpers.randomString() }, b: { S: 'bde' }, c: item.c }, + item6 = { a: { S: helpers.randomString() }, b: { S: 'abd' }, c: item.c }, + item7 = { a: { S: helpers.randomString() }, b: { L: [ { 'N': '123' }, { 'S': 'bde' } ] }, c: item.c }, + item8 = { a: { S: helpers.randomString() }, b: { L: [ { 'S': 'abd' } ] }, c: item.c }, + item9 = { a: { S: helpers.randomString() }, b: { L: [ { 'S': 'abde' } ] }, c: item.c }, + batchReq = { RequestItems: {} } batchReq.RequestItems[helpers.testHashTable] = [ - {PutRequest: {Item: item}}, - {PutRequest: {Item: item2}}, - {PutRequest: {Item: item3}}, - {PutRequest: {Item: item4}}, - {PutRequest: {Item: item5}}, - {PutRequest: {Item: item6}}, - {PutRequest: {Item: item7}}, - {PutRequest: {Item: item8}}, - {PutRequest: {Item: item9}}, + { PutRequest: { Item: item } }, + { PutRequest: { Item: item2 } }, + { PutRequest: { Item: item3 } }, + { PutRequest: { Item: item4 } }, + { PutRequest: { Item: item5 } }, + { PutRequest: { Item: item6 } }, + { PutRequest: { Item: item7 } }, + { PutRequest: { Item: item8 } }, + { PutRequest: { Item: item9 } }, ] - request(helpers.opts('BatchWriteItem', batchReq), function(err, res) { + request(helpers.opts('BatchWriteItem', batchReq), function (err, res) { if (err) return done(err) res.statusCode.should.equal(200) - async.forEach([{ + async.forEach([ { ScanFilter: { - b: {ComparisonOperator: 'CONTAINS', AttributeValueList: [item5.b]}, - c: {ComparisonOperator: 'EQ', AttributeValueList: [item.c]}, + b: { ComparisonOperator: 'CONTAINS', AttributeValueList: [ item5.b ] }, + c: { ComparisonOperator: 'EQ', AttributeValueList: [ item.c ] }, }, }, { FilterExpression: 'contains(b, :b) AND c = :c', - ExpressionAttributeValues: {':b': item5.b, ':c': item.c}, - }], function(scanOpts, cb) { + ExpressionAttributeValues: { ':b': item5.b, ':c': item.c }, + } ], function (scanOpts, cb) { scanOpts.TableName = helpers.testHashTable - request(opts(scanOpts), function(err, res) { + request(opts(scanOpts), function (err, res) { if (err) return cb(err) res.statusCode.should.equal(200) res.body.Items.should.containEql(item) @@ -2280,40 +2280,40 @@ describe('scan', function() { }) }) - it('should scan by CONTAINS on type N', function(done) { - var item = {a: {S: helpers.randomString()}, b: {N: '1234'}, c: {S: helpers.randomString()}}, - item2 = {a: {S: helpers.randomString()}, b: {NS: ['123', '234']}, c: item.c}, - item3 = {a: {S: helpers.randomString()}, b: {B: Buffer.from('1234').toString('base64')}, c: item.c}, - item4 = {a: {S: helpers.randomString()}, b: {BS: [Buffer.from('234').toString('base64')]}, c: item.c}, - item5 = {a: {S: helpers.randomString()}, b: {SS: ['234']}, c: item.c}, - item6 = {a: {S: helpers.randomString()}, b: {L: [{'S': 'abd'}, {'N': '234'}]}, c: item.c}, - item7 = {a: {S: helpers.randomString()}, b: {L: [{'N': '123'}]}, c: item.c}, - item8 = {a: {S: helpers.randomString()}, b: {L: [{'N': '1234'}]}, c: item.c}, - batchReq = {RequestItems: {}} + it('should scan by CONTAINS on type N', function (done) { + var item = { a: { S: helpers.randomString() }, b: { N: '1234' }, c: { S: helpers.randomString() } }, + item2 = { a: { S: helpers.randomString() }, b: { NS: [ '123', '234' ] }, c: item.c }, + item3 = { a: { S: helpers.randomString() }, b: { B: Buffer.from('1234').toString('base64') }, c: item.c }, + item4 = { a: { S: helpers.randomString() }, b: { BS: [ Buffer.from('234').toString('base64') ] }, c: item.c }, + item5 = { a: { S: helpers.randomString() }, b: { SS: [ '234' ] }, c: item.c }, + item6 = { a: { S: helpers.randomString() }, b: { L: [ { 'S': 'abd' }, { 'N': '234' } ] }, c: item.c }, + item7 = { a: { S: helpers.randomString() }, b: { L: [ { 'N': '123' } ] }, c: item.c }, + item8 = { a: { S: helpers.randomString() }, b: { L: [ { 'N': '1234' } ] }, c: item.c }, + batchReq = { RequestItems: {} } batchReq.RequestItems[helpers.testHashTable] = [ - {PutRequest: {Item: item}}, - {PutRequest: {Item: item2}}, - {PutRequest: {Item: item3}}, - {PutRequest: {Item: item4}}, - {PutRequest: {Item: item5}}, - {PutRequest: {Item: item6}}, - {PutRequest: {Item: item7}}, - {PutRequest: {Item: item8}}, + { PutRequest: { Item: item } }, + { PutRequest: { Item: item2 } }, + { PutRequest: { Item: item3 } }, + { PutRequest: { Item: item4 } }, + { PutRequest: { Item: item5 } }, + { PutRequest: { Item: item6 } }, + { PutRequest: { Item: item7 } }, + { PutRequest: { Item: item8 } }, ] - request(helpers.opts('BatchWriteItem', batchReq), function(err, res) { + request(helpers.opts('BatchWriteItem', batchReq), function (err, res) { if (err) return done(err) res.statusCode.should.equal(200) - async.forEach([{ + async.forEach([ { ScanFilter: { - b: {ComparisonOperator: 'CONTAINS', AttributeValueList: [{N: '234'}]}, - c: {ComparisonOperator: 'EQ', AttributeValueList: [item.c]}, + b: { ComparisonOperator: 'CONTAINS', AttributeValueList: [ { N: '234' } ] }, + c: { ComparisonOperator: 'EQ', AttributeValueList: [ item.c ] }, }, }, { FilterExpression: 'contains(b, :b) AND c = :c', - ExpressionAttributeValues: {':b': {N: '234'}, ':c': item.c}, - }], function(scanOpts, cb) { + ExpressionAttributeValues: { ':b': { N: '234' }, ':c': item.c }, + } ], function (scanOpts, cb) { scanOpts.TableName = helpers.testHashTable - request(opts(scanOpts), function(err, res) { + request(opts(scanOpts), function (err, res) { if (err) return cb(err) res.statusCode.should.equal(200) res.body.Items.should.containEql(item2) @@ -2326,42 +2326,42 @@ describe('scan', function() { }) }) - it('should scan by CONTAINS on type B', function(done) { - var item = {a: {S: helpers.randomString()}, b: {S: 'abdef'}, c: {S: helpers.randomString()}}, - item2 = {a: {S: helpers.randomString()}, b: {SS: ['abd', 'bde']}, c: item.c}, - item3 = {a: {S: helpers.randomString()}, b: {B: Buffer.from('abdef').toString('base64')}, c: item.c}, - item4 = {a: {S: helpers.randomString()}, b: {BS: [Buffer.from('bde').toString('base64'), 'abcd']}, c: item.c}, - item5 = {a: {S: helpers.randomString()}, b: {B: Buffer.from('bde').toString('base64')}, c: item.c}, - item6 = {a: {S: helpers.randomString()}, b: {S: 'abd'}, c: item.c}, - item7 = {a: {S: helpers.randomString()}, b: {L: [{'N': '123'}, {'B': Buffer.from('bde').toString('base64')}]}, c: item.c}, - item8 = {a: {S: helpers.randomString()}, b: {L: [{'B': Buffer.from('abd').toString('base64')}]}, c: item.c}, - item9 = {a: {S: helpers.randomString()}, b: {L: [{'B': Buffer.from('abde').toString('base64')}]}, c: item.c}, - batchReq = {RequestItems: {}} + it('should scan by CONTAINS on type B', function (done) { + var item = { a: { S: helpers.randomString() }, b: { S: 'abdef' }, c: { S: helpers.randomString() } }, + item2 = { a: { S: helpers.randomString() }, b: { SS: [ 'abd', 'bde' ] }, c: item.c }, + item3 = { a: { S: helpers.randomString() }, b: { B: Buffer.from('abdef').toString('base64') }, c: item.c }, + item4 = { a: { S: helpers.randomString() }, b: { BS: [ Buffer.from('bde').toString('base64'), 'abcd' ] }, c: item.c }, + item5 = { a: { S: helpers.randomString() }, b: { B: Buffer.from('bde').toString('base64') }, c: item.c }, + item6 = { a: { S: helpers.randomString() }, b: { S: 'abd' }, c: item.c }, + item7 = { a: { S: helpers.randomString() }, b: { L: [ { 'N': '123' }, { 'B': Buffer.from('bde').toString('base64') } ] }, c: item.c }, + item8 = { a: { S: helpers.randomString() }, b: { L: [ { 'B': Buffer.from('abd').toString('base64') } ] }, c: item.c }, + item9 = { a: { S: helpers.randomString() }, b: { L: [ { 'B': Buffer.from('abde').toString('base64') } ] }, c: item.c }, + batchReq = { RequestItems: {} } batchReq.RequestItems[helpers.testHashTable] = [ - {PutRequest: {Item: item}}, - {PutRequest: {Item: item2}}, - {PutRequest: {Item: item3}}, - {PutRequest: {Item: item4}}, - {PutRequest: {Item: item5}}, - {PutRequest: {Item: item6}}, - {PutRequest: {Item: item7}}, - {PutRequest: {Item: item8}}, - {PutRequest: {Item: item9}}, + { PutRequest: { Item: item } }, + { PutRequest: { Item: item2 } }, + { PutRequest: { Item: item3 } }, + { PutRequest: { Item: item4 } }, + { PutRequest: { Item: item5 } }, + { PutRequest: { Item: item6 } }, + { PutRequest: { Item: item7 } }, + { PutRequest: { Item: item8 } }, + { PutRequest: { Item: item9 } }, ] - request(helpers.opts('BatchWriteItem', batchReq), function(err, res) { + request(helpers.opts('BatchWriteItem', batchReq), function (err, res) { if (err) return done(err) res.statusCode.should.equal(200) - async.forEach([{ + async.forEach([ { ScanFilter: { - b: {ComparisonOperator: 'CONTAINS', AttributeValueList: [item5.b]}, - c: {ComparisonOperator: 'EQ', AttributeValueList: [item.c]}, + b: { ComparisonOperator: 'CONTAINS', AttributeValueList: [ item5.b ] }, + c: { ComparisonOperator: 'EQ', AttributeValueList: [ item.c ] }, }, }, { FilterExpression: 'contains(b, :b) AND c = :c', - ExpressionAttributeValues: {':b': item5.b, ':c': item.c}, - }], function(scanOpts, cb) { + ExpressionAttributeValues: { ':b': item5.b, ':c': item.c }, + } ], function (scanOpts, cb) { scanOpts.TableName = helpers.testHashTable - request(opts(scanOpts), function(err, res) { + request(opts(scanOpts), function (err, res) { if (err) return cb(err) res.statusCode.should.equal(200) res.body.Items.should.containEql(item3) @@ -2376,36 +2376,36 @@ describe('scan', function() { }) }) - it('should scan by NOT_CONTAINS on type S', function(done) { - var item = {a: {S: helpers.randomString()}, b: {S: 'abdef'}, c: {S: helpers.randomString()}}, - item2 = {a: {S: helpers.randomString()}, b: {SS: ['abd', 'bde']}, c: item.c}, - item3 = {a: {S: helpers.randomString()}, b: {B: Buffer.from('abdef').toString('base64')}, c: item.c}, - item4 = {a: {S: helpers.randomString()}, b: {BS: [Buffer.from('bde').toString('base64'), 'abcd']}, c: item.c}, - item5 = {a: {S: helpers.randomString()}, b: {S: 'bde'}, c: item.c}, - item6 = {a: {S: helpers.randomString()}, b: {S: 'abd'}, c: item.c}, - batchReq = {RequestItems: {}} + it('should scan by NOT_CONTAINS on type S', function (done) { + var item = { a: { S: helpers.randomString() }, b: { S: 'abdef' }, c: { S: helpers.randomString() } }, + item2 = { a: { S: helpers.randomString() }, b: { SS: [ 'abd', 'bde' ] }, c: item.c }, + item3 = { a: { S: helpers.randomString() }, b: { B: Buffer.from('abdef').toString('base64') }, c: item.c }, + item4 = { a: { S: helpers.randomString() }, b: { BS: [ Buffer.from('bde').toString('base64'), 'abcd' ] }, c: item.c }, + item5 = { a: { S: helpers.randomString() }, b: { S: 'bde' }, c: item.c }, + item6 = { a: { S: helpers.randomString() }, b: { S: 'abd' }, c: item.c }, + batchReq = { RequestItems: {} } batchReq.RequestItems[helpers.testHashTable] = [ - {PutRequest: {Item: item}}, - {PutRequest: {Item: item2}}, - {PutRequest: {Item: item3}}, - {PutRequest: {Item: item4}}, - {PutRequest: {Item: item5}}, - {PutRequest: {Item: item6}}, + { PutRequest: { Item: item } }, + { PutRequest: { Item: item2 } }, + { PutRequest: { Item: item3 } }, + { PutRequest: { Item: item4 } }, + { PutRequest: { Item: item5 } }, + { PutRequest: { Item: item6 } }, ] - request(helpers.opts('BatchWriteItem', batchReq), function(err, res) { + request(helpers.opts('BatchWriteItem', batchReq), function (err, res) { if (err) return done(err) res.statusCode.should.equal(200) - async.forEach([{ + async.forEach([ { ScanFilter: { - b: {ComparisonOperator: 'NOT_CONTAINS', AttributeValueList: [item5.b]}, - c: {ComparisonOperator: 'EQ', AttributeValueList: [item.c]}, + b: { ComparisonOperator: 'NOT_CONTAINS', AttributeValueList: [ item5.b ] }, + c: { ComparisonOperator: 'EQ', AttributeValueList: [ item.c ] }, }, }, { FilterExpression: 'NOT contains(b, :b) AND c = :c', - ExpressionAttributeValues: {':b': item5.b, ':c': item.c}, - }], function(scanOpts, cb) { + ExpressionAttributeValues: { ':b': item5.b, ':c': item.c }, + } ], function (scanOpts, cb) { scanOpts.TableName = helpers.testHashTable - request(opts(scanOpts), function(err, res) { + request(opts(scanOpts), function (err, res) { if (err) return cb(err) res.statusCode.should.equal(200) res.body.Items.should.containEql(item3) @@ -2419,34 +2419,34 @@ describe('scan', function() { }) }) - it('should scan by NOT_CONTAINS on type N', function(done) { - var item = {a: {S: helpers.randomString()}, b: {N: '1234'}, c: {S: helpers.randomString()}}, - item2 = {a: {S: helpers.randomString()}, b: {NS: ['123', '234']}, c: item.c}, - item3 = {a: {S: helpers.randomString()}, b: {B: Buffer.from('1234').toString('base64')}, c: item.c}, - item4 = {a: {S: helpers.randomString()}, b: {BS: [Buffer.from('234').toString('base64')]}, c: item.c}, - item5 = {a: {S: helpers.randomString()}, b: {SS: ['234']}, c: item.c}, - batchReq = {RequestItems: {}} + it('should scan by NOT_CONTAINS on type N', function (done) { + var item = { a: { S: helpers.randomString() }, b: { N: '1234' }, c: { S: helpers.randomString() } }, + item2 = { a: { S: helpers.randomString() }, b: { NS: [ '123', '234' ] }, c: item.c }, + item3 = { a: { S: helpers.randomString() }, b: { B: Buffer.from('1234').toString('base64') }, c: item.c }, + item4 = { a: { S: helpers.randomString() }, b: { BS: [ Buffer.from('234').toString('base64') ] }, c: item.c }, + item5 = { a: { S: helpers.randomString() }, b: { SS: [ '234' ] }, c: item.c }, + batchReq = { RequestItems: {} } batchReq.RequestItems[helpers.testHashTable] = [ - {PutRequest: {Item: item}}, - {PutRequest: {Item: item2}}, - {PutRequest: {Item: item3}}, - {PutRequest: {Item: item4}}, - {PutRequest: {Item: item5}}, + { PutRequest: { Item: item } }, + { PutRequest: { Item: item2 } }, + { PutRequest: { Item: item3 } }, + { PutRequest: { Item: item4 } }, + { PutRequest: { Item: item5 } }, ] - request(helpers.opts('BatchWriteItem', batchReq), function(err, res) { + request(helpers.opts('BatchWriteItem', batchReq), function (err, res) { if (err) return done(err) res.statusCode.should.equal(200) - async.forEach([{ + async.forEach([ { ScanFilter: { - b: {ComparisonOperator: 'NOT_CONTAINS', AttributeValueList: [{N: '234'}]}, - c: {ComparisonOperator: 'EQ', AttributeValueList: [item.c]}, + b: { ComparisonOperator: 'NOT_CONTAINS', AttributeValueList: [ { N: '234' } ] }, + c: { ComparisonOperator: 'EQ', AttributeValueList: [ item.c ] }, }, }, { FilterExpression: 'NOT contains(b, :b) AND c = :c', - ExpressionAttributeValues: {':b': {N: '234'}, ':c': item.c}, - }], function(scanOpts, cb) { + ExpressionAttributeValues: { ':b': { N: '234' }, ':c': item.c }, + } ], function (scanOpts, cb) { scanOpts.TableName = helpers.testHashTable - request(opts(scanOpts), function(err, res) { + request(opts(scanOpts), function (err, res) { if (err) return cb(err) res.statusCode.should.equal(200) res.body.Items.should.containEql(item) @@ -2461,36 +2461,36 @@ describe('scan', function() { }) }) - it('should scan by NOT_CONTAINS on type B', function(done) { - var item = {a: {S: helpers.randomString()}, b: {S: 'abdef'}, c: {S: helpers.randomString()}}, - item2 = {a: {S: helpers.randomString()}, b: {SS: ['abd', 'bde']}, c: item.c}, - item3 = {a: {S: helpers.randomString()}, b: {B: Buffer.from('abdef').toString('base64')}, c: item.c}, - item4 = {a: {S: helpers.randomString()}, b: {BS: [Buffer.from('bde').toString('base64'), 'abcd']}, c: item.c}, - item5 = {a: {S: helpers.randomString()}, b: {B: Buffer.from('bde').toString('base64')}, c: item.c}, - item6 = {a: {S: helpers.randomString()}, b: {S: 'abd'}, c: item.c}, - batchReq = {RequestItems: {}} + it('should scan by NOT_CONTAINS on type B', function (done) { + var item = { a: { S: helpers.randomString() }, b: { S: 'abdef' }, c: { S: helpers.randomString() } }, + item2 = { a: { S: helpers.randomString() }, b: { SS: [ 'abd', 'bde' ] }, c: item.c }, + item3 = { a: { S: helpers.randomString() }, b: { B: Buffer.from('abdef').toString('base64') }, c: item.c }, + item4 = { a: { S: helpers.randomString() }, b: { BS: [ Buffer.from('bde').toString('base64'), 'abcd' ] }, c: item.c }, + item5 = { a: { S: helpers.randomString() }, b: { B: Buffer.from('bde').toString('base64') }, c: item.c }, + item6 = { a: { S: helpers.randomString() }, b: { S: 'abd' }, c: item.c }, + batchReq = { RequestItems: {} } batchReq.RequestItems[helpers.testHashTable] = [ - {PutRequest: {Item: item}}, - {PutRequest: {Item: item2}}, - {PutRequest: {Item: item3}}, - {PutRequest: {Item: item4}}, - {PutRequest: {Item: item5}}, - {PutRequest: {Item: item6}}, + { PutRequest: { Item: item } }, + { PutRequest: { Item: item2 } }, + { PutRequest: { Item: item3 } }, + { PutRequest: { Item: item4 } }, + { PutRequest: { Item: item5 } }, + { PutRequest: { Item: item6 } }, ] - request(helpers.opts('BatchWriteItem', batchReq), function(err, res) { + request(helpers.opts('BatchWriteItem', batchReq), function (err, res) { if (err) return done(err) res.statusCode.should.equal(200) - async.forEach([{ + async.forEach([ { ScanFilter: { - b: {ComparisonOperator: 'NOT_CONTAINS', AttributeValueList: [item5.b]}, - c: {ComparisonOperator: 'EQ', AttributeValueList: [item.c]}, + b: { ComparisonOperator: 'NOT_CONTAINS', AttributeValueList: [ item5.b ] }, + c: { ComparisonOperator: 'EQ', AttributeValueList: [ item.c ] }, }, }, { FilterExpression: 'NOT contains(b, :b) AND c = :c', - ExpressionAttributeValues: {':b': item5.b, ':c': item.c}, - }], function(scanOpts, cb) { + ExpressionAttributeValues: { ':b': item5.b, ':c': item.c }, + } ], function (scanOpts, cb) { scanOpts.TableName = helpers.testHashTable - request(opts(scanOpts), function(err, res) { + request(opts(scanOpts), function (err, res) { if (err) return cb(err) res.statusCode.should.equal(200) res.body.Items.should.containEql(item) @@ -2504,34 +2504,34 @@ describe('scan', function() { }) }) - it('should scan by BEGINS_WITH on type S', function(done) { - var item = {a: {S: helpers.randomString()}, b: {S: 'abdef'}, c: {S: helpers.randomString()}}, - item2 = {a: {S: helpers.randomString()}, b: {SS: ['abd', 'bde']}, c: item.c}, - item3 = {a: {S: helpers.randomString()}, b: {B: Buffer.from('abdef').toString('base64')}, c: item.c}, - item4 = {a: {S: helpers.randomString()}, b: {S: 'ab'}, c: item.c}, - item5 = {a: {S: helpers.randomString()}, b: {S: 'abd'}, c: item.c}, - batchReq = {RequestItems: {}} + it('should scan by BEGINS_WITH on type S', function (done) { + var item = { a: { S: helpers.randomString() }, b: { S: 'abdef' }, c: { S: helpers.randomString() } }, + item2 = { a: { S: helpers.randomString() }, b: { SS: [ 'abd', 'bde' ] }, c: item.c }, + item3 = { a: { S: helpers.randomString() }, b: { B: Buffer.from('abdef').toString('base64') }, c: item.c }, + item4 = { a: { S: helpers.randomString() }, b: { S: 'ab' }, c: item.c }, + item5 = { a: { S: helpers.randomString() }, b: { S: 'abd' }, c: item.c }, + batchReq = { RequestItems: {} } batchReq.RequestItems[helpers.testHashTable] = [ - {PutRequest: {Item: item}}, - {PutRequest: {Item: item2}}, - {PutRequest: {Item: item3}}, - {PutRequest: {Item: item4}}, - {PutRequest: {Item: item5}}, + { PutRequest: { Item: item } }, + { PutRequest: { Item: item2 } }, + { PutRequest: { Item: item3 } }, + { PutRequest: { Item: item4 } }, + { PutRequest: { Item: item5 } }, ] - request(helpers.opts('BatchWriteItem', batchReq), function(err, res) { + request(helpers.opts('BatchWriteItem', batchReq), function (err, res) { if (err) return done(err) res.statusCode.should.equal(200) - async.forEach([{ + async.forEach([ { ScanFilter: { - b: {ComparisonOperator: 'BEGINS_WITH', AttributeValueList: [item5.b]}, - c: {ComparisonOperator: 'EQ', AttributeValueList: [item.c]}, + b: { ComparisonOperator: 'BEGINS_WITH', AttributeValueList: [ item5.b ] }, + c: { ComparisonOperator: 'EQ', AttributeValueList: [ item.c ] }, }, }, { FilterExpression: 'begins_with(b, :b) AND c = :c', - ExpressionAttributeValues: {':b': item5.b, ':c': item.c}, - }], function(scanOpts, cb) { + ExpressionAttributeValues: { ':b': item5.b, ':c': item.c }, + } ], function (scanOpts, cb) { scanOpts.TableName = helpers.testHashTable - request(opts(scanOpts), function(err, res) { + request(opts(scanOpts), function (err, res) { if (err) return cb(err) res.statusCode.should.equal(200) res.body.Items.should.containEql(item) @@ -2544,34 +2544,34 @@ describe('scan', function() { }) }) - it('should scan by BEGINS_WITH on type B', function(done) { - var item = {a: {S: helpers.randomString()}, b: {S: 'abdef'}, c: {S: helpers.randomString()}}, - item2 = {a: {S: helpers.randomString()}, b: {SS: ['abd', 'bde']}, c: item.c}, - item3 = {a: {S: helpers.randomString()}, b: {B: Buffer.from('abdef').toString('base64')}, c: item.c}, - item4 = {a: {S: helpers.randomString()}, b: {S: 'ab'}, c: item.c}, - item5 = {a: {S: helpers.randomString()}, b: {B: Buffer.from('abd').toString('base64')}, c: item.c}, - batchReq = {RequestItems: {}} + it('should scan by BEGINS_WITH on type B', function (done) { + var item = { a: { S: helpers.randomString() }, b: { S: 'abdef' }, c: { S: helpers.randomString() } }, + item2 = { a: { S: helpers.randomString() }, b: { SS: [ 'abd', 'bde' ] }, c: item.c }, + item3 = { a: { S: helpers.randomString() }, b: { B: Buffer.from('abdef').toString('base64') }, c: item.c }, + item4 = { a: { S: helpers.randomString() }, b: { S: 'ab' }, c: item.c }, + item5 = { a: { S: helpers.randomString() }, b: { B: Buffer.from('abd').toString('base64') }, c: item.c }, + batchReq = { RequestItems: {} } batchReq.RequestItems[helpers.testHashTable] = [ - {PutRequest: {Item: item}}, - {PutRequest: {Item: item2}}, - {PutRequest: {Item: item3}}, - {PutRequest: {Item: item4}}, - {PutRequest: {Item: item5}}, + { PutRequest: { Item: item } }, + { PutRequest: { Item: item2 } }, + { PutRequest: { Item: item3 } }, + { PutRequest: { Item: item4 } }, + { PutRequest: { Item: item5 } }, ] - request(helpers.opts('BatchWriteItem', batchReq), function(err, res) { + request(helpers.opts('BatchWriteItem', batchReq), function (err, res) { if (err) return done(err) res.statusCode.should.equal(200) - async.forEach([{ + async.forEach([ { ScanFilter: { - b: {ComparisonOperator: 'BEGINS_WITH', AttributeValueList: [item5.b]}, - c: {ComparisonOperator: 'EQ', AttributeValueList: [item.c]}, + b: { ComparisonOperator: 'BEGINS_WITH', AttributeValueList: [ item5.b ] }, + c: { ComparisonOperator: 'EQ', AttributeValueList: [ item.c ] }, }, }, { FilterExpression: 'begins_with(b, :b) AND c = :c', - ExpressionAttributeValues: {':b': item5.b, ':c': item.c}, - }], function(scanOpts, cb) { + ExpressionAttributeValues: { ':b': item5.b, ':c': item.c }, + } ], function (scanOpts, cb) { scanOpts.TableName = helpers.testHashTable - request(opts(scanOpts), function(err, res) { + request(opts(scanOpts), function (err, res) { if (err) return cb(err) res.statusCode.should.equal(200) res.body.Items.should.containEql(item3) @@ -2584,34 +2584,34 @@ describe('scan', function() { }) }) - it('should scan by IN on type S', function(done) { - var item = {a: {S: helpers.randomString()}, b: {S: 'abdef'}, c: {S: helpers.randomString()}}, - item2 = {a: {S: helpers.randomString()}, b: {SS: ['abd', 'bde']}, c: item.c}, - item3 = {a: {S: helpers.randomString()}, b: {B: Buffer.from('abdef').toString('base64')}, c: item.c}, - item4 = {a: {S: helpers.randomString()}, b: {S: 'ab'}, c: item.c}, - item5 = {a: {S: helpers.randomString()}, b: {S: 'abd'}, c: item.c}, - batchReq = {RequestItems: {}} + it('should scan by IN on type S', function (done) { + var item = { a: { S: helpers.randomString() }, b: { S: 'abdef' }, c: { S: helpers.randomString() } }, + item2 = { a: { S: helpers.randomString() }, b: { SS: [ 'abd', 'bde' ] }, c: item.c }, + item3 = { a: { S: helpers.randomString() }, b: { B: Buffer.from('abdef').toString('base64') }, c: item.c }, + item4 = { a: { S: helpers.randomString() }, b: { S: 'ab' }, c: item.c }, + item5 = { a: { S: helpers.randomString() }, b: { S: 'abd' }, c: item.c }, + batchReq = { RequestItems: {} } batchReq.RequestItems[helpers.testHashTable] = [ - {PutRequest: {Item: item}}, - {PutRequest: {Item: item2}}, - {PutRequest: {Item: item3}}, - {PutRequest: {Item: item4}}, - {PutRequest: {Item: item5}}, + { PutRequest: { Item: item } }, + { PutRequest: { Item: item2 } }, + { PutRequest: { Item: item3 } }, + { PutRequest: { Item: item4 } }, + { PutRequest: { Item: item5 } }, ] - request(helpers.opts('BatchWriteItem', batchReq), function(err, res) { + request(helpers.opts('BatchWriteItem', batchReq), function (err, res) { if (err) return done(err) res.statusCode.should.equal(200) - async.forEach([{ + async.forEach([ { ScanFilter: { - b: {ComparisonOperator: 'IN', AttributeValueList: [item5.b, item.b]}, - c: {ComparisonOperator: 'EQ', AttributeValueList: [item.c]}, + b: { ComparisonOperator: 'IN', AttributeValueList: [ item5.b, item.b ] }, + c: { ComparisonOperator: 'EQ', AttributeValueList: [ item.c ] }, }, }, { FilterExpression: 'b IN (:b, :d) AND c = :c', - ExpressionAttributeValues: {':b': item5.b, ':c': item.c, ':d': item.b}, - }], function(scanOpts, cb) { + ExpressionAttributeValues: { ':b': item5.b, ':c': item.c, ':d': item.b }, + } ], function (scanOpts, cb) { scanOpts.TableName = helpers.testHashTable - request(opts(scanOpts), function(err, res) { + request(opts(scanOpts), function (err, res) { if (err) return cb(err) res.statusCode.should.equal(200) res.body.Items.should.containEql(item) @@ -2624,34 +2624,34 @@ describe('scan', function() { }) }) - it('should scan by IN on type N', function(done) { - var item = {a: {S: helpers.randomString()}, b: {S: '1234'}, c: {S: helpers.randomString()}}, - item2 = {a: {S: helpers.randomString()}, b: {NS: ['1234']}, c: item.c}, - item3 = {a: {S: helpers.randomString()}, b: {B: Buffer.from('1234').toString('base64')}, c: item.c}, - item4 = {a: {S: helpers.randomString()}, b: {N: '1234'}, c: item.c}, - item5 = {a: {S: helpers.randomString()}, b: {N: '123.45'}, c: item.c}, - batchReq = {RequestItems: {}} + it('should scan by IN on type N', function (done) { + var item = { a: { S: helpers.randomString() }, b: { S: '1234' }, c: { S: helpers.randomString() } }, + item2 = { a: { S: helpers.randomString() }, b: { NS: [ '1234' ] }, c: item.c }, + item3 = { a: { S: helpers.randomString() }, b: { B: Buffer.from('1234').toString('base64') }, c: item.c }, + item4 = { a: { S: helpers.randomString() }, b: { N: '1234' }, c: item.c }, + item5 = { a: { S: helpers.randomString() }, b: { N: '123.45' }, c: item.c }, + batchReq = { RequestItems: {} } batchReq.RequestItems[helpers.testHashTable] = [ - {PutRequest: {Item: item}}, - {PutRequest: {Item: item2}}, - {PutRequest: {Item: item3}}, - {PutRequest: {Item: item4}}, - {PutRequest: {Item: item5}}, + { PutRequest: { Item: item } }, + { PutRequest: { Item: item2 } }, + { PutRequest: { Item: item3 } }, + { PutRequest: { Item: item4 } }, + { PutRequest: { Item: item5 } }, ] - request(helpers.opts('BatchWriteItem', batchReq), function(err, res) { + request(helpers.opts('BatchWriteItem', batchReq), function (err, res) { if (err) return done(err) res.statusCode.should.equal(200) - async.forEach([{ + async.forEach([ { ScanFilter: { - b: {ComparisonOperator: 'IN', AttributeValueList: [item4.b, item5.b]}, - c: {ComparisonOperator: 'EQ', AttributeValueList: [item.c]}, + b: { ComparisonOperator: 'IN', AttributeValueList: [ item4.b, item5.b ] }, + c: { ComparisonOperator: 'EQ', AttributeValueList: [ item.c ] }, }, }, { FilterExpression: 'b IN (:b, :d) AND c = :c', - ExpressionAttributeValues: {':b': item4.b, ':c': item.c, ':d': item5.b}, - }], function(scanOpts, cb) { + ExpressionAttributeValues: { ':b': item4.b, ':c': item.c, ':d': item5.b }, + } ], function (scanOpts, cb) { scanOpts.TableName = helpers.testHashTable - request(opts(scanOpts), function(err, res) { + request(opts(scanOpts), function (err, res) { if (err) return cb(err) res.statusCode.should.equal(200) res.body.Items.should.containEql(item4) @@ -2664,34 +2664,34 @@ describe('scan', function() { }) }) - it('should scan by IN on type B', function(done) { - var item = {a: {S: helpers.randomString()}, b: {S: '1234'}, c: {S: helpers.randomString()}}, - item2 = {a: {S: helpers.randomString()}, b: {BS: [Buffer.from('1234').toString('base64')]}, c: item.c}, - item3 = {a: {S: helpers.randomString()}, b: {B: Buffer.from('1234').toString('base64')}, c: item.c}, - item4 = {a: {S: helpers.randomString()}, b: {N: '1234'}, c: item.c}, - item5 = {a: {S: helpers.randomString()}, b: {B: Buffer.from('12345').toString('base64')}, c: item.c}, - batchReq = {RequestItems: {}} + it('should scan by IN on type B', function (done) { + var item = { a: { S: helpers.randomString() }, b: { S: '1234' }, c: { S: helpers.randomString() } }, + item2 = { a: { S: helpers.randomString() }, b: { BS: [ Buffer.from('1234').toString('base64') ] }, c: item.c }, + item3 = { a: { S: helpers.randomString() }, b: { B: Buffer.from('1234').toString('base64') }, c: item.c }, + item4 = { a: { S: helpers.randomString() }, b: { N: '1234' }, c: item.c }, + item5 = { a: { S: helpers.randomString() }, b: { B: Buffer.from('12345').toString('base64') }, c: item.c }, + batchReq = { RequestItems: {} } batchReq.RequestItems[helpers.testHashTable] = [ - {PutRequest: {Item: item}}, - {PutRequest: {Item: item2}}, - {PutRequest: {Item: item3}}, - {PutRequest: {Item: item4}}, - {PutRequest: {Item: item5}}, + { PutRequest: { Item: item } }, + { PutRequest: { Item: item2 } }, + { PutRequest: { Item: item3 } }, + { PutRequest: { Item: item4 } }, + { PutRequest: { Item: item5 } }, ] - request(helpers.opts('BatchWriteItem', batchReq), function(err, res) { + request(helpers.opts('BatchWriteItem', batchReq), function (err, res) { if (err) return done(err) res.statusCode.should.equal(200) - async.forEach([{ + async.forEach([ { ScanFilter: { - b: {ComparisonOperator: 'IN', AttributeValueList: [item3.b, item5.b]}, - c: {ComparisonOperator: 'EQ', AttributeValueList: [item.c]}, + b: { ComparisonOperator: 'IN', AttributeValueList: [ item3.b, item5.b ] }, + c: { ComparisonOperator: 'EQ', AttributeValueList: [ item.c ] }, }, }, { FilterExpression: 'b IN (:b, :d) AND c = :c', - ExpressionAttributeValues: {':b': item3.b, ':c': item.c, ':d': item5.b}, - }], function(scanOpts, cb) { + ExpressionAttributeValues: { ':b': item3.b, ':c': item.c, ':d': item5.b }, + } ], function (scanOpts, cb) { scanOpts.TableName = helpers.testHashTable - request(opts(scanOpts), function(err, res) { + request(opts(scanOpts), function (err, res) { if (err) return cb(err) res.statusCode.should.equal(200) res.body.Items.should.containEql(item3) @@ -2704,34 +2704,34 @@ describe('scan', function() { }) }) - it('should scan by BETWEEN on type S', function(done) { - var item = {a: {S: helpers.randomString()}, b: {S: 'abc'}, c: {S: helpers.randomString()}}, - item2 = {a: {S: helpers.randomString()}, b: {S: 'abd'}, c: item.c}, - item3 = {a: {S: helpers.randomString()}, b: {S: 'abd\x00'}, c: item.c}, - item4 = {a: {S: helpers.randomString()}, b: {S: 'abe'}, c: item.c}, - item5 = {a: {S: helpers.randomString()}, b: {S: 'abe\x00'}, c: item.c}, - batchReq = {RequestItems: {}} + it('should scan by BETWEEN on type S', function (done) { + var item = { a: { S: helpers.randomString() }, b: { S: 'abc' }, c: { S: helpers.randomString() } }, + item2 = { a: { S: helpers.randomString() }, b: { S: 'abd' }, c: item.c }, + item3 = { a: { S: helpers.randomString() }, b: { S: 'abd\x00' }, c: item.c }, + item4 = { a: { S: helpers.randomString() }, b: { S: 'abe' }, c: item.c }, + item5 = { a: { S: helpers.randomString() }, b: { S: 'abe\x00' }, c: item.c }, + batchReq = { RequestItems: {} } batchReq.RequestItems[helpers.testHashTable] = [ - {PutRequest: {Item: item}}, - {PutRequest: {Item: item2}}, - {PutRequest: {Item: item3}}, - {PutRequest: {Item: item4}}, - {PutRequest: {Item: item5}}, + { PutRequest: { Item: item } }, + { PutRequest: { Item: item2 } }, + { PutRequest: { Item: item3 } }, + { PutRequest: { Item: item4 } }, + { PutRequest: { Item: item5 } }, ] - request(helpers.opts('BatchWriteItem', batchReq), function(err, res) { + request(helpers.opts('BatchWriteItem', batchReq), function (err, res) { if (err) return done(err) res.statusCode.should.equal(200) - async.forEach([{ + async.forEach([ { ScanFilter: { - b: {ComparisonOperator: 'BETWEEN', AttributeValueList: [item2.b, item4.b]}, - c: {ComparisonOperator: 'EQ', AttributeValueList: [item.c]}, + b: { ComparisonOperator: 'BETWEEN', AttributeValueList: [ item2.b, item4.b ] }, + c: { ComparisonOperator: 'EQ', AttributeValueList: [ item.c ] }, }, }, { FilterExpression: 'b BETWEEN :b AND :d AND c = :c', - ExpressionAttributeValues: {':b': item2.b, ':c': item.c, ':d': item4.b}, - }], function(scanOpts, cb) { + ExpressionAttributeValues: { ':b': item2.b, ':c': item.c, ':d': item4.b }, + } ], function (scanOpts, cb) { scanOpts.TableName = helpers.testHashTable - request(opts(scanOpts), function(err, res) { + request(opts(scanOpts), function (err, res) { if (err) return cb(err) res.statusCode.should.equal(200) res.body.Items.should.containEql(item2) @@ -2745,34 +2745,34 @@ describe('scan', function() { }) }) - it('should scan by BETWEEN on type N', function(done) { - var item = {a: {S: helpers.randomString()}, b: {N: '123'}, c: {S: helpers.randomString()}}, - item2 = {a: {S: helpers.randomString()}, b: {N: '124'}, c: item.c}, - item3 = {a: {S: helpers.randomString()}, b: {N: '124.99999'}, c: item.c}, - item4 = {a: {S: helpers.randomString()}, b: {N: '125'}, c: item.c}, - item5 = {a: {S: helpers.randomString()}, b: {N: '125.000001'}, c: item.c}, - batchReq = {RequestItems: {}} + it('should scan by BETWEEN on type N', function (done) { + var item = { a: { S: helpers.randomString() }, b: { N: '123' }, c: { S: helpers.randomString() } }, + item2 = { a: { S: helpers.randomString() }, b: { N: '124' }, c: item.c }, + item3 = { a: { S: helpers.randomString() }, b: { N: '124.99999' }, c: item.c }, + item4 = { a: { S: helpers.randomString() }, b: { N: '125' }, c: item.c }, + item5 = { a: { S: helpers.randomString() }, b: { N: '125.000001' }, c: item.c }, + batchReq = { RequestItems: {} } batchReq.RequestItems[helpers.testHashTable] = [ - {PutRequest: {Item: item}}, - {PutRequest: {Item: item2}}, - {PutRequest: {Item: item3}}, - {PutRequest: {Item: item4}}, - {PutRequest: {Item: item5}}, + { PutRequest: { Item: item } }, + { PutRequest: { Item: item2 } }, + { PutRequest: { Item: item3 } }, + { PutRequest: { Item: item4 } }, + { PutRequest: { Item: item5 } }, ] - request(helpers.opts('BatchWriteItem', batchReq), function(err, res) { + request(helpers.opts('BatchWriteItem', batchReq), function (err, res) { if (err) return done(err) res.statusCode.should.equal(200) - async.forEach([{ + async.forEach([ { ScanFilter: { - b: {ComparisonOperator: 'BETWEEN', AttributeValueList: [item2.b, item4.b]}, - c: {ComparisonOperator: 'EQ', AttributeValueList: [item.c]}, + b: { ComparisonOperator: 'BETWEEN', AttributeValueList: [ item2.b, item4.b ] }, + c: { ComparisonOperator: 'EQ', AttributeValueList: [ item.c ] }, }, }, { FilterExpression: 'b BETWEEN :b AND :d AND c = :c', - ExpressionAttributeValues: {':b': item2.b, ':c': item.c, ':d': item4.b}, - }], function(scanOpts, cb) { + ExpressionAttributeValues: { ':b': item2.b, ':c': item.c, ':d': item4.b }, + } ], function (scanOpts, cb) { scanOpts.TableName = helpers.testHashTable - request(opts(scanOpts), function(err, res) { + request(opts(scanOpts), function (err, res) { if (err) return cb(err) res.statusCode.should.equal(200) res.body.Items.should.containEql(item2) @@ -2786,34 +2786,34 @@ describe('scan', function() { }) }) - it('should scan by BETWEEN on type B', function(done) { - var item = {a: {S: helpers.randomString()}, b: {B: Buffer.from('ce', 'hex').toString('base64')}, c: {S: helpers.randomString()}}, - item2 = {a: {S: helpers.randomString()}, b: {B: Buffer.from('d0', 'hex').toString('base64')}, c: item.c}, - item3 = {a: {S: helpers.randomString()}, b: {B: Buffer.from('cf', 'hex').toString('base64')}, c: item.c}, - item4 = {a: {S: helpers.randomString()}, b: {B: Buffer.from('d000', 'hex').toString('base64')}, c: item.c}, - item5 = {a: {S: helpers.randomString()}, b: {B: Buffer.from('cfff', 'hex').toString('base64')}, c: item.c}, - batchReq = {RequestItems: {}} + it('should scan by BETWEEN on type B', function (done) { + var item = { a: { S: helpers.randomString() }, b: { B: Buffer.from('ce', 'hex').toString('base64') }, c: { S: helpers.randomString() } }, + item2 = { a: { S: helpers.randomString() }, b: { B: Buffer.from('d0', 'hex').toString('base64') }, c: item.c }, + item3 = { a: { S: helpers.randomString() }, b: { B: Buffer.from('cf', 'hex').toString('base64') }, c: item.c }, + item4 = { a: { S: helpers.randomString() }, b: { B: Buffer.from('d000', 'hex').toString('base64') }, c: item.c }, + item5 = { a: { S: helpers.randomString() }, b: { B: Buffer.from('cfff', 'hex').toString('base64') }, c: item.c }, + batchReq = { RequestItems: {} } batchReq.RequestItems[helpers.testHashTable] = [ - {PutRequest: {Item: item}}, - {PutRequest: {Item: item2}}, - {PutRequest: {Item: item3}}, - {PutRequest: {Item: item4}}, - {PutRequest: {Item: item5}}, + { PutRequest: { Item: item } }, + { PutRequest: { Item: item2 } }, + { PutRequest: { Item: item3 } }, + { PutRequest: { Item: item4 } }, + { PutRequest: { Item: item5 } }, ] - request(helpers.opts('BatchWriteItem', batchReq), function(err, res) { + request(helpers.opts('BatchWriteItem', batchReq), function (err, res) { if (err) return done(err) res.statusCode.should.equal(200) - async.forEach([{ + async.forEach([ { ScanFilter: { - b: {ComparisonOperator: 'BETWEEN', AttributeValueList: [item5.b, item4.b]}, - c: {ComparisonOperator: 'EQ', AttributeValueList: [item.c]}, + b: { ComparisonOperator: 'BETWEEN', AttributeValueList: [ item5.b, item4.b ] }, + c: { ComparisonOperator: 'EQ', AttributeValueList: [ item.c ] }, }, }, { FilterExpression: 'b BETWEEN :b AND :d AND c = :c', - ExpressionAttributeValues: {':b': item5.b, ':c': item.c, ':d': item4.b}, - }], function(scanOpts, cb) { + ExpressionAttributeValues: { ':b': item5.b, ':c': item.c, ':d': item4.b }, + } ], function (scanOpts, cb) { scanOpts.TableName = helpers.testHashTable - request(opts(scanOpts), function(err, res) { + request(opts(scanOpts), function (err, res) { if (err) return cb(err) res.statusCode.should.equal(200) res.body.Items.should.containEql(item2) @@ -2827,35 +2827,35 @@ describe('scan', function() { }) }) - it('should scan by nested properties', function(done) { - var item = {a: {S: helpers.randomString()}, b: {M: {a: {M: {b: {S: helpers.randomString()}}}}}, c: {N: helpers.randomNumber()}} - var item2 = {a: {S: helpers.randomString()}, b: {L: [{S: helpers.randomString()}, item.b]}, c: item.c} - var item3 = {a: {S: helpers.randomString()}, b: item.b, c: {N: helpers.randomNumber()}} - var item4 = {a: {S: helpers.randomString()}, b: {S: helpers.randomString()}, c: item.c} - var item5 = {a: {S: helpers.randomString()}, c: item.c} - var batchReq = {RequestItems: {}} + it('should scan by nested properties', function (done) { + var item = { a: { S: helpers.randomString() }, b: { M: { a: { M: { b: { S: helpers.randomString() } } } } }, c: { N: helpers.randomNumber() } } + var item2 = { a: { S: helpers.randomString() }, b: { L: [ { S: helpers.randomString() }, item.b ] }, c: item.c } + var item3 = { a: { S: helpers.randomString() }, b: item.b, c: { N: helpers.randomNumber() } } + var item4 = { a: { S: helpers.randomString() }, b: { S: helpers.randomString() }, c: item.c } + var item5 = { a: { S: helpers.randomString() }, c: item.c } + var batchReq = { RequestItems: {} } batchReq.RequestItems[helpers.testHashTable] = [ - {PutRequest: {Item: item}}, - {PutRequest: {Item: item2}}, - {PutRequest: {Item: item3}}, - {PutRequest: {Item: item4}}, - {PutRequest: {Item: item5}}, + { PutRequest: { Item: item } }, + { PutRequest: { Item: item2 } }, + { PutRequest: { Item: item3 } }, + { PutRequest: { Item: item4 } }, + { PutRequest: { Item: item5 } }, ] - request(helpers.opts('BatchWriteItem', batchReq), function(err, res) { + request(helpers.opts('BatchWriteItem', batchReq), function (err, res) { if (err) return done(err) res.statusCode.should.equal(200) - async.forEach([{ + async.forEach([ { FilterExpression: '(b[1].a.b = :b OR b.a.b = :b) AND c = :c', - ExpressionAttributeValues: {':b': item.b.M.a.M.b, ':c': item.c}, + ExpressionAttributeValues: { ':b': item.b.M.a.M.b, ':c': item.c }, }, { FilterExpression: '(attribute_exists(b.a) OR attribute_exists(b[1])) AND c = :c', - ExpressionAttributeValues: {':c': item.c}, + ExpressionAttributeValues: { ':c': item.c }, }, { FilterExpression: '(attribute_type(b.a, :m) OR attribute_type(b[1].a, :m)) AND c = :c', - ExpressionAttributeValues: {':c': item.c, ':m': {S: 'M'}}, - }], function(scanOpts, cb) { + ExpressionAttributeValues: { ':c': item.c, ':m': { S: 'M' } }, + } ], function (scanOpts, cb) { scanOpts.TableName = helpers.testHashTable - request(opts(scanOpts), function(err, res) { + request(opts(scanOpts), function (err, res) { if (err) return cb(err) res.statusCode.should.equal(200) res.body.Items.should.containEql(item) @@ -2868,39 +2868,39 @@ describe('scan', function() { }) }) - it('should calculate size function correctly', function(done) { - var item = {a: {S: helpers.randomString()}, b: {S: 'abÿ'}, c: {N: helpers.randomNumber()}} - var item2 = {a: {S: helpers.randomString()}, b: {N: '123'}, c: item.c} - var item3 = {a: {S: helpers.randomString()}, b: {B: 'YWJj'}, c: item.c} - var item4 = {a: {S: helpers.randomString()}, b: {SS: ['a', 'b', 'c']}, c: item.c} - var item5 = {a: {S: helpers.randomString()}, b: {L: [{S: 'a'}, {S: 'a'}, {S: 'a'}]}, c: item.c} - var item6 = {a: {S: helpers.randomString()}, b: {M: {a: {S: 'a'}, b: {S: 'a'}, c: {S: 'a'}}}, c: item.c} - var item7 = {a: {S: helpers.randomString()}, b: {S: 'abcd'}, c: item.c} - var batchReq = {RequestItems: {}} + it('should calculate size function correctly', function (done) { + var item = { a: { S: helpers.randomString() }, b: { S: 'abÿ' }, c: { N: helpers.randomNumber() } } + var item2 = { a: { S: helpers.randomString() }, b: { N: '123' }, c: item.c } + var item3 = { a: { S: helpers.randomString() }, b: { B: 'YWJj' }, c: item.c } + var item4 = { a: { S: helpers.randomString() }, b: { SS: [ 'a', 'b', 'c' ] }, c: item.c } + var item5 = { a: { S: helpers.randomString() }, b: { L: [ { S: 'a' }, { S: 'a' }, { S: 'a' } ] }, c: item.c } + var item6 = { a: { S: helpers.randomString() }, b: { M: { a: { S: 'a' }, b: { S: 'a' }, c: { S: 'a' } } }, c: item.c } + var item7 = { a: { S: helpers.randomString() }, b: { S: 'abcd' }, c: item.c } + var batchReq = { RequestItems: {} } batchReq.RequestItems[helpers.testHashTable] = [ - {PutRequest: {Item: item}}, - {PutRequest: {Item: item2}}, - {PutRequest: {Item: item3}}, - {PutRequest: {Item: item4}}, - {PutRequest: {Item: item5}}, - {PutRequest: {Item: item6}}, - {PutRequest: {Item: item7}}, + { PutRequest: { Item: item } }, + { PutRequest: { Item: item2 } }, + { PutRequest: { Item: item3 } }, + { PutRequest: { Item: item4 } }, + { PutRequest: { Item: item5 } }, + { PutRequest: { Item: item6 } }, + { PutRequest: { Item: item7 } }, ] - request(helpers.opts('BatchWriteItem', batchReq), function(err, res) { + request(helpers.opts('BatchWriteItem', batchReq), function (err, res) { if (err) return done(err) res.statusCode.should.equal(200) - async.forEach([{ + async.forEach([ { FilterExpression: 'size(b) = :b AND c = :c', - ExpressionAttributeValues: {':b': {N: '3'}, ':c': item.c}, + ExpressionAttributeValues: { ':b': { N: '3' }, ':c': item.c }, }, { FilterExpression: '(size(b)) = :b AND c = :c', - ExpressionAttributeValues: {':b': {N: '3'}, ':c': item.c}, + ExpressionAttributeValues: { ':b': { N: '3' }, ':c': item.c }, }, { FilterExpression: '((size(b)) = :b) AND c = :c', - ExpressionAttributeValues: {':b': {N: '3'}, ':c': item.c}, - }], function(scanOpts, cb) { + ExpressionAttributeValues: { ':b': { N: '3' }, ':c': item.c }, + } ], function (scanOpts, cb) { scanOpts.TableName = helpers.testHashTable - request(opts(scanOpts), function(err, res) { + request(opts(scanOpts), function (err, res) { if (err) return cb(err) res.statusCode.should.equal(200) res.body.Items.should.containEql(item) @@ -2916,41 +2916,41 @@ describe('scan', function() { }) }) - it('should only return requested attributes', function(done) { - var item = {a: {S: helpers.randomString()}, b: {S: 'b1'}, c: {S: helpers.randomString()}, d: {S: 'd1'}}, - item2 = {a: {S: helpers.randomString()}, b: {S: 'b2'}, c: item.c}, - item3 = {a: {S: helpers.randomString()}, b: {S: 'b3'}, c: item.c, d: {S: 'd3'}, e: {S: 'e3'}}, - batchReq = {RequestItems: {}} + it('should only return requested attributes', function (done) { + var item = { a: { S: helpers.randomString() }, b: { S: 'b1' }, c: { S: helpers.randomString() }, d: { S: 'd1' } }, + item2 = { a: { S: helpers.randomString() }, b: { S: 'b2' }, c: item.c }, + item3 = { a: { S: helpers.randomString() }, b: { S: 'b3' }, c: item.c, d: { S: 'd3' }, e: { S: 'e3' } }, + batchReq = { RequestItems: {} } batchReq.RequestItems[helpers.testHashTable] = [ - {PutRequest: {Item: item}}, - {PutRequest: {Item: item2}}, - {PutRequest: {Item: item3}}, + { PutRequest: { Item: item } }, + { PutRequest: { Item: item2 } }, + { PutRequest: { Item: item3 } }, ] - request(helpers.opts('BatchWriteItem', batchReq), function(err, res) { + request(helpers.opts('BatchWriteItem', batchReq), function (err, res) { if (err) return done(err) res.statusCode.should.equal(200) - async.forEach([{ + async.forEach([ { ScanFilter: { - c: {ComparisonOperator: 'EQ', AttributeValueList: [item.c]}, + c: { ComparisonOperator: 'EQ', AttributeValueList: [ item.c ] }, }, - AttributesToGet: ['b', 'd'], + AttributesToGet: [ 'b', 'd' ], }, { FilterExpression: 'c = :c', - ExpressionAttributeValues: {':c': item.c}, + ExpressionAttributeValues: { ':c': item.c }, ProjectionExpression: 'b, d', }, { FilterExpression: 'c = :c', - ExpressionAttributeValues: {':c': item.c}, - ExpressionAttributeNames: {'#b': 'b', '#d': 'd'}, + ExpressionAttributeValues: { ':c': item.c }, + ExpressionAttributeNames: { '#b': 'b', '#d': 'd' }, ProjectionExpression: '#b, #d', - }], function(scanOpts, cb) { + } ], function (scanOpts, cb) { scanOpts.TableName = helpers.testHashTable - request(opts(scanOpts), function(err, res) { + request(opts(scanOpts), function (err, res) { if (err) return cb(err) res.statusCode.should.equal(200) - res.body.Items.should.containEql({b: {S: 'b1'}, d: {S: 'd1'}}) - res.body.Items.should.containEql({b: {S: 'b2'}}) - res.body.Items.should.containEql({b: {S: 'b3'}, d: {S: 'd3'}}) + res.body.Items.should.containEql({ b: { S: 'b1' }, d: { S: 'd1' } }) + res.body.Items.should.containEql({ b: { S: 'b2' } }) + res.body.Items.should.containEql({ b: { S: 'b3' }, d: { S: 'd3' } }) res.body.Items.should.have.length(3) res.body.Count.should.equal(3) cb() @@ -2959,27 +2959,27 @@ describe('scan', function() { }) }) - it('should return COUNT if requested', function(done) { - var item = {a: {S: helpers.randomString()}, b: {S: '1'}, c: {S: helpers.randomString()}}, - item2 = {a: {S: helpers.randomString()}, b: {N: '1'}, c: item.c}, - item3 = {a: {S: helpers.randomString()}, b: {S: '1'}, c: item.c}, - item4 = {a: {S: helpers.randomString()}, c: item.c}, - item5 = {a: {S: helpers.randomString()}, b: {S: '2'}, c: item.c}, - batchReq = {RequestItems: {}} + it('should return COUNT if requested', function (done) { + var item = { a: { S: helpers.randomString() }, b: { S: '1' }, c: { S: helpers.randomString() } }, + item2 = { a: { S: helpers.randomString() }, b: { N: '1' }, c: item.c }, + item3 = { a: { S: helpers.randomString() }, b: { S: '1' }, c: item.c }, + item4 = { a: { S: helpers.randomString() }, c: item.c }, + item5 = { a: { S: helpers.randomString() }, b: { S: '2' }, c: item.c }, + batchReq = { RequestItems: {} } batchReq.RequestItems[helpers.testHashTable] = [ - {PutRequest: {Item: item}}, - {PutRequest: {Item: item2}}, - {PutRequest: {Item: item3}}, - {PutRequest: {Item: item4}}, - {PutRequest: {Item: item5}}, + { PutRequest: { Item: item } }, + { PutRequest: { Item: item2 } }, + { PutRequest: { Item: item3 } }, + { PutRequest: { Item: item4 } }, + { PutRequest: { Item: item5 } }, ] - request(helpers.opts('BatchWriteItem', batchReq), function(err, res) { + request(helpers.opts('BatchWriteItem', batchReq), function (err, res) { if (err) return done(err) res.statusCode.should.equal(200) - request(opts({TableName: helpers.testHashTable, ScanFilter: { - b: {ComparisonOperator: 'EQ', AttributeValueList: [item.b]}, - c: {ComparisonOperator: 'EQ', AttributeValueList: [item.c]}, - }, Select: 'COUNT'}), function(err, res) { + request(opts({ TableName: helpers.testHashTable, ScanFilter: { + b: { ComparisonOperator: 'EQ', AttributeValueList: [ item.b ] }, + c: { ComparisonOperator: 'EQ', AttributeValueList: [ item.c ] }, + }, Select: 'COUNT' }), function (err, res) { if (err) return done(err) res.statusCode.should.equal(200) should.not.exist(res.body.Items) @@ -2990,25 +2990,25 @@ describe('scan', function() { }) }) - it('should return after but not including ExclusiveStartKey', function(done) { - var i, b = {S: helpers.randomString()}, items = [], batchReq = {RequestItems: {}}, - scanFilter = {b: {ComparisonOperator: 'EQ', AttributeValueList: [b]}} + it('should return after but not including ExclusiveStartKey', function (done) { + var i, b = { S: helpers.randomString() }, items = [], batchReq = { RequestItems: {} }, + scanFilter = { b: { ComparisonOperator: 'EQ', AttributeValueList: [ b ] } } for (i = 0; i < 10; i++) - items.push({a: {S: String(i)}, b: b}) + items.push({ a: { S: String(i) }, b: b }) - batchReq.RequestItems[helpers.testHashTable] = items.map(function(item) { return {PutRequest: {Item: item}} }) + batchReq.RequestItems[helpers.testHashTable] = items.map(function (item) { return { PutRequest: { Item: item } } }) - request(helpers.opts('BatchWriteItem', batchReq), function(err, res) { + request(helpers.opts('BatchWriteItem', batchReq), function (err, res) { if (err) return done(err) res.statusCode.should.equal(200) - request(opts({TableName: helpers.testHashTable, ScanFilter: scanFilter}), function(err, res) { + request(opts({ TableName: helpers.testHashTable, ScanFilter: scanFilter }), function (err, res) { if (err) return done(err) res.statusCode.should.equal(200) res.body.Count.should.equal(10) - request(opts({TableName: helpers.testHashTable, ScanFilter: scanFilter, ExclusiveStartKey: {a: res.body.Items[0].a}}), function(err, res) { + request(opts({ TableName: helpers.testHashTable, ScanFilter: scanFilter, ExclusiveStartKey: { a: res.body.Items[0].a } }), function (err, res) { if (err) return done(err) res.statusCode.should.equal(200) res.body.Count.should.equal(9) @@ -3018,13 +3018,13 @@ describe('scan', function() { }) }) - it('should succeed even if ExclusiveStartKey does not match scan filter', function(done) { - var hashes = [helpers.randomString(), helpers.randomString()].sort() + it('should succeed even if ExclusiveStartKey does not match scan filter', function (done) { + var hashes = [ helpers.randomString(), helpers.randomString() ].sort() request(opts({ TableName: helpers.testHashTable, - ExclusiveStartKey: {a: {S: hashes[1]}}, - ScanFilter: {a: {ComparisonOperator: 'EQ', AttributeValueList: [{S: hashes[0]}]}}, - }), function(err, res) { + ExclusiveStartKey: { a: { S: hashes[1] } }, + ScanFilter: { a: { ComparisonOperator: 'EQ', AttributeValueList: [ { S: hashes[0] } ] } }, + }), function (err, res) { if (err) return done(err) res.statusCode.should.equal(200) res.body.Count.should.equal(0) @@ -3033,19 +3033,19 @@ describe('scan', function() { }) }) - it('should return LastEvaluatedKey if Limit not reached', function(done) { - var i, b = {S: helpers.randomString()}, items = [], batchReq = {RequestItems: {}} + it('should return LastEvaluatedKey if Limit not reached', function (done) { + var i, b = { S: helpers.randomString() }, items = [], batchReq = { RequestItems: {} } for (i = 0; i < 5; i++) - items.push({a: {S: String(i)}, b: b}) + items.push({ a: { S: String(i) }, b: b }) - batchReq.RequestItems[helpers.testHashTable] = items.map(function(item) { return {PutRequest: {Item: item}} }) + batchReq.RequestItems[helpers.testHashTable] = items.map(function (item) { return { PutRequest: { Item: item } } }) - request(helpers.opts('BatchWriteItem', batchReq), function(err, res) { + request(helpers.opts('BatchWriteItem', batchReq), function (err, res) { if (err) return done(err) res.statusCode.should.equal(200) - request(opts({TableName: helpers.testHashTable, Limit: 3, ReturnConsumedCapacity: 'INDEXES'}), function(err, res) { + request(opts({ TableName: helpers.testHashTable, Limit: 3, ReturnConsumedCapacity: 'INDEXES' }), function (err, res) { if (err) return done(err) res.statusCode.should.equal(200) res.body.ScannedCount.should.equal(3) @@ -3056,19 +3056,19 @@ describe('scan', function() { }) }) - it('should return LastEvaluatedKey even if selecting Count', function(done) { - var i, b = {S: helpers.randomString()}, items = [], batchReq = {RequestItems: {}} + it('should return LastEvaluatedKey even if selecting Count', function (done) { + var i, b = { S: helpers.randomString() }, items = [], batchReq = { RequestItems: {} } for (i = 0; i < 5; i++) - items.push({a: {S: String(i)}, b: b}) + items.push({ a: { S: String(i) }, b: b }) - batchReq.RequestItems[helpers.testHashTable] = items.map(function(item) { return {PutRequest: {Item: item}} }) + batchReq.RequestItems[helpers.testHashTable] = items.map(function (item) { return { PutRequest: { Item: item } } }) - request(helpers.opts('BatchWriteItem', batchReq), function(err, res) { + request(helpers.opts('BatchWriteItem', batchReq), function (err, res) { if (err) return done(err) res.statusCode.should.equal(200) - request(opts({TableName: helpers.testHashTable, Limit: 3, Select: 'COUNT'}), function(err, res) { + request(opts({ TableName: helpers.testHashTable, Limit: 3, Select: 'COUNT' }), function (err, res) { if (err) return done(err) res.statusCode.should.equal(200) res.body.ScannedCount.should.equal(3) @@ -3079,8 +3079,8 @@ describe('scan', function() { }) }) - it('should return LastEvaluatedKey while filtering, even if Limit is smaller than the expected return list', function(done) { - var i, items = [], batchReq = {RequestItems: {}} + it('should return LastEvaluatedKey while filtering, even if Limit is smaller than the expected return list', function (done) { + var i, items = [], batchReq = { RequestItems: {} } // This bug manifests itself when the sought after item is not among the first .Limit number of // items in the scan. Because we can't guarantee the order of the returned scan items, we can't @@ -3090,21 +3090,21 @@ describe('scan', function() { // of items should be small enough to give us practical assurance of correctness in this one // regard... for (i = 0; i < 25; i++) - items.push({a: {S: 'item' + i}}) + items.push({ a: { S: 'item' + i } }) - batchReq.RequestItems[helpers.testHashTable] = items.map(function(item) { return {PutRequest: {Item: item}} }) + batchReq.RequestItems[helpers.testHashTable] = items.map(function (item) { return { PutRequest: { Item: item } } }) - request(helpers.opts('BatchWriteItem', batchReq), function(err, res) { + request(helpers.opts('BatchWriteItem', batchReq), function (err, res) { if (err) return done(err) res.statusCode.should.equal(200) request(opts({ TableName: helpers.testHashTable, - ExpressionAttributeNames: {'#key': 'a'}, - ExpressionAttributeValues: {':value': {S: 'item12'}}, + ExpressionAttributeNames: { '#key': 'a' }, + ExpressionAttributeValues: { ':value': { S: 'item12' } }, FilterExpression: '#key = :value', Limit: 2, - }), function(err, res) { + }), function (err, res) { if (err) return done(err) res.statusCode.should.equal(200) @@ -3116,20 +3116,20 @@ describe('scan', function() { }) }) - it('should not return LastEvaluatedKey if Limit is large', function(done) { - var i, b = {S: helpers.randomString()}, items = [], batchReq = {RequestItems: {}}, - scanFilter = {b: {ComparisonOperator: 'EQ', AttributeValueList: [b]}} + it('should not return LastEvaluatedKey if Limit is large', function (done) { + var i, b = { S: helpers.randomString() }, items = [], batchReq = { RequestItems: {} }, + scanFilter = { b: { ComparisonOperator: 'EQ', AttributeValueList: [ b ] } } for (i = 0; i < 5; i++) - items.push({a: {S: String(i)}, b: b}) + items.push({ a: { S: String(i) }, b: b }) - batchReq.RequestItems[helpers.testHashTable] = items.map(function(item) { return {PutRequest: {Item: item}} }) + batchReq.RequestItems[helpers.testHashTable] = items.map(function (item) { return { PutRequest: { Item: item } } }) - request(helpers.opts('BatchWriteItem', batchReq), function(err, res) { + request(helpers.opts('BatchWriteItem', batchReq), function (err, res) { if (err) return done(err) res.statusCode.should.equal(200) - request(opts({TableName: helpers.testHashTable, AttributesToGet: ['a', 'b'], Limit: 100000}), function(err, res) { + request(opts({ TableName: helpers.testHashTable, AttributesToGet: [ 'a', 'b' ], Limit: 100000 }), function (err, res) { if (err) return done(err) res.statusCode.should.equal(200) res.body.Count.should.equal(res.body.ScannedCount) @@ -3138,22 +3138,22 @@ describe('scan', function() { if (res.body.Items[i].b.S == b.S) lastIx = i } var totalItems = res.body.Count - request(opts({TableName: helpers.testHashTable, ScanFilter: scanFilter, Limit: lastIx}), function(err, res) { + request(opts({ TableName: helpers.testHashTable, ScanFilter: scanFilter, Limit: lastIx }), function (err, res) { if (err) return done(err) res.statusCode.should.equal(200) res.body.Count.should.equal(4) res.body.LastEvaluatedKey.a.S.should.not.be.empty // eslint-disable-line no-unused-expressions - request(opts({TableName: helpers.testHashTable, ScanFilter: scanFilter, Limit: lastIx + 1}), function(err, res) { + request(opts({ TableName: helpers.testHashTable, ScanFilter: scanFilter, Limit: lastIx + 1 }), function (err, res) { if (err) return done(err) res.statusCode.should.equal(200) res.body.Count.should.equal(5) res.body.LastEvaluatedKey.a.S.should.not.be.empty // eslint-disable-line no-unused-expressions - request(opts({TableName: helpers.testHashTable, ScanFilter: scanFilter, Limit: totalItems}), function(err, res) { + request(opts({ TableName: helpers.testHashTable, ScanFilter: scanFilter, Limit: totalItems }), function (err, res) { if (err) return done(err) res.statusCode.should.equal(200) res.body.Count.should.equal(5) res.body.LastEvaluatedKey.a.S.should.not.be.empty // eslint-disable-line no-unused-expressions - request(opts({TableName: helpers.testHashTable, ScanFilter: scanFilter, Limit: totalItems + 1}), function(err, res) { + request(opts({ TableName: helpers.testHashTable, ScanFilter: scanFilter, Limit: totalItems + 1 }), function (err, res) { if (err) return done(err) res.statusCode.should.equal(200) res.body.Count.should.equal(5) @@ -3167,28 +3167,28 @@ describe('scan', function() { }) }) - it('should return items in same segment order', function(done) { - var i, b = {S: helpers.randomString()}, items = [], - firstHalf, secondHalf, batchReq = {RequestItems: {}}, - scanFilter = {b: {ComparisonOperator: 'EQ', AttributeValueList: [b]}} + it('should return items in same segment order', function (done) { + var i, b = { S: helpers.randomString() }, items = [], + firstHalf, secondHalf, batchReq = { RequestItems: {} }, + scanFilter = { b: { ComparisonOperator: 'EQ', AttributeValueList: [ b ] } } for (i = 0; i < 20; i++) - items.push({a: {S: String(i)}, b: b}) + items.push({ a: { S: String(i) }, b: b }) - batchReq.RequestItems[helpers.testHashTable] = items.map(function(item) { return {PutRequest: {Item: item}} }) + batchReq.RequestItems[helpers.testHashTable] = items.map(function (item) { return { PutRequest: { Item: item } } }) - request(helpers.opts('BatchWriteItem', batchReq), function(err, res) { + request(helpers.opts('BatchWriteItem', batchReq), function (err, res) { if (err) return done(err) res.statusCode.should.equal(200) - request(opts({TableName: helpers.testHashTable, Segment: 0, TotalSegments: 2, ScanFilter: scanFilter}), function(err, res) { + request(opts({ TableName: helpers.testHashTable, Segment: 0, TotalSegments: 2, ScanFilter: scanFilter }), function (err, res) { if (err) return done(err) res.statusCode.should.equal(200) res.body.Count.should.be.above(0) firstHalf = res.body.Items - request(opts({TableName: helpers.testHashTable, Segment: 1, TotalSegments: 2, ScanFilter: scanFilter}), function(err, res) { + request(opts({ TableName: helpers.testHashTable, Segment: 1, TotalSegments: 2, ScanFilter: scanFilter }), function (err, res) { if (err) return done(err) res.statusCode.should.equal(200) res.body.Count.should.be.above(0) @@ -3197,29 +3197,29 @@ describe('scan', function() { secondHalf.should.have.length(items.length - firstHalf.length) - request(opts({TableName: helpers.testHashTable, Segment: 0, TotalSegments: 4, ScanFilter: scanFilter}), function(err, res) { + request(opts({ TableName: helpers.testHashTable, Segment: 0, TotalSegments: 4, ScanFilter: scanFilter }), function (err, res) { if (err) return done(err) res.statusCode.should.equal(200) - res.body.Items.forEach(function(item) { firstHalf.should.containEql(item) }) + res.body.Items.forEach(function (item) { firstHalf.should.containEql(item) }) - request(opts({TableName: helpers.testHashTable, Segment: 1, TotalSegments: 4, ScanFilter: scanFilter}), function(err, res) { + request(opts({ TableName: helpers.testHashTable, Segment: 1, TotalSegments: 4, ScanFilter: scanFilter }), function (err, res) { if (err) return done(err) res.statusCode.should.equal(200) - res.body.Items.forEach(function(item) { firstHalf.should.containEql(item) }) + res.body.Items.forEach(function (item) { firstHalf.should.containEql(item) }) - request(opts({TableName: helpers.testHashTable, Segment: 2, TotalSegments: 4, ScanFilter: scanFilter}), function(err, res) { + request(opts({ TableName: helpers.testHashTable, Segment: 2, TotalSegments: 4, ScanFilter: scanFilter }), function (err, res) { if (err) return done(err) res.statusCode.should.equal(200) - res.body.Items.forEach(function(item) { secondHalf.should.containEql(item) }) + res.body.Items.forEach(function (item) { secondHalf.should.containEql(item) }) - request(opts({TableName: helpers.testHashTable, Segment: 3, TotalSegments: 4, ScanFilter: scanFilter}), function(err, res) { + request(opts({ TableName: helpers.testHashTable, Segment: 3, TotalSegments: 4, ScanFilter: scanFilter }), function (err, res) { if (err) return done(err) res.statusCode.should.equal(200) - res.body.Items.forEach(function(item) { secondHalf.should.containEql(item) }) + res.body.Items.forEach(function (item) { secondHalf.should.containEql(item) }) done() }) @@ -3232,91 +3232,91 @@ describe('scan', function() { }) // XXX: This is very brittle, relies on knowing the hashing scheme - it('should return items in string hash order', function(done) { - var i, b = {S: helpers.randomString()}, items = [], - batchReq = {RequestItems: {}}, - scanFilter = {b: {ComparisonOperator: 'EQ', AttributeValueList: [b]}} + it('should return items in string hash order', function (done) { + var i, b = { S: helpers.randomString() }, items = [], + batchReq = { RequestItems: {} }, + scanFilter = { b: { ComparisonOperator: 'EQ', AttributeValueList: [ b ] } } for (i = 0; i < 10; i++) - items.push({a: {S: String(i)}, b: b}) + items.push({ a: { S: String(i) }, b: b }) - items.push({a: {S: 'aardman'}, b: b}) - items.push({a: {S: 'hello'}, b: b}) - items.push({a: {S: 'zapf'}, b: b}) - items.push({a: {S: 'äáöü'}, b: b}) + items.push({ a: { S: 'aardman' }, b: b }) + items.push({ a: { S: 'hello' }, b: b }) + items.push({ a: { S: 'zapf' }, b: b }) + items.push({ a: { S: 'äáöü' }, b: b }) - batchReq.RequestItems[helpers.testHashTable] = items.map(function(item) { return {PutRequest: {Item: item}} }) + batchReq.RequestItems[helpers.testHashTable] = items.map(function (item) { return { PutRequest: { Item: item } } }) - request(helpers.opts('BatchWriteItem', batchReq), function(err, res) { + request(helpers.opts('BatchWriteItem', batchReq), function (err, res) { if (err) return done(err) res.statusCode.should.equal(200) - request(opts({TableName: helpers.testHashTable, ScanFilter: scanFilter}), function(err, res) { + request(opts({ TableName: helpers.testHashTable, ScanFilter: scanFilter }), function (err, res) { if (err) return done(err) res.statusCode.should.equal(200) res.body.Count.should.equal(14) - var keys = res.body.Items.map(function(item) { return item.a.S }) - keys.should.eql(['2', '8', '9', '1', '6', 'hello', '0', '5', '4', 'äáöü', 'aardman', '7', '3', 'zapf']) + var keys = res.body.Items.map(function (item) { return item.a.S }) + keys.should.eql([ '2', '8', '9', '1', '6', 'hello', '0', '5', '4', 'äáöü', 'aardman', '7', '3', 'zapf' ]) done() }) }) }) // XXX: This is very brittle, relies on knowing the hashing scheme - it('should return items in number hash order', function(done) { - var i, b = {S: helpers.randomString()}, items = [], - batchReq = {RequestItems: {}}, - scanFilter = {b: {ComparisonOperator: 'EQ', AttributeValueList: [b]}} + it('should return items in number hash order', function (done) { + var i, b = { S: helpers.randomString() }, items = [], + batchReq = { RequestItems: {} }, + scanFilter = { b: { ComparisonOperator: 'EQ', AttributeValueList: [ b ] } } for (i = 0; i < 10; i++) - items.push({a: {N: String(i)}, b: b}) + items.push({ a: { N: String(i) }, b: b }) - items.push({a: {N: '-0.09'}, b: b}) - items.push({a: {N: '999.9'}, b: b}) - items.push({a: {N: '0.012345'}, b: b}) - items.push({a: {N: '-999.9'}, b: b}) + items.push({ a: { N: '-0.09' }, b: b }) + items.push({ a: { N: '999.9' }, b: b }) + items.push({ a: { N: '0.012345' }, b: b }) + items.push({ a: { N: '-999.9' }, b: b }) - batchReq.RequestItems[helpers.testHashNTable] = items.map(function(item) { return {PutRequest: {Item: item}} }) + batchReq.RequestItems[helpers.testHashNTable] = items.map(function (item) { return { PutRequest: { Item: item } } }) - request(helpers.opts('BatchWriteItem', batchReq), function(err, res) { + request(helpers.opts('BatchWriteItem', batchReq), function (err, res) { if (err) return done(err) res.statusCode.should.equal(200) - request(opts({TableName: helpers.testHashNTable, ScanFilter: scanFilter}), function(err, res) { + request(opts({ TableName: helpers.testHashNTable, ScanFilter: scanFilter }), function (err, res) { if (err) return done(err) res.statusCode.should.equal(200) res.body.Count.should.equal(14) - var keys = res.body.Items.map(function(item) { return item.a.N }) - keys.should.eql(['7', '999.9', '8', '3', '2', '-999.9', '9', '4', '-0.09', '6', '1', '0', '0.012345', '5']) + var keys = res.body.Items.map(function (item) { return item.a.N }) + keys.should.eql([ '7', '999.9', '8', '3', '2', '-999.9', '9', '4', '-0.09', '6', '1', '0', '0.012345', '5' ]) done() }) }) }) // XXX: This is very brittle, relies on knowing the hashing scheme - it('should return items from correct string hash segments', function(done) { - var batchReq = {RequestItems: {}}, items = [ - {a: {S: '3635'}}, - {a: {S: '228'}}, - {a: {S: '1668'}}, - {a: {S: '3435'}}, + it('should return items from correct string hash segments', function (done) { + var batchReq = { RequestItems: {} }, items = [ + { a: { S: '3635' } }, + { a: { S: '228' } }, + { a: { S: '1668' } }, + { a: { S: '3435' } }, ] - batchReq.RequestItems[helpers.testHashTable] = items.map(function(item) { return {PutRequest: {Item: item}} }) + batchReq.RequestItems[helpers.testHashTable] = items.map(function (item) { return { PutRequest: { Item: item } } }) - request(helpers.opts('BatchWriteItem', batchReq), function(err, res) { + request(helpers.opts('BatchWriteItem', batchReq), function (err, res) { if (err) return done(err) res.statusCode.should.equal(200) - request(opts({TableName: helpers.testHashTable, Segment: 0, TotalSegments: 4096}), function(err, res) { + request(opts({ TableName: helpers.testHashTable, Segment: 0, TotalSegments: 4096 }), function (err, res) { if (err) return done(err) res.statusCode.should.equal(200) res.body.Items.should.containEql(items[0]) res.body.Items.should.containEql(items[1]) - request(opts({TableName: helpers.testHashTable, Segment: 1, TotalSegments: 4096}), function(err, res) { + request(opts({ TableName: helpers.testHashTable, Segment: 1, TotalSegments: 4096 }), function (err, res) { if (err) return done(err) res.statusCode.should.equal(200) res.body.Items.should.containEql(items[2]) - request(opts({TableName: helpers.testHashTable, Segment: 4, TotalSegments: 4096}), function(err, res) { + request(opts({ TableName: helpers.testHashTable, Segment: 4, TotalSegments: 4096 }), function (err, res) { if (err) return done(err) res.statusCode.should.equal(200) res.body.Items.should.containEql(items[3]) @@ -3328,22 +3328,22 @@ describe('scan', function() { }) // XXX: This is very brittle, relies on knowing the hashing scheme - it('should return items from correct number hash segments', function(done) { - var batchReq = {RequestItems: {}}, items = [ - {a: {N: '251'}}, - {a: {N: '2388'}}, + it('should return items from correct number hash segments', function (done) { + var batchReq = { RequestItems: {} }, items = [ + { a: { N: '251' } }, + { a: { N: '2388' } }, ] - batchReq.RequestItems[helpers.testHashNTable] = items.map(function(item) { return {PutRequest: {Item: item}} }) + batchReq.RequestItems[helpers.testHashNTable] = items.map(function (item) { return { PutRequest: { Item: item } } }) - request(helpers.opts('BatchWriteItem', batchReq), function(err, res) { + request(helpers.opts('BatchWriteItem', batchReq), function (err, res) { if (err) return done(err) res.statusCode.should.equal(200) - request(opts({TableName: helpers.testHashNTable, Segment: 1, TotalSegments: 4096}), function(err, res) { + request(opts({ TableName: helpers.testHashNTable, Segment: 1, TotalSegments: 4096 }), function (err, res) { if (err) return done(err) res.statusCode.should.equal(200) res.body.Items.should.containEql(items[0]) - request(opts({TableName: helpers.testHashNTable, Segment: 4095, TotalSegments: 4096}), function(err, res) { + request(opts({ TableName: helpers.testHashNTable, Segment: 4095, TotalSegments: 4096 }), function (err, res) { if (err) return done(err) res.statusCode.should.equal(200) res.body.Items.should.containEql(items[1]) @@ -3355,18 +3355,18 @@ describe('scan', function() { // High capacity (~100 or more) needed to run this quickly if (runSlowTests) { - it('should not return LastEvaluatedKey if just under limit for range table', function(done) { + it('should not return LastEvaluatedKey if just under limit for range table', function (done) { this.timeout(200000) var i, items = [], id = helpers.randomString(), e = new Array(41583).join('e'), eAttr = e.slice(0, 255) for (i = 0; i < 25; i++) { - var item = {a: {S: id}, b: {S: ('000000' + i).slice(-6)}, c: {S: 'abcde'}} - item[eAttr] = {S: e} + var item = { a: { S: id }, b: { S: ('000000' + i).slice(-6) }, c: { S: 'abcde' } } + item[eAttr] = { S: e } items.push(item) } items[24][eAttr].S = new Array(41583).join('e') - helpers.replaceTable(helpers.testRangeTable, ['a', 'b'], items, function(err) { + helpers.replaceTable(helpers.testRangeTable, [ 'a', 'b' ], items, function (err) { if (err) return done(err) request(opts({ @@ -3374,7 +3374,7 @@ describe('scan', function() { Select: 'COUNT', ReturnConsumedCapacity: 'INDEXES', Limit: 26, - }), function(err, res) { + }), function (err, res) { if (err) return done(err) res.statusCode.should.equal(200) res.body.should.eql({ @@ -3382,31 +3382,31 @@ describe('scan', function() { ScannedCount: 25, ConsumedCapacity: { CapacityUnits: 128, - Table: {CapacityUnits: 128}, + Table: { CapacityUnits: 128 }, TableName: helpers.testRangeTable, }, }) - helpers.clearTable(helpers.testRangeTable, ['a', 'b'], done) + helpers.clearTable(helpers.testRangeTable, [ 'a', 'b' ], done) }) }) }) - it('should return LastEvaluatedKey if just over limit for range table', function(done) { + it('should return LastEvaluatedKey if just over limit for range table', function (done) { this.timeout(200000) var i, items = [], id = helpers.randomString(), e = new Array(41597).join('e') for (i = 0; i < 25; i++) - items.push({a: {S: id}, b: {S: ('00000' + i).slice(-5)}, c: {S: 'abcde'}, e: {S: e}}) + items.push({ a: { S: id }, b: { S: ('00000' + i).slice(-5) }, c: { S: 'abcde' }, e: { S: e } }) items[24].e.S = new Array(41598).join('e') - helpers.replaceTable(helpers.testRangeTable, ['a', 'b'], items, function(err) { + helpers.replaceTable(helpers.testRangeTable, [ 'a', 'b' ], items, function (err) { if (err) return done(err) request(opts({ TableName: helpers.testRangeTable, Select: 'COUNT', ReturnConsumedCapacity: 'INDEXES', - }), function(err, res) { + }), function (err, res) { if (err) return done(err) res.statusCode.should.equal(200) res.body.should.eql({ @@ -3414,28 +3414,28 @@ describe('scan', function() { ScannedCount: 25, ConsumedCapacity: { CapacityUnits: 127.5, - Table: {CapacityUnits: 127.5}, + Table: { CapacityUnits: 127.5 }, TableName: helpers.testRangeTable, }, - LastEvaluatedKey: {a: items[24].a, b: items[24].b}, + LastEvaluatedKey: { a: items[24].a, b: items[24].b }, }) - helpers.clearTable(helpers.testRangeTable, ['a', 'b'], done) + helpers.clearTable(helpers.testRangeTable, [ 'a', 'b' ], done) }) }) }) - it('should not return LastEvaluatedKey if just under limit for number range table', function(done) { + it('should not return LastEvaluatedKey if just under limit for number range table', function (done) { this.timeout(200000) var i, items = [], id = helpers.randomString(), e = new Array(41639).join('e'), eAttr = e.slice(0, 255) for (i = 0; i < 25; i++) { - var item = {a: {S: id}, b: {N: ('00' + i).slice(-2)}, c: {S: 'abcde'}} - item[eAttr] = {S: e} + var item = { a: { S: id }, b: { N: ('00' + i).slice(-2) }, c: { S: 'abcde' } } + item[eAttr] = { S: e } items.push(item) } items[24][eAttr].S = new Array(41653).join('e') - helpers.replaceTable(helpers.testRangeNTable, ['a', 'b'], items, function(err) { + helpers.replaceTable(helpers.testRangeNTable, [ 'a', 'b' ], items, function (err) { if (err) return done(err) request(opts({ @@ -3443,7 +3443,7 @@ describe('scan', function() { Select: 'COUNT', ReturnConsumedCapacity: 'INDEXES', Limit: 26, - }), function(err, res) { + }), function (err, res) { if (err) return done(err) res.statusCode.should.equal(200) res.body.should.eql({ @@ -3451,31 +3451,31 @@ describe('scan', function() { ScannedCount: 25, ConsumedCapacity: { CapacityUnits: 128, - Table: {CapacityUnits: 128}, + Table: { CapacityUnits: 128 }, TableName: helpers.testRangeNTable, }, }) - helpers.clearTable(helpers.testRangeNTable, ['a', 'b'], done) + helpers.clearTable(helpers.testRangeNTable, [ 'a', 'b' ], done) }) }) }) - it('should return LastEvaluatedKey if just over limit for number range table', function(done) { + it('should return LastEvaluatedKey if just over limit for number range table', function (done) { this.timeout(200000) var i, items = [], id = helpers.randomString(), e = new Array(41639).join('e') for (i = 0; i < 25; i++) - items.push({a: {S: id}, b: {N: ('00' + i).slice(-2)}, c: {S: 'abcde'}, e: {S: e}}) + items.push({ a: { S: id }, b: { N: ('00' + i).slice(-2) }, c: { S: 'abcde' }, e: { S: e } }) items[24].e.S = new Array(41654).join('e') - helpers.replaceTable(helpers.testRangeNTable, ['a', 'b'], items, function(err) { + helpers.replaceTable(helpers.testRangeNTable, [ 'a', 'b' ], items, function (err) { if (err) return done(err) request(opts({ TableName: helpers.testRangeNTable, Select: 'COUNT', ReturnConsumedCapacity: 'INDEXES', - }), function(err, res) { + }), function (err, res) { if (err) return done(err) res.statusCode.should.equal(200) res.body.should.eql({ @@ -3483,27 +3483,27 @@ describe('scan', function() { ScannedCount: 25, ConsumedCapacity: { CapacityUnits: 127.5, - Table: {CapacityUnits: 127.5}, + Table: { CapacityUnits: 127.5 }, TableName: helpers.testRangeNTable, }, - LastEvaluatedKey: {a: items[24].a, b: items[24].b}, + LastEvaluatedKey: { a: items[24].a, b: items[24].b }, }) - helpers.clearTable(helpers.testRangeNTable, ['a', 'b'], done) + helpers.clearTable(helpers.testRangeNTable, [ 'a', 'b' ], done) }) }) }) - it('should return all if just under limit with small attribute for hash table', function(done) { + it('should return all if just under limit with small attribute for hash table', function (done) { this.timeout(200000) var i, items = [] for (i = 0; i < 25; i++) - items.push({a: {S: ('0' + i).slice(-2)}}) + items.push({ a: { S: ('0' + i).slice(-2) } }) - helpers.replaceTable(helpers.testHashTable, 'a', items, function(err) { + helpers.replaceTable(helpers.testHashTable, 'a', items, function (err) { if (err) return done(err) - request(opts({TableName: helpers.testHashTable}), function(err, res) { + request(opts({ TableName: helpers.testHashTable }), function (err, res) { if (err) return done(err) res.statusCode.should.equal(200) items = res.body.Items @@ -3514,23 +3514,25 @@ describe('scan', function() { for (i = 0; i < 25; i++) { if (i == 23) { // Second last item - items[i].b = {S: b.slice(0, 43412 - 46)} - items[i].c = {N: '12.3456'} - items[i].d = {B: 'AQI='} - items[i].e = {SS: ['a', 'bc']} - items[i].f = {NS: ['1.23', '12.3']} - items[i].g = {BS: ['AQI=', 'Ag==', 'AQ==']} - } else if (i == 24) { - items[i].b = {S: 'b'} // Last item doesn't matter - } else { - items[i].b = {S: b} + items[i].b = { S: b.slice(0, 43412 - 46) } + items[i].c = { N: '12.3456' } + items[i].d = { B: 'AQI=' } + items[i].e = { SS: [ 'a', 'bc' ] } + items[i].f = { NS: [ '1.23', '12.3' ] } + items[i].g = { BS: [ 'AQI=', 'Ag==', 'AQ==' ] } + } + else if (i == 24) { + items[i].b = { S: 'b' } // Last item doesn't matter + } + else { + items[i].b = { S: b } } } - helpers.replaceTable(helpers.testHashTable, 'a', items, 10, function(err) { + helpers.replaceTable(helpers.testHashTable, 'a', items, 10, function (err) { if (err) return done(err) - request(opts({TableName: helpers.testHashTable, Select: 'COUNT', ReturnConsumedCapacity: 'TOTAL'}), function(err, res) { + request(opts({ TableName: helpers.testHashTable, Select: 'COUNT', ReturnConsumedCapacity: 'TOTAL' }), function (err, res) { if (err) return done(err) res.statusCode.should.equal(200) res.body.ScannedCount.should.equal(25) @@ -3543,17 +3545,17 @@ describe('scan', function() { }) }) - it('should return all if just under limit with large attribute', function(done) { + it('should return all if just under limit with large attribute', function (done) { this.timeout(200000) var i, items = [] for (i = 0; i < 25; i++) - items.push({a: {S: ('0' + i).slice(-2)}}) + items.push({ a: { S: ('0' + i).slice(-2) } }) - helpers.replaceTable(helpers.testHashTable, 'a', items, function(err) { + helpers.replaceTable(helpers.testHashTable, 'a', items, function (err) { if (err) return done(err) - request(opts({TableName: helpers.testHashTable}), function(err, res) { + request(opts({ TableName: helpers.testHashTable }), function (err, res) { if (err) return done(err) res.statusCode.should.equal(200) items = res.body.Items @@ -3564,23 +3566,25 @@ describe('scan', function() { for (i = 0; i < 25; i++) { if (i == 23) { // Second last item - items[i].bfasfdsfdsa = {S: b.slice(0, 43412 - 46)} - items[i].cfadsfdsaafds = {N: '12.3456'} - items[i].dfasdfdafdsa = {B: 'AQI='} - items[i].efdasfdasfd = {SS: ['a', 'bc']} - items[i].ffdsafsdfd = {NS: ['1.23', '12.3']} - items[i].gfsdfdsaafds = {BS: ['AQI=', 'Ag==', 'AQ==']} - } else if (i == 24) { - items[i].b = {S: 'b'} - } else { - items[i][bAttr] = {S: b} + items[i].bfasfdsfdsa = { S: b.slice(0, 43412 - 46) } + items[i].cfadsfdsaafds = { N: '12.3456' } + items[i].dfasdfdafdsa = { B: 'AQI=' } + items[i].efdasfdasfd = { SS: [ 'a', 'bc' ] } + items[i].ffdsafsdfd = { NS: [ '1.23', '12.3' ] } + items[i].gfsdfdsaafds = { BS: [ 'AQI=', 'Ag==', 'AQ==' ] } + } + else if (i == 24) { + items[i].b = { S: 'b' } + } + else { + items[i][bAttr] = { S: b } } } - helpers.replaceTable(helpers.testHashTable, 'a', items, 10, function(err) { + helpers.replaceTable(helpers.testHashTable, 'a', items, 10, function (err) { if (err) return done(err) - request(opts({TableName: helpers.testHashTable, Select: 'COUNT', ReturnConsumedCapacity: 'TOTAL'}), function(err, res) { + request(opts({ TableName: helpers.testHashTable, Select: 'COUNT', ReturnConsumedCapacity: 'TOTAL' }), function (err, res) { if (err) return done(err) res.statusCode.should.equal(200) res.body.ScannedCount.should.equal(25) @@ -3593,17 +3597,17 @@ describe('scan', function() { }) }) - it('should return one less than all if just over limit with small attribute for hash table', function(done) { + it('should return one less than all if just over limit with small attribute for hash table', function (done) { this.timeout(100000) var i, items = [] for (i = 0; i < 25; i++) - items.push({a: {S: ('0' + i).slice(-2)}}) + items.push({ a: { S: ('0' + i).slice(-2) } }) - helpers.replaceTable(helpers.testHashTable, 'a', items, function(err) { + helpers.replaceTable(helpers.testHashTable, 'a', items, function (err) { if (err) return done(err) - request(opts({TableName: helpers.testHashTable}), function(err, res) { + request(opts({ TableName: helpers.testHashTable }), function (err, res) { if (err) return done(err) res.statusCode.should.equal(200) items = res.body.Items @@ -3614,23 +3618,25 @@ describe('scan', function() { for (i = 0; i < 25; i++) { if (i == 23) { // Second last item - items[i].b = {S: b.slice(0, 43412 - 45)} - items[i].c = {N: '12.3456'} - items[i].d = {B: 'AQI='} - items[i].e = {SS: ['a', 'bc']} - items[i].f = {NS: ['1.23', '12.3']} - items[i].g = {BS: ['AQI=', 'Ag==', 'AQ==']} - } else if (i == 24) { - items[i].b = {S: 'b'} // Last item doesn't matter - } else { - items[i].b = {S: b} + items[i].b = { S: b.slice(0, 43412 - 45) } + items[i].c = { N: '12.3456' } + items[i].d = { B: 'AQI=' } + items[i].e = { SS: [ 'a', 'bc' ] } + items[i].f = { NS: [ '1.23', '12.3' ] } + items[i].g = { BS: [ 'AQI=', 'Ag==', 'AQ==' ] } + } + else if (i == 24) { + items[i].b = { S: 'b' } // Last item doesn't matter + } + else { + items[i].b = { S: b } } } - helpers.replaceTable(helpers.testHashTable, 'a', items, 10, function(err) { + helpers.replaceTable(helpers.testHashTable, 'a', items, 10, function (err) { if (err) return done(err) - request(opts({TableName: helpers.testHashTable, Select: 'COUNT', ReturnConsumedCapacity: 'TOTAL'}), function(err, res) { + request(opts({ TableName: helpers.testHashTable, Select: 'COUNT', ReturnConsumedCapacity: 'TOTAL' }), function (err, res) { if (err) return done(err) res.statusCode.should.equal(200) res.body.ScannedCount.should.equal(24) @@ -3643,17 +3649,17 @@ describe('scan', function() { }) }) - it('should return all if just under limit for range table', function(done) { + it('should return all if just under limit for range table', function (done) { this.timeout(200000) var i, items = [] for (i = 0; i < 25; i++) - items.push({a: {S: ('0' + i).slice(-2)}, b: {S: ('0' + i).slice(-2)}}) + items.push({ a: { S: ('0' + i).slice(-2) }, b: { S: ('0' + i).slice(-2) } }) - helpers.replaceTable(helpers.testRangeTable, ['a', 'b'], items, function(err) { + helpers.replaceTable(helpers.testRangeTable, [ 'a', 'b' ], items, function (err) { if (err) return done(err) - request(opts({TableName: helpers.testRangeTable}), function(err, res) { + request(opts({ TableName: helpers.testRangeTable }), function (err, res) { if (err) return done(err) res.statusCode.should.equal(200) items = res.body.Items @@ -3664,46 +3670,48 @@ describe('scan', function() { for (i = 0; i < 25; i++) { if (i == 23) { // Second last item - items[i].z = {S: b.slice(0, 43381 - 22)} - items[i].y = {N: '12.3456'} - items[i].x = {B: 'AQI='} - items[i].w = {SS: ['a', 'bc']} - items[i].v = {NS: ['1.23', '12.3']} - items[i].u = {BS: ['AQI=', 'Ag==', 'AQ==']} - } else if (i == 24) { - items[i].z = {S: 'b'} // Last item doesn't matter - } else { - items[i][bAttr] = {S: b} + items[i].z = { S: b.slice(0, 43381 - 22) } + items[i].y = { N: '12.3456' } + items[i].x = { B: 'AQI=' } + items[i].w = { SS: [ 'a', 'bc' ] } + items[i].v = { NS: [ '1.23', '12.3' ] } + items[i].u = { BS: [ 'AQI=', 'Ag==', 'AQ==' ] } + } + else if (i == 24) { + items[i].z = { S: 'b' } // Last item doesn't matter + } + else { + items[i][bAttr] = { S: b } } } - helpers.replaceTable(helpers.testRangeTable, ['a', 'b'], items, 10, function(err) { + helpers.replaceTable(helpers.testRangeTable, [ 'a', 'b' ], items, 10, function (err) { if (err) return done(err) - request(opts({TableName: helpers.testRangeTable, Select: 'COUNT', ReturnConsumedCapacity: 'TOTAL'}), function(err, res) { + request(opts({ TableName: helpers.testRangeTable, Select: 'COUNT', ReturnConsumedCapacity: 'TOTAL' }), function (err, res) { if (err) return done(err) res.statusCode.should.equal(200) res.body.ScannedCount.should.equal(25) res.body.Count.should.equal(25) res.body.ConsumedCapacity.CapacityUnits.should.equal(128) - helpers.clearTable(helpers.testRangeTable, ['a', 'b'], done) + helpers.clearTable(helpers.testRangeTable, [ 'a', 'b' ], done) }) }) }) }) }) - it('should return all if just over limit with less items for range table', function(done) { + it('should return all if just over limit with less items for range table', function (done) { this.timeout(200000) var i, items = [] for (i = 0; i < 13; i++) - items.push({a: {S: ('0' + i).slice(-2)}, b: {S: ('0000000' + i).slice(-7)}}) + items.push({ a: { S: ('0' + i).slice(-2) }, b: { S: ('0000000' + i).slice(-7) } }) - helpers.replaceTable(helpers.testRangeTable, ['a', 'b'], items, function(err) { + helpers.replaceTable(helpers.testRangeTable, [ 'a', 'b' ], items, function (err) { if (err) return done(err) - request(opts({TableName: helpers.testRangeTable}), function(err, res) { + request(opts({ TableName: helpers.testRangeTable }), function (err, res) { if (err) return done(err) res.statusCode.should.equal(200) items = res.body.Items @@ -3714,42 +3722,44 @@ describe('scan', function() { for (i = 0; i < 13; i++) { if (i == 11) { // Second last item - items[i].z = {S: b.slice(0, 86648 - 9)} - } else if (i == 12) { - items[i].z = {S: 'b'} // Last item doesn't matter, 127.5 capacity units + items[i].z = { S: b.slice(0, 86648 - 9) } + } + else if (i == 12) { + items[i].z = { S: 'b' } // Last item doesn't matter, 127.5 capacity units // items[i][bAttr] = {S: b} // 138 capacity units - } else { - items[i].z = {S: b} + } + else { + items[i].z = { S: b } } } - helpers.replaceTable(helpers.testRangeTable, ['a', 'b'], items, 10, function(err) { + helpers.replaceTable(helpers.testRangeTable, [ 'a', 'b' ], items, 10, function (err) { if (err) return done(err) - request(opts({TableName: helpers.testRangeTable, Select: 'COUNT', ReturnConsumedCapacity: 'TOTAL'}), function(err, res) { + request(opts({ TableName: helpers.testRangeTable, Select: 'COUNT', ReturnConsumedCapacity: 'TOTAL' }), function (err, res) { if (err) return done(err) res.statusCode.should.equal(200) res.body.ScannedCount.should.equal(12) res.body.Count.should.equal(12) res.body.ConsumedCapacity.CapacityUnits.should.equal(127) - helpers.clearTable(helpers.testRangeTable, ['a', 'b'], done) + helpers.clearTable(helpers.testRangeTable, [ 'a', 'b' ], done) }) }) }) }) }) - it('should return all if just over limit for range table', function(done) { + it('should return all if just over limit for range table', function (done) { this.timeout(200000) var i, items = [] for (i = 0; i < 25; i++) - items.push({a: {S: ('0' + i).slice(-2)}, b: {S: ('0' + i).slice(-2)}}) + items.push({ a: { S: ('0' + i).slice(-2) }, b: { S: ('0' + i).slice(-2) } }) - helpers.replaceTable(helpers.testRangeTable, ['a', 'b'], items, function(err) { + helpers.replaceTable(helpers.testRangeTable, [ 'a', 'b' ], items, function (err) { if (err) return done(err) - request(opts({TableName: helpers.testRangeTable}), function(err, res) { + request(opts({ TableName: helpers.testRangeTable }), function (err, res) { if (err) return done(err) res.statusCode.should.equal(200) items = res.body.Items @@ -3760,46 +3770,48 @@ describe('scan', function() { for (i = 0; i < 25; i++) { if (i == 23) { // Second last item - items[i].z = {S: b.slice(0, 43381 - 21)} - items[i].y = {N: '12.3456'} - items[i].x = {B: 'AQI='} - items[i].w = {SS: ['a', 'bc']} - items[i].v = {NS: ['1.23', '12.3']} - items[i].u = {BS: ['AQI=', 'Ag==', 'AQ==']} - } else if (i == 24) { - items[i].z = {S: 'b'} // Last item doesn't matter - } else { - items[i].z = {S: b} + items[i].z = { S: b.slice(0, 43381 - 21) } + items[i].y = { N: '12.3456' } + items[i].x = { B: 'AQI=' } + items[i].w = { SS: [ 'a', 'bc' ] } + items[i].v = { NS: [ '1.23', '12.3' ] } + items[i].u = { BS: [ 'AQI=', 'Ag==', 'AQ==' ] } + } + else if (i == 24) { + items[i].z = { S: 'b' } // Last item doesn't matter + } + else { + items[i].z = { S: b } } } - helpers.replaceTable(helpers.testRangeTable, ['a', 'b'], items, 10, function(err) { + helpers.replaceTable(helpers.testRangeTable, [ 'a', 'b' ], items, 10, function (err) { if (err) return done(err) - request(opts({TableName: helpers.testRangeTable, Select: 'COUNT', ReturnConsumedCapacity: 'TOTAL'}), function(err, res) { + request(opts({ TableName: helpers.testRangeTable, Select: 'COUNT', ReturnConsumedCapacity: 'TOTAL' }), function (err, res) { if (err) return done(err) res.statusCode.should.equal(200) res.body.ScannedCount.should.equal(24) res.body.Count.should.equal(24) res.body.ConsumedCapacity.CapacityUnits.should.equal(127.5) - helpers.clearTable(helpers.testRangeTable, ['a', 'b'], done) + helpers.clearTable(helpers.testRangeTable, [ 'a', 'b' ], done) }) }) }) }) }) - it('should return one less than all if just over limit with large attribute', function(done) { + it('should return one less than all if just over limit with large attribute', function (done) { this.timeout(100000) var i, items = [] for (i = 0; i < 25; i++) - items.push({a: {S: ('0' + i).slice(-2)}}) + items.push({ a: { S: ('0' + i).slice(-2) } }) - helpers.replaceTable(helpers.testHashTable, 'a', items, function(err) { + helpers.replaceTable(helpers.testHashTable, 'a', items, function (err) { if (err) return done(err) - request(opts({TableName: helpers.testHashTable}), function(err, res) { + request(opts({ TableName: helpers.testHashTable }), function (err, res) { if (err) return done(err) res.statusCode.should.equal(200) items = res.body.Items @@ -3810,23 +3822,25 @@ describe('scan', function() { for (i = 0; i < 25; i++) { if (i == 23) { // Second last item - items[i].bfasfdsfdsa = {S: b.slice(0, 43412 - 45)} - items[i].cfadsfdsaafds = {N: '12.3456'} - items[i].dfasdfdafdsa = {B: 'AQI='} - items[i].efdasfdasfd = {SS: ['a', 'bc']} - items[i].ffdsafsdfd = {NS: ['1.23', '12.3']} - items[i].gfsdfdsaafds = {BS: ['AQI=', 'Ag==', 'AQ==']} - } else if (i == 24) { - items[i][bAttr] = {S: new Array(100).join('b')} // Last item doesn't matter - } else { - items[i][bAttr] = {S: b} + items[i].bfasfdsfdsa = { S: b.slice(0, 43412 - 45) } + items[i].cfadsfdsaafds = { N: '12.3456' } + items[i].dfasdfdafdsa = { B: 'AQI=' } + items[i].efdasfdasfd = { SS: [ 'a', 'bc' ] } + items[i].ffdsafsdfd = { NS: [ '1.23', '12.3' ] } + items[i].gfsdfdsaafds = { BS: [ 'AQI=', 'Ag==', 'AQ==' ] } + } + else if (i == 24) { + items[i][bAttr] = { S: new Array(100).join('b') } // Last item doesn't matter + } + else { + items[i][bAttr] = { S: b } } } - helpers.replaceTable(helpers.testHashTable, 'a', items, 10, function(err) { + helpers.replaceTable(helpers.testHashTable, 'a', items, 10, function (err) { if (err) return done(err) - request(opts({TableName: helpers.testHashTable, Select: 'COUNT', ReturnConsumedCapacity: 'TOTAL'}), function(err, res) { + request(opts({ TableName: helpers.testHashTable, Select: 'COUNT', ReturnConsumedCapacity: 'TOTAL' }), function (err, res) { if (err) return done(err) res.statusCode.should.equal(200) res.body.ScannedCount.should.equal(24) @@ -3841,13 +3855,13 @@ describe('scan', function() { } // Upper bound seems to vary – tends to return a 500 above 30000 args - it('should allow scans at least for 27500 args to IN', function(done) { + it('should allow scans at least for 27500 args to IN', function (done) { this.timeout(100000) var attrValList = [], i - for (i = 0; i < 27500; i++) attrValList.push({S: 'a'}) - request(opts({TableName: helpers.testHashTable, ScanFilter: { - a: {ComparisonOperator: 'IN', AttributeValueList: attrValList}, - }}), function(err, res) { + for (i = 0; i < 27500; i++) attrValList.push({ S: 'a' }) + request(opts({ TableName: helpers.testHashTable, ScanFilter: { + a: { ComparisonOperator: 'IN', AttributeValueList: attrValList }, + } }), function (err, res) { if (err) return done(err) res.statusCode.should.equal(200) done() diff --git a/test/tagResource.js b/test/tagResource.js index d87b5e9..dd84e33 100644 --- a/test/tagResource.js +++ b/test/tagResource.js @@ -1,92 +1,92 @@ var helpers = require('./helpers') var target = 'TagResource', - assertType = helpers.assertType.bind(null, target), - assertNotFound = helpers.assertNotFound.bind(null, target), - assertAccessDenied = helpers.assertAccessDenied.bind(null, target), - assertValidation = helpers.assertValidation.bind(null, target) + assertType = helpers.assertType.bind(null, target), + assertNotFound = helpers.assertNotFound.bind(null, target), + assertAccessDenied = helpers.assertAccessDenied.bind(null, target), + assertValidation = helpers.assertValidation.bind(null, target) -describe('tagResource', function() { +describe('tagResource', function () { - describe('serializations', function() { + describe('serializations', function () { - it('should return SerializationException when ResourceArn is not a string', function(done) { + it('should return SerializationException when ResourceArn is not a string', function (done) { assertType('ResourceArn', 'String', done) }) - it('should return SerializationException when Tags is not a list', function(done) { + it('should return SerializationException when Tags is not a list', function (done) { assertType('Tags', 'List', done) }) - it('should return SerializationException when Tags.0 is not a struct', function(done) { + it('should return SerializationException when Tags.0 is not a struct', function (done) { assertType('Tags.0', 'ValueStruct', done) }) - it('should return SerializationException when Tags.0.Key is not a string', function(done) { + it('should return SerializationException when Tags.0.Key is not a string', function (done) { assertType('Tags.0.Key', 'String', done) }) - it('should return SerializationException when Tags.0.Value is not a string', function(done) { + it('should return SerializationException when Tags.0.Value is not a string', function (done) { assertType('Tags.0.Value', 'String', done) }) }) - describe('validations', function() { + describe('validations', function () { - it('should return ValidationException for no ResourceArn', function(done) { + it('should return ValidationException for no ResourceArn', function (done) { assertValidation({}, 'Invalid TableArn', done) }) - it('should return AccessDeniedException for empty ResourceArn', function(done) { - assertAccessDenied({ResourceArn: ''}, + it('should return AccessDeniedException for empty ResourceArn', function (done) { + assertAccessDenied({ ResourceArn: '' }, /^User: arn:aws:iam::\d+:.+ is not authorized to perform: dynamodb:TagResource on resource: \*$/, done) }) - it('should return AccessDeniedException for short unauthorized ResourceArn', function(done) { - assertAccessDenied({ResourceArn: 'abcd'}, + it('should return AccessDeniedException for short unauthorized ResourceArn', function (done) { + assertAccessDenied({ ResourceArn: 'abcd' }, /^User: arn:aws:iam::\d+:.+ is not authorized to perform: dynamodb:TagResource on resource: abcd$/, done) }) - it('should return AccessDeniedException for long unauthorized ResourceArn', function(done) { - assertAccessDenied({ResourceArn: 'a:b:c:d:e:f'}, + it('should return AccessDeniedException for long unauthorized ResourceArn', function (done) { + assertAccessDenied({ ResourceArn: 'a:b:c:d:e:f' }, /^User: arn:aws:iam::\d+:.+ is not authorized to perform: dynamodb:TagResource on resource: a:b:c:d:e:f$/, done) }) - it('should return AccessDeniedException for longer unauthorized ResourceArn', function(done) { - assertAccessDenied({ResourceArn: 'a:b:c:d:e/f'}, + it('should return AccessDeniedException for longer unauthorized ResourceArn', function (done) { + assertAccessDenied({ ResourceArn: 'a:b:c:d:e/f' }, /^User: arn:aws:iam::\d+:.+ is not authorized to perform: dynamodb:TagResource on resource: a:b:c:d:e\/f$/, done) }) - it('should return ValidationException for null Tags', function(done) { - assertValidation({ResourceArn: 'a:b:c:d:e:f/g'}, + it('should return ValidationException for null Tags', function (done) { + assertValidation({ ResourceArn: 'a:b:c:d:e:f/g' }, '1 validation error detected: Value null at \'tags\' failed to satisfy constraint: Member must not be null', done) }) - it('should return ValidationException for invalid ResourceArn', function(done) { - assertValidation({ResourceArn: 'a:b:c:d:e:f/g', Tags: []}, + it('should return ValidationException for invalid ResourceArn', function (done) { + assertValidation({ ResourceArn: 'a:b:c:d:e:f/g', Tags: [] }, 'Invalid TableArn: Invalid ResourceArn provided as input a:b:c:d:e:f/g', done) }) - it('should return ValidationException for short table name', function(done) { + it('should return ValidationException for short table name', function (done) { var resourceArn = 'arn:aws:dynamodb:' + helpers.awsRegion + ':' + helpers.awsAccountId + ':table/ab' - assertValidation({ResourceArn: resourceArn, Tags: []}, + assertValidation({ ResourceArn: resourceArn, Tags: [] }, 'Invalid TableArn: Invalid ResourceArn provided as input ' + resourceArn, done) }) - it('should return ResourceNotFoundException if Tags are empty', function(done) { + it('should return ResourceNotFoundException if Tags are empty', function (done) { var resourceArn = 'arn:aws:dynamodb:' + helpers.awsRegion + ':' + helpers.awsAccountId + ':table/' + helpers.randomString() - assertValidation({ResourceArn: resourceArn, Tags: []}, + assertValidation({ ResourceArn: resourceArn, Tags: [] }, 'Atleast one Tag needs to be provided as Input.', done) }) - it('should return ResourceNotFoundException if ResourceArn does not exist', function(done) { + it('should return ResourceNotFoundException if ResourceArn does not exist', function (done) { var resourceArn = 'arn:aws:dynamodb:' + helpers.awsRegion + ':' + helpers.awsAccountId + ':table/' + helpers.randomString() - assertNotFound({ResourceArn: resourceArn, Tags: [{Key: 'a', Value: 'b'}]}, + assertNotFound({ ResourceArn: resourceArn, Tags: [ { Key: 'a', Value: 'b' } ] }, 'Requested resource not found: ResourcArn: ' + resourceArn + ' not found', done) }) diff --git a/test/untagResource.js b/test/untagResource.js index 6eb5558..c5f4b26 100644 --- a/test/untagResource.js +++ b/test/untagResource.js @@ -1,84 +1,84 @@ var helpers = require('./helpers') var target = 'UntagResource', - assertType = helpers.assertType.bind(null, target), - assertNotFound = helpers.assertNotFound.bind(null, target), - assertAccessDenied = helpers.assertAccessDenied.bind(null, target), - assertValidation = helpers.assertValidation.bind(null, target) + assertType = helpers.assertType.bind(null, target), + assertNotFound = helpers.assertNotFound.bind(null, target), + assertAccessDenied = helpers.assertAccessDenied.bind(null, target), + assertValidation = helpers.assertValidation.bind(null, target) -describe('untagResource', function() { +describe('untagResource', function () { - describe('serializations', function() { + describe('serializations', function () { - it('should return SerializationException when ResourceArn is not a string', function(done) { + it('should return SerializationException when ResourceArn is not a string', function (done) { assertType('ResourceArn', 'String', done) }) - it('should return SerializationException when TagKeys is not a list', function(done) { + it('should return SerializationException when TagKeys is not a list', function (done) { assertType('TagKeys', 'List', done) }) - it('should return SerializationException when TagKeys.0 is not a string', function(done) { + it('should return SerializationException when TagKeys.0 is not a string', function (done) { assertType('TagKeys.0', 'String', done) }) }) - describe('validations', function() { + describe('validations', function () { - it('should return ValidationException for no ResourceArn', function(done) { + it('should return ValidationException for no ResourceArn', function (done) { assertValidation({}, 'Invalid TableArn', done) }) - it('should return AccessDeniedException for empty ResourceArn', function(done) { - assertAccessDenied({ResourceArn: ''}, + it('should return AccessDeniedException for empty ResourceArn', function (done) { + assertAccessDenied({ ResourceArn: '' }, /^User: arn:aws:iam::\d+:.+ is not authorized to perform: dynamodb:UntagResource on resource: \*$/, done) }) - it('should return AccessDeniedException for short unauthorized ResourceArn', function(done) { - assertAccessDenied({ResourceArn: 'abcd'}, + it('should return AccessDeniedException for short unauthorized ResourceArn', function (done) { + assertAccessDenied({ ResourceArn: 'abcd' }, /^User: arn:aws:iam::\d+:.+ is not authorized to perform: dynamodb:UntagResource on resource: abcd$/, done) }) - it('should return AccessDeniedException for long unauthorized ResourceArn', function(done) { - assertAccessDenied({ResourceArn: 'a:b:c:d:e:f'}, + it('should return AccessDeniedException for long unauthorized ResourceArn', function (done) { + assertAccessDenied({ ResourceArn: 'a:b:c:d:e:f' }, /^User: arn:aws:iam::\d+:.+ is not authorized to perform: dynamodb:UntagResource on resource: a:b:c:d:e:f$/, done) }) - it('should return AccessDeniedException for longer unauthorized ResourceArn', function(done) { - assertAccessDenied({ResourceArn: 'a:b:c:d:e/f'}, + it('should return AccessDeniedException for longer unauthorized ResourceArn', function (done) { + assertAccessDenied({ ResourceArn: 'a:b:c:d:e/f' }, /^User: arn:aws:iam::\d+:.+ is not authorized to perform: dynamodb:UntagResource on resource: a:b:c:d:e\/f$/, done) }) - it('should return ValidationException for null TagKeys', function(done) { - assertValidation({ResourceArn: 'a:b:c:d:e:f/g'}, + it('should return ValidationException for null TagKeys', function (done) { + assertValidation({ ResourceArn: 'a:b:c:d:e:f/g' }, '1 validation error detected: Value null at \'tagKeys\' failed to satisfy constraint: Member must not be null', done) }) - it('should return ValidationException for invalid ResourceArn', function(done) { - assertValidation({ResourceArn: 'a:b:c:d:e:f/g', TagKeys: []}, + it('should return ValidationException for invalid ResourceArn', function (done) { + assertValidation({ ResourceArn: 'a:b:c:d:e:f/g', TagKeys: [] }, 'Invalid TableArn: Invalid ResourceArn provided as input a:b:c:d:e:f/g', done) }) - it('should return ValidationException for short table name', function(done) { + it('should return ValidationException for short table name', function (done) { var resourceArn = 'arn:aws:dynamodb:' + helpers.awsRegion + ':' + helpers.awsAccountId + ':table/ab' - assertValidation({ResourceArn: resourceArn, TagKeys: []}, + assertValidation({ ResourceArn: resourceArn, TagKeys: [] }, 'Invalid TableArn: Invalid ResourceArn provided as input ' + resourceArn, done) }) - it('should return ResourceNotFoundException if TagKeys are empty', function(done) { + it('should return ResourceNotFoundException if TagKeys are empty', function (done) { var resourceArn = 'arn:aws:dynamodb:' + helpers.awsRegion + ':' + helpers.awsAccountId + ':table/' + helpers.randomString() - assertValidation({ResourceArn: resourceArn, TagKeys: []}, + assertValidation({ ResourceArn: resourceArn, TagKeys: [] }, 'Atleast one Tag Key needs to be provided as Input.', done) }) - it('should return ResourceNotFoundException if ResourceArn does not exist', function(done) { + it('should return ResourceNotFoundException if ResourceArn does not exist', function (done) { var resourceArn = 'arn:aws:dynamodb:' + helpers.awsRegion + ':' + helpers.awsAccountId + ':table/' + helpers.randomString() - assertNotFound({ResourceArn: resourceArn, TagKeys: ['a']}, + assertNotFound({ ResourceArn: resourceArn, TagKeys: [ 'a' ] }, 'Requested resource not found', done) }) diff --git a/test/updateItem.js b/test/updateItem.js index d1b811e..005ea3f 100644 --- a/test/updateItem.js +++ b/test/updateItem.js @@ -1,108 +1,108 @@ var async = require('async'), - helpers = require('./helpers') + helpers = require('./helpers') var target = 'UpdateItem', - request = helpers.request, - randomName = helpers.randomName, - opts = helpers.opts.bind(null, target), - assertType = helpers.assertType.bind(null, target), - assertValidation = helpers.assertValidation.bind(null, target), - assertNotFound = helpers.assertNotFound.bind(null, target), - assertConditional = helpers.assertConditional.bind(null, target) + request = helpers.request, + randomName = helpers.randomName, + opts = helpers.opts.bind(null, target), + assertType = helpers.assertType.bind(null, target), + assertValidation = helpers.assertValidation.bind(null, target), + assertNotFound = helpers.assertNotFound.bind(null, target), + assertConditional = helpers.assertConditional.bind(null, target) -describe('updateItem', function() { +describe('updateItem', function () { - describe('serializations', function() { + describe('serializations', function () { - it('should return SerializationException when TableName is not a string', function(done) { + it('should return SerializationException when TableName is not a string', function (done) { assertType('TableName', 'String', done) }) - it('should return SerializationException when Key is not a map', function(done) { + it('should return SerializationException when Key is not a map', function (done) { assertType('Key', 'Map', done) }) - it('should return SerializationException when Key.Attr is not an attr struct', function(done) { + it('should return SerializationException when Key.Attr is not an attr struct', function (done) { this.timeout(60000) assertType('Key.Attr', 'AttrStruct', done) }) - it('should return SerializationException when Expected is not a map', function(done) { + it('should return SerializationException when Expected is not a map', function (done) { assertType('Expected', 'Map', done) }) - it('should return SerializationException when Expected.Attr is not a struct', function(done) { + it('should return SerializationException when Expected.Attr is not a struct', function (done) { assertType('Expected.Attr', 'ValueStruct', done) }) - it('should return SerializationException when Expected.Attr.Exists is not a boolean', function(done) { + it('should return SerializationException when Expected.Attr.Exists is not a boolean', function (done) { assertType('Expected.Attr.Exists', 'Boolean', done) }) - it('should return SerializationException when Expected.Attr.Value is not an attr struct', function(done) { + it('should return SerializationException when Expected.Attr.Value is not an attr struct', function (done) { this.timeout(60000) assertType('Expected.Attr.Value', 'AttrStruct', done) }) - it('should return SerializationException when AttributeUpdates is not a map', function(done) { + it('should return SerializationException when AttributeUpdates is not a map', function (done) { assertType('AttributeUpdates', 'Map', done) }) - it('should return SerializationException when AttributeUpdates.Attr is not a struct', function(done) { + it('should return SerializationException when AttributeUpdates.Attr is not a struct', function (done) { assertType('AttributeUpdates.Attr', 'ValueStruct', done) }) - it('should return SerializationException when AttributeUpdates.Attr.Action is not a string', function(done) { + it('should return SerializationException when AttributeUpdates.Attr.Action is not a string', function (done) { assertType('AttributeUpdates.Attr.Action', 'String', done) }) - it('should return SerializationException when AttributeUpdates.Attr.Value is not an attr struct', function(done) { + it('should return SerializationException when AttributeUpdates.Attr.Value is not an attr struct', function (done) { this.timeout(60000) assertType('AttributeUpdates.Attr.Value', 'AttrStruct', done) }) - it('should return SerializationException when ReturnConsumedCapacity is not a string', function(done) { + it('should return SerializationException when ReturnConsumedCapacity is not a string', function (done) { assertType('ReturnConsumedCapacity', 'String', done) }) - it('should return SerializationException when ReturnItemCollectionMetrics is not a string', function(done) { + it('should return SerializationException when ReturnItemCollectionMetrics is not a string', function (done) { assertType('ReturnItemCollectionMetrics', 'String', done) }) - it('should return SerializationException when ReturnValues is not a string', function(done) { + it('should return SerializationException when ReturnValues is not a string', function (done) { assertType('ReturnValues', 'String', done) }) - it('should return SerializationException when ConditionExpression is not a string', function(done) { + it('should return SerializationException when ConditionExpression is not a string', function (done) { assertType('ConditionExpression', 'String', done) }) - it('should return SerializationException when UpdateExpression is not a string', function(done) { + it('should return SerializationException when UpdateExpression is not a string', function (done) { assertType('UpdateExpression', 'String', done) }) - it('should return SerializationException when ExpressionAttributeValues is not a map', function(done) { + it('should return SerializationException when ExpressionAttributeValues is not a map', function (done) { assertType('ExpressionAttributeValues', 'Map', done) }) - it('should return SerializationException when ExpressionAttributeValues.Attr is not an attr struct', function(done) { + it('should return SerializationException when ExpressionAttributeValues.Attr is not an attr struct', function (done) { this.timeout(60000) assertType('ExpressionAttributeValues.Attr', 'AttrStruct', done) }) - it('should return SerializationException when ExpressionAttributeNames is not a map', function(done) { + it('should return SerializationException when ExpressionAttributeNames is not a map', function (done) { assertType('ExpressionAttributeNames', 'Map', done) }) - it('should return SerializationException when ExpressionAttributeNames.Attr is not a string', function(done) { + it('should return SerializationException when ExpressionAttributeNames.Attr is not a string', function (done) { assertType('ExpressionAttributeNames.Attr', 'String', done) }) }) - describe('validations', function() { + describe('validations', function () { - it('should return ValidationException for no TableName', function(done) { + it('should return ValidationException for no TableName', function (done) { assertValidation({}, [ 'Value null at \'tableName\' failed to satisfy constraint: ' + 'Member must not be null', @@ -111,8 +111,8 @@ describe('updateItem', function() { ], done) }) - it('should return ValidationException for empty TableName', function(done) { - assertValidation({TableName: ''}, [ + it('should return ValidationException for empty TableName', function (done) { + assertValidation({ TableName: '' }, [ 'Value \'\' at \'tableName\' failed to satisfy constraint: ' + 'Member must satisfy regular expression pattern: [a-zA-Z0-9_.-]+', 'Value \'\' at \'tableName\' failed to satisfy constraint: ' + @@ -122,8 +122,8 @@ describe('updateItem', function() { ], done) }) - it('should return ValidationException for short TableName', function(done) { - assertValidation({TableName: 'a;'}, [ + it('should return ValidationException for short TableName', function (done) { + assertValidation({ TableName: 'a;' }, [ 'Value \'a;\' at \'tableName\' failed to satisfy constraint: ' + 'Member must satisfy regular expression pattern: [a-zA-Z0-9_.-]+', 'Value \'a;\' at \'tableName\' failed to satisfy constraint: ' + @@ -133,9 +133,9 @@ describe('updateItem', function() { ], done) }) - it('should return ValidationException for long TableName', function(done) { + it('should return ValidationException for long TableName', function (done) { var name = new Array(256 + 1).join('a') - assertValidation({TableName: name}, [ + assertValidation({ TableName: name }, [ 'Value \'' + name + '\' at \'tableName\' failed to satisfy constraint: ' + 'Member must have length less than or equal to 255', 'Value null at \'key\' failed to satisfy constraint: ' + @@ -143,27 +143,27 @@ describe('updateItem', function() { ], done) }) - it('should return ValidationException for incorrect attributes', function(done) { - assertValidation({TableName: 'abc;', ReturnConsumedCapacity: 'hi', - ReturnItemCollectionMetrics: 'hi', ReturnValues: 'hi'}, [ - 'Value \'hi\' at \'returnConsumedCapacity\' failed to satisfy constraint: ' + + it('should return ValidationException for incorrect attributes', function (done) { + assertValidation({ TableName: 'abc;', ReturnConsumedCapacity: 'hi', + ReturnItemCollectionMetrics: 'hi', ReturnValues: 'hi' }, [ + 'Value \'hi\' at \'returnConsumedCapacity\' failed to satisfy constraint: ' + 'Member must satisfy enum value set: [INDEXES, TOTAL, NONE]', - 'Value \'abc;\' at \'tableName\' failed to satisfy constraint: ' + + 'Value \'abc;\' at \'tableName\' failed to satisfy constraint: ' + 'Member must satisfy regular expression pattern: [a-zA-Z0-9_.-]+', - 'Value \'hi\' at \'returnItemCollectionMetrics\' failed to satisfy constraint: ' + + 'Value \'hi\' at \'returnItemCollectionMetrics\' failed to satisfy constraint: ' + 'Member must satisfy enum value set: [SIZE, NONE]', - 'Value \'hi\' at \'returnValues\' failed to satisfy constraint: ' + + 'Value \'hi\' at \'returnValues\' failed to satisfy constraint: ' + 'Member must satisfy enum value set: [ALL_NEW, UPDATED_OLD, ALL_OLD, NONE, UPDATED_NEW]', - 'Value null at \'key\' failed to satisfy constraint: ' + + 'Value null at \'key\' failed to satisfy constraint: ' + 'Member must not be null', - ], done) + ], done) }) - it('should return ValidationException if expression and non-expression', function(done) { + it('should return ValidationException if expression and non-expression', function (done) { assertValidation({ TableName: 'abc', - Key: {a: {}}, - Expected: {a: {}}, + Key: { a: {} }, + Expected: { a: {} }, AttributeUpdates: {}, ExpressionAttributeNames: {}, ExpressionAttributeValues: {}, @@ -173,36 +173,36 @@ describe('updateItem', function() { 'Non-expression parameters: {AttributeUpdates, Expected} Expression parameters: {UpdateExpression, ConditionExpression}', done) }) - it('should return ValidationException if ExpressionAttributeNames but no ConditionExpression', function(done) { + it('should return ValidationException if ExpressionAttributeNames but no ConditionExpression', function (done) { assertValidation({ TableName: 'abc', - Key: {a: {}}, - Expected: {a: {}}, + Key: { a: {} }, + Expected: { a: {} }, ExpressionAttributeNames: {}, ExpressionAttributeValues: {}, }, 'ExpressionAttributeNames can only be specified when using expressions', done) }) - it('should return ValidationException if ExpressionAttributeValues but no ConditionExpression', function(done) { + it('should return ValidationException if ExpressionAttributeValues but no ConditionExpression', function (done) { assertValidation({ TableName: 'abc', - Key: {a: {}}, - Expected: {a: {}}, + Key: { a: {} }, + Expected: { a: {} }, ExpressionAttributeValues: {}, }, 'ExpressionAttributeValues can only be specified when using expressions: UpdateExpression and ConditionExpression are null', done) }) - it('should return ValidationException for unsupported datatype in Key', function(done) { + it('should return ValidationException for unsupported datatype in Key', function (done) { async.forEach([ {}, - {a: ''}, - {M: {a: {}}}, - {L: [{}]}, - {L: [{a: {}}]}, - ], function(expr, cb) { + { a: '' }, + { M: { a: {} } }, + { L: [ {} ] }, + { L: [ { a: {} } ] }, + ], function (expr, cb) { assertValidation({ TableName: 'abc', - Key: {a: expr}, + Key: { a: expr }, ConditionExpression: '', UpdateExpression: '', ExpressionAttributeNames: {}, @@ -211,119 +211,119 @@ describe('updateItem', function() { }, done) }) - it('should return ValidationException for invalid values in Key', function(done) { + it('should return ValidationException for invalid values in Key', function (done) { async.forEach([ - [{NULL: 'no'}, 'Null attribute value types must have the value of true'], - [{SS: []}, 'An string set may not be empty'], - [{NS: []}, 'An number set may not be empty'], - [{BS: []}, 'Binary sets should not be empty'], - [{SS: ['a', 'a']}, 'Input collection [a, a] contains duplicates.'], - [{BS: ['Yg==', 'Yg==']}, 'Input collection [Yg==, Yg==]of type BS contains duplicates.'], - ], function(expr, cb) { + [ { NULL: 'no' }, 'Null attribute value types must have the value of true' ], + [ { SS: [] }, 'An string set may not be empty' ], + [ { NS: [] }, 'An number set may not be empty' ], + [ { BS: [] }, 'Binary sets should not be empty' ], + [ { SS: [ 'a', 'a' ] }, 'Input collection [a, a] contains duplicates.' ], + [ { BS: [ 'Yg==', 'Yg==' ] }, 'Input collection [Yg==, Yg==]of type BS contains duplicates.' ], + ], function (expr, cb) { assertValidation({ TableName: 'abc', - Key: {a: expr[0]}, - Expected: {a: {}}, - AttributeUpdates: {a: {x: 'whatever'}}, + Key: { a: expr[0] }, + Expected: { a: {} }, + AttributeUpdates: { a: { x: 'whatever' } }, }, 'One or more parameter values were invalid: ' + expr[1], cb) }, done) }) - it('should return ValidationException for empty/invalid numbers in Key', function(done) { + it('should return ValidationException for empty/invalid numbers in Key', function (done) { async.forEach([ - [{S: '', N: ''}, 'The parameter cannot be converted to a numeric value'], - [{S: 'a', N: ''}, 'The parameter cannot be converted to a numeric value'], - [{S: 'a', N: 'b'}, 'The parameter cannot be converted to a numeric value: b'], - [{NS: ['1', '']}, 'The parameter cannot be converted to a numeric value'], - [{NS: ['1', 'b']}, 'The parameter cannot be converted to a numeric value: b'], - [{NS: ['1', '1']}, 'Input collection contains duplicates'], - [{N: '123456789012345678901234567890123456789'}, 'Attempting to store more than 38 significant digits in a Number'], - [{N: '-1.23456789012345678901234567890123456789'}, 'Attempting to store more than 38 significant digits in a Number'], - [{N: '1e126'}, 'Number overflow. Attempting to store a number with magnitude larger than supported range'], - [{N: '-1e126'}, 'Number overflow. Attempting to store a number with magnitude larger than supported range'], - [{N: '1e-131'}, 'Number underflow. Attempting to store a number with magnitude smaller than supported range'], - [{N: '-1e-131'}, 'Number underflow. Attempting to store a number with magnitude smaller than supported range'], - ], function(expr, cb) { - assertValidation({TableName: 'abc', Key: {a: expr[0]}}, expr[1], cb) + [ { S: '', N: '' }, 'The parameter cannot be converted to a numeric value' ], + [ { S: 'a', N: '' }, 'The parameter cannot be converted to a numeric value' ], + [ { S: 'a', N: 'b' }, 'The parameter cannot be converted to a numeric value: b' ], + [ { NS: [ '1', '' ] }, 'The parameter cannot be converted to a numeric value' ], + [ { NS: [ '1', 'b' ] }, 'The parameter cannot be converted to a numeric value: b' ], + [ { NS: [ '1', '1' ] }, 'Input collection contains duplicates' ], + [ { N: '123456789012345678901234567890123456789' }, 'Attempting to store more than 38 significant digits in a Number' ], + [ { N: '-1.23456789012345678901234567890123456789' }, 'Attempting to store more than 38 significant digits in a Number' ], + [ { N: '1e126' }, 'Number overflow. Attempting to store a number with magnitude larger than supported range' ], + [ { N: '-1e126' }, 'Number overflow. Attempting to store a number with magnitude larger than supported range' ], + [ { N: '1e-131' }, 'Number underflow. Attempting to store a number with magnitude smaller than supported range' ], + [ { N: '-1e-131' }, 'Number underflow. Attempting to store a number with magnitude smaller than supported range' ], + ], function (expr, cb) { + assertValidation({ TableName: 'abc', Key: { a: expr[0] } }, expr[1], cb) }, done) }) - it('should return ValidationException for multiple datatypes in Key', function(done) { - assertValidation({TableName: 'abc', Key: {'a': {S: 'a', N: '1'}}}, + it('should return ValidationException for multiple datatypes in Key', function (done) { + assertValidation({ TableName: 'abc', Key: { 'a': { S: 'a', N: '1' } } }, 'Supplied AttributeValue has more than one datatypes set, must contain exactly one of the supported datatypes', done) }) - it('should return ValidationException if update has no value', function(done) { + it('should return ValidationException if update has no value', function (done) { assertValidation({ TableName: 'abc', Key: {}, - Expected: {a: {}}, - AttributeUpdates: {a: {x: 'whatever'}}, + Expected: { a: {} }, + AttributeUpdates: { a: { x: 'whatever' } }, }, 'One or more parameter values were invalid: ' + 'Only DELETE action is allowed when no attribute value is specified', done) }) - it('should return ValidationException if trying to delete incorrect types', function(done) { + it('should return ValidationException if trying to delete incorrect types', function (done) { async.forEach([ - {S: '1'}, - {N: '1'}, - {B: 'Yg=='}, - {NULL: true}, - {BOOL: true}, - {M: {}}, - {L: []}, - ], function(val, cb) { + { S: '1' }, + { N: '1' }, + { B: 'Yg==' }, + { NULL: true }, + { BOOL: true }, + { M: {} }, + { L: [] }, + ], function (val, cb) { assertValidation({ TableName: 'abc', Key: {}, - AttributeUpdates: {a: {Action: 'DELETE', Value: val}}, + AttributeUpdates: { a: { Action: 'DELETE', Value: val } }, }, 'One or more parameter values were invalid: ' + 'DELETE action with value is not supported for the type ' + Object.keys(val)[0], cb) }, done) }) - it('should return ValidationException if trying to add incorrect types', function(done) { + it('should return ValidationException if trying to add incorrect types', function (done) { async.forEach([ - {S: '1'}, - {B: 'Yg=='}, - {NULL: true}, - {BOOL: true}, - {M: {}}, - ], function(val, cb) { + { S: '1' }, + { B: 'Yg==' }, + { NULL: true }, + { BOOL: true }, + { M: {} }, + ], function (val, cb) { assertValidation({ TableName: 'abc', Key: {}, - AttributeUpdates: {a: {Action: 'ADD', Value: val}}, + AttributeUpdates: { a: { Action: 'ADD', Value: val } }, }, 'One or more parameter values were invalid: ' + 'ADD action is not supported for the type ' + Object.keys(val)[0], cb) }, done) }) - it('should return ValidationException if trying to add type B', function(done) { + it('should return ValidationException if trying to add type B', function (done) { assertValidation({ TableName: 'abc', Key: {}, - AttributeUpdates: {a: {Action: 'ADD', Value: {B: 'Yg=='}}}, + AttributeUpdates: { a: { Action: 'ADD', Value: { B: 'Yg==' } } }, }, 'One or more parameter values were invalid: ' + 'ADD action is not supported for the type B', done) }) - it('should return ValidationException if no value and no exists', function(done) { - assertValidation({TableName: 'abc', Key: {}, Expected: {a: {}}}, + it('should return ValidationException if no value and no exists', function (done) { + assertValidation({ TableName: 'abc', Key: {}, Expected: { a: {} } }, 'One or more parameter values were invalid: Value must be provided when Exists is null for Attribute: a', done) }) - it('should return ValidationException for Exists true with no value', function(done) { - assertValidation({TableName: 'abc', Key: {}, Expected: {a: {Exists: true}}}, + it('should return ValidationException for Exists true with no value', function (done) { + assertValidation({ TableName: 'abc', Key: {}, Expected: { a: { Exists: true } } }, 'One or more parameter values were invalid: Value must be provided when Exists is true for Attribute: a', done) }) - it('should return ValidationException for Exists false with value', function(done) { - assertValidation({TableName: 'abc', Key: {}, Expected: {a: {Exists: false, Value: {S: 'a'}}}}, + it('should return ValidationException for Exists false with value', function (done) { + assertValidation({ TableName: 'abc', Key: {}, Expected: { a: { Exists: false, Value: { S: 'a' } } } }, 'One or more parameter values were invalid: Value cannot be used when Exists is false for Attribute: a', done) }) - it('should return ValidationException for empty ExpressionAttributeNames', function(done) { + it('should return ValidationException for empty ExpressionAttributeNames', function (done) { assertValidation({ TableName: 'abc', Key: {}, @@ -334,18 +334,18 @@ describe('updateItem', function() { }, 'ExpressionAttributeNames must not be empty', done) }) - it('should return ValidationException for invalid ExpressionAttributeNames', function(done) { + it('should return ValidationException for invalid ExpressionAttributeNames', function (done) { assertValidation({ TableName: 'abc', Key: {}, - ExpressionAttributeNames: {'a': 'a'}, + ExpressionAttributeNames: { 'a': 'a' }, ExpressionAttributeValues: {}, ConditionExpression: '', UpdateExpression: '', }, 'ExpressionAttributeNames contains invalid key: Syntax error; key: "a"', done) }) - it('should return ValidationException for empty ExpressionAttributeValues', function(done) { + it('should return ValidationException for empty ExpressionAttributeValues', function (done) { assertValidation({ TableName: 'abc', Key: {}, @@ -355,28 +355,28 @@ describe('updateItem', function() { }, 'ExpressionAttributeValues must not be empty', done) }) - it('should return ValidationException for invalid keys in ExpressionAttributeValues', function(done) { + it('should return ValidationException for invalid keys in ExpressionAttributeValues', function (done) { assertValidation({ TableName: 'abc', Key: {}, - ExpressionAttributeValues: {':b': {a: ''}, 'b': {S: 'a'}}, + ExpressionAttributeValues: { ':b': { a: '' }, 'b': { S: 'a' } }, ConditionExpression: '', UpdateExpression: '', }, 'ExpressionAttributeValues contains invalid key: Syntax error; key: "b"', done) }) - it('should return ValidationException for unsupported datatype in ExpressionAttributeValues', function(done) { + it('should return ValidationException for unsupported datatype in ExpressionAttributeValues', function (done) { async.forEach([ {}, - {a: ''}, - {M: {a: {}}}, - {L: [{}]}, - {L: [{a: {}}]}, - ], function(expr, cb) { + { a: '' }, + { M: { a: {} } }, + { L: [ {} ] }, + { L: [ { a: {} } ] }, + ], function (expr, cb) { assertValidation({ TableName: 'abc', Key: {}, - ExpressionAttributeValues: {':b': expr}, + ExpressionAttributeValues: { ':b': expr }, ConditionExpression: '', UpdateExpression: '', }, 'ExpressionAttributeValues contains invalid value: ' + @@ -384,19 +384,19 @@ describe('updateItem', function() { }, done) }) - it('should return ValidationException for invalid values in ExpressionAttributeValues', function(done) { + it('should return ValidationException for invalid values in ExpressionAttributeValues', function (done) { async.forEach([ - [{NULL: 'no'}, 'Null attribute value types must have the value of true'], - [{SS: []}, 'An string set may not be empty'], - [{NS: []}, 'An number set may not be empty'], - [{BS: []}, 'Binary sets should not be empty'], - [{SS: ['a', 'a']}, 'Input collection [a, a] contains duplicates.'], - [{BS: ['Yg==', 'Yg==']}, 'Input collection [Yg==, Yg==]of type BS contains duplicates.'], - ], function(expr, cb) { + [ { NULL: 'no' }, 'Null attribute value types must have the value of true' ], + [ { SS: [] }, 'An string set may not be empty' ], + [ { NS: [] }, 'An number set may not be empty' ], + [ { BS: [] }, 'Binary sets should not be empty' ], + [ { SS: [ 'a', 'a' ] }, 'Input collection [a, a] contains duplicates.' ], + [ { BS: [ 'Yg==', 'Yg==' ] }, 'Input collection [Yg==, Yg==]of type BS contains duplicates.' ], + ], function (expr, cb) { assertValidation({ TableName: 'abc', Key: {}, - ExpressionAttributeValues: {':b': expr[0]}, + ExpressionAttributeValues: { ':b': expr[0] }, ConditionExpression: '', UpdateExpression: '', }, 'ExpressionAttributeValues contains invalid value: ' + @@ -404,36 +404,36 @@ describe('updateItem', function() { }, done) }) - it('should return ValidationException for empty/invalid numbers in ExpressionAttributeValues', function(done) { + it('should return ValidationException for empty/invalid numbers in ExpressionAttributeValues', function (done) { async.forEach([ - [{S: 'a', N: ''}, 'The parameter cannot be converted to a numeric value'], - [{S: 'a', N: 'b'}, 'The parameter cannot be converted to a numeric value: b'], - [{NS: ['1', '']}, 'The parameter cannot be converted to a numeric value'], - [{NS: ['1', 'b']}, 'The parameter cannot be converted to a numeric value: b'], - [{NS: ['1', '1']}, 'Input collection contains duplicates'], - ], function(expr, cb) { + [ { S: 'a', N: '' }, 'The parameter cannot be converted to a numeric value' ], + [ { S: 'a', N: 'b' }, 'The parameter cannot be converted to a numeric value: b' ], + [ { NS: [ '1', '' ] }, 'The parameter cannot be converted to a numeric value' ], + [ { NS: [ '1', 'b' ] }, 'The parameter cannot be converted to a numeric value: b' ], + [ { NS: [ '1', '1' ] }, 'Input collection contains duplicates' ], + ], function (expr, cb) { assertValidation({ TableName: 'abc', Key: {}, - ExpressionAttributeValues: {':b': expr[0]}, + ExpressionAttributeValues: { ':b': expr[0] }, ConditionExpression: '', UpdateExpression: '', }, 'ExpressionAttributeValues contains invalid value: ' + expr[1] + ' for key :b', cb) }, done) }) - it('should return ValidationException for multiple datatypes in ExpressionAttributeValues', function(done) { + it('should return ValidationException for multiple datatypes in ExpressionAttributeValues', function (done) { assertValidation({ TableName: 'abc', Key: {}, - ExpressionAttributeValues: {':b': {S: 'a', N: '1'}}, + ExpressionAttributeValues: { ':b': { S: 'a', N: '1' } }, ConditionExpression: '', UpdateExpression: '', }, 'ExpressionAttributeValues contains invalid value: ' + 'Supplied AttributeValue has more than one datatypes set, must contain exactly one of the supported datatypes for key :b', done) }) - it('should return ValidationException for empty UpdateExpression', function(done) { + it('should return ValidationException for empty UpdateExpression', function (done) { assertValidation({ TableName: 'abc', Key: {}, @@ -442,7 +442,7 @@ describe('updateItem', function() { }, 'Invalid UpdateExpression: The expression can not be empty;', done) }) - it('should return ValidationException for empty ConditionExpression', function(done) { + it('should return ValidationException for empty ConditionExpression', function (done) { assertValidation({ TableName: 'abc', Key: {}, @@ -450,7 +450,7 @@ describe('updateItem', function() { }, 'Invalid ConditionExpression: The expression can not be empty;', done) }) - it('should return ValidationException for syntax errors in UpdateExpression', function(done) { + it('should return ValidationException for syntax errors in UpdateExpression', function (done) { async.forEach([ 'whatever', 'set a', @@ -486,7 +486,7 @@ describe('updateItem', function() { 'set a = (b.c)[0] + e', 'set a = b + c + d', // 'set a = ((b.c.d)+(e))', - ], function(updateOpts, cb) { + ], function (updateOpts, cb) { assertValidation({ TableName: 'abc', Key: {}, @@ -495,360 +495,360 @@ describe('updateItem', function() { }, done) }) - it('should return ValidationException for reserved keywords', function(done) { + it('should return ValidationException for reserved keywords', function (done) { async.forEach([ - [' set #c = :c set abOrt = true ', 'abOrt'], - [' remove Absolute ', 'Absolute'], - ], function(expr, cb) { + [ ' set #c = :c set abOrt = true ', 'abOrt' ], + [ ' remove Absolute ', 'Absolute' ], + ], function (expr, cb) { assertValidation({ TableName: 'abc', Key: {}, UpdateExpression: expr[0], - ExpressionAttributeValues: {':a': {S: 'a'}, ':b': {S: 'a'}}, - ExpressionAttributeNames: {'#a': 'a', '#b': 'b'}, + ExpressionAttributeValues: { ':a': { S: 'a' }, ':b': { S: 'a' } }, + ExpressionAttributeNames: { '#a': 'a', '#b': 'b' }, }, 'Invalid UpdateExpression: Attribute name is a reserved keyword; reserved keyword: ' + expr[1], cb) }, done) }) - it('should return ValidationException for invalid functions in UpdateExpression', function(done) { + it('should return ValidationException for invalid functions in UpdateExpression', function (done) { async.forEach([ 'set #c = if_not_exist(:c) set c = d', - ], function(updateOpts, cb) { + ], function (updateOpts, cb) { assertValidation({ TableName: 'abc', Key: {}, UpdateExpression: updateOpts, - ExpressionAttributeValues: {':a': {S: 'a'}, ':b': {S: 'a'}}, - ExpressionAttributeNames: {'#a': 'a', '#b': 'b'}, + ExpressionAttributeValues: { ':a': { S: 'a' }, ':b': { S: 'a' } }, + ExpressionAttributeNames: { '#a': 'a', '#b': 'b' }, }, /^Invalid UpdateExpression: Invalid function name; function: /, cb) }, done) }) - it('should return ValidationException for multiple sections', function(done) { + it('should return ValidationException for multiple sections', function (done) { async.forEach([ - ['set a = #c set c = :d', 'SET'], - ['remove #d set a = b remove e', 'REMOVE'], - ['add #d :e set a = b add e :f', 'ADD'], - ['delete #d :e set a = b delete #e :f', 'DELETE'], - ], function(expr, cb) { + [ 'set a = #c set c = :d', 'SET' ], + [ 'remove #d set a = b remove e', 'REMOVE' ], + [ 'add #d :e set a = b add e :f', 'ADD' ], + [ 'delete #d :e set a = b delete #e :f', 'DELETE' ], + ], function (expr, cb) { assertValidation({ TableName: 'abc', Key: {}, UpdateExpression: expr[0], - ExpressionAttributeValues: {':a': {S: 'a'}, ':b': {S: 'a'}}, - ExpressionAttributeNames: {'#a': 'a', '#b': 'b'}, + ExpressionAttributeValues: { ':a': { S: 'a' }, ':b': { S: 'a' } }, + ExpressionAttributeNames: { '#a': 'a', '#b': 'b' }, }, 'Invalid UpdateExpression: The "' + expr[1] + '" section can only be used once in an update expression;', cb) }, done) }) - it('should return ValidationException for undefined attribute names in UpdateExpression', function(done) { + it('should return ValidationException for undefined attribute names in UpdateExpression', function (done) { async.forEach([ 'SET #c = if_not_exists(:c)', - ], function(updateOpts, cb) { + ], function (updateOpts, cb) { assertValidation({ TableName: 'abc', Key: {}, UpdateExpression: updateOpts, - ExpressionAttributeValues: {':a': {S: 'a'}, ':b': {S: 'a'}}, - ExpressionAttributeNames: {'#a': 'a', '#b': 'b'}, + ExpressionAttributeValues: { ':a': { S: 'a' }, ':b': { S: 'a' } }, + ExpressionAttributeNames: { '#a': 'a', '#b': 'b' }, }, /^Invalid UpdateExpression: An expression attribute name used in the document path is not defined; attribute name: #/, cb) }, done) }) - it('should return ValidationException for undefined attribute values in UpdateExpression', function(done) { + it('should return ValidationException for undefined attribute values in UpdateExpression', function (done) { async.forEach([ 'SET #a = if_not_exists(:c)', - ], function(updateOpts, cb) { + ], function (updateOpts, cb) { assertValidation({ TableName: 'abc', Key: {}, UpdateExpression: updateOpts, - ExpressionAttributeValues: {':a': {S: 'a'}, ':b': {S: 'a'}}, - ExpressionAttributeNames: {'#a': 'a', '#b': 'b'}, + ExpressionAttributeValues: { ':a': { S: 'a' }, ':b': { S: 'a' } }, + ExpressionAttributeNames: { '#a': 'a', '#b': 'b' }, }, /^Invalid UpdateExpression: An expression attribute value used in expression is not defined; attribute value: :/, cb) }, done) }) - it('should return ValidationException for overlapping paths in UpdateExpression', function(done) { + it('should return ValidationException for overlapping paths in UpdateExpression', function (done) { async.forEach([ - ['set d[1] = a, d.b = a, c[1].a = a, #c = if_not_exists(a)', '[c, [1], a]', '[c]'], + [ 'set d[1] = a, d.b = a, c[1].a = a, #c = if_not_exists(a)', '[c, [1], a]', '[c]' ], // TODO: This changed at some point, now conflicts with [[3]] instead of [c]? // ['set c.b.#c = a, c = a, #d = a', '[c, b, c]', '[[3]]'], // TODO: This changed at some point, now conflicts with [[3]] instead of [a]? // ['set a = b remove a, #c, #d', '[a]', '[[3]]'], - ['set #c[3].#d = a, #c[3] = a', '[c, [3], [3]]', '[c, [3]]'], + [ 'set #c[3].#d = a, #c[3] = a', '[c, [3], [3]]', '[c, [3]]' ], // TODO: This changed at some point, now conflicts with [[3]] instead of [c, a]? // ['remove c, #c.a, #d', '[c]', '[[3]]'], // TODO: This changed at some point, now conflicts with [[3]] instead of [a]? // ['remove a, #c, a, #d', '[a]', '[[3]]'], - ], function(expr, cb) { + ], function (expr, cb) { assertValidation({ TableName: 'abc', Key: {}, UpdateExpression: expr[0], - ExpressionAttributeNames: {'#c': 'c', '#d': '[3]'}, + ExpressionAttributeNames: { '#c': 'c', '#d': '[3]' }, }, 'Invalid UpdateExpression: Two document paths overlap with each other; ' + 'must remove or rewrite one of these paths; path one: ' + expr[1] + ', path two: ' + expr[2], cb) }, done) }) - it('should return ValidationException for conflicting paths in UpdateExpression', function(done) { + it('should return ValidationException for conflicting paths in UpdateExpression', function (done) { async.forEach([ - ['set #c[3].#d = a, #c.#d[3] = if_not_exists(a)', '[c, [3], [3]]', '[c, [3], [3]]'], - ['remove a.#c set a[1] = #d', '[a, c]', '[a, [1]]'], - ], function(expr, cb) { + [ 'set #c[3].#d = a, #c.#d[3] = if_not_exists(a)', '[c, [3], [3]]', '[c, [3], [3]]' ], + [ 'remove a.#c set a[1] = #d', '[a, c]', '[a, [1]]' ], + ], function (expr, cb) { assertValidation({ TableName: 'abc', Key: {}, UpdateExpression: expr[0], - ExpressionAttributeNames: {'#b': 'b', '#c': 'c', '#d': '[3]'}, + ExpressionAttributeNames: { '#b': 'b', '#c': 'c', '#d': '[3]' }, }, 'Invalid UpdateExpression: Two document paths conflict with each other; ' + 'must remove or rewrite one of these paths; path one: ' + expr[1] + ', path two: ' + expr[2], cb) }, done) }) - it('should return ValidationException for incorrect types in UpdateExpression', function(done) { + it('should return ValidationException for incorrect types in UpdateExpression', function (done) { async.forEach([ - ['set b = list_append(:a, a), c = if_not_exists(a) add a.b :a', {S: 'a'}, 'ADD', 'STRING'], - ['delete a.b :a', {S: 'a'}, 'DELETE', 'STRING'], - ['add a.b :a', {NULL: '1'}, 'ADD', 'NULL'], - ['delete a.b :a', {NULL: 'yes'}, 'DELETE', 'NULL'], - ['add a.b :a', {BOOL: '0'}, 'ADD', 'BOOLEAN'], - ['delete a.b :a', {BOOL: 'false'}, 'DELETE', 'BOOLEAN'], - ['add a.b :a', {B: 'YQ=='}, 'ADD', 'BINARY'], - ['delete a.b :a', {B: 'YQ=='}, 'DELETE', 'BINARY'], - ['add a.b :a', {M: {a: {L: [{N: '1'}]}}}, 'ADD', 'MAP'], - ['delete a.b :a', {M: {a: {L: [{N: '1'}]}}}, 'DELETE', 'MAP'], - ['add a.b :a', {L: [{N: '1'}]}, 'ADD', 'LIST'], - ['delete a.b :a', {L: [{N: '1'}]}, 'DELETE', 'LIST'], - ['delete a.b :a', {N: '1'}, 'DELETE', 'NUMBER'], - ], function(updateOpts, cb) { + [ 'set b = list_append(:a, a), c = if_not_exists(a) add a.b :a', { S: 'a' }, 'ADD', 'STRING' ], + [ 'delete a.b :a', { S: 'a' }, 'DELETE', 'STRING' ], + [ 'add a.b :a', { NULL: '1' }, 'ADD', 'NULL' ], + [ 'delete a.b :a', { NULL: 'yes' }, 'DELETE', 'NULL' ], + [ 'add a.b :a', { BOOL: '0' }, 'ADD', 'BOOLEAN' ], + [ 'delete a.b :a', { BOOL: 'false' }, 'DELETE', 'BOOLEAN' ], + [ 'add a.b :a', { B: 'YQ==' }, 'ADD', 'BINARY' ], + [ 'delete a.b :a', { B: 'YQ==' }, 'DELETE', 'BINARY' ], + [ 'add a.b :a', { M: { a: { L: [ { N: '1' } ] } } }, 'ADD', 'MAP' ], + [ 'delete a.b :a', { M: { a: { L: [ { N: '1' } ] } } }, 'DELETE', 'MAP' ], + [ 'add a.b :a', { L: [ { N: '1' } ] }, 'ADD', 'LIST' ], + [ 'delete a.b :a', { L: [ { N: '1' } ] }, 'DELETE', 'LIST' ], + [ 'delete a.b :a', { N: '1' }, 'DELETE', 'NUMBER' ], + ], function (updateOpts, cb) { assertValidation({ TableName: 'abc', Key: {}, UpdateExpression: updateOpts[0], - ExpressionAttributeValues: {':a': updateOpts[1], ':b': {S: 'a'}}, + ExpressionAttributeValues: { ':a': updateOpts[1], ':b': { S: 'a' } }, }, 'Invalid UpdateExpression: Incorrect operand type for operator or function; operator: ' + updateOpts[2] + ', operand type: ' + updateOpts[3], cb) }, done) }) - it('should return ValidationException for incorrect number of operands to functions in UpdateExpression', function(done) { + it('should return ValidationException for incorrect number of operands to functions in UpdateExpression', function (done) { async.forEach([ 'set a = if_not_exists(c)', 'set a = list_append(c)', - ], function(expression, cb) { + ], function (expression, cb) { assertValidation({ TableName: 'abc', Key: {}, UpdateExpression: expression, - ExpressionAttributeValues: {':a': {S: 'a'}, ':b': {S: 'a'}}, - ExpressionAttributeNames: {'#a': 'a', '#b': 'b'}, + ExpressionAttributeValues: { ':a': { S: 'a' }, ':b': { S: 'a' } }, + ExpressionAttributeNames: { '#a': 'a', '#b': 'b' }, }, /^Invalid UpdateExpression: Incorrect number of operands for operator or function; operator or function: [a-z_]+, number of operands: \d+$/, cb) }, done) }) - it('should return ValidationException for incorrect operand path type to functions in UpdateExpression', function(done) { + it('should return ValidationException for incorrect operand path type to functions in UpdateExpression', function (done) { async.forEach([ 'set a = if_not_exists(:a, c)', 'set a = if_not_exists(if_not_exists(a, b), c)', - ], function(expression, cb) { + ], function (expression, cb) { assertValidation({ TableName: 'abc', Key: {}, UpdateExpression: expression, - ExpressionAttributeValues: {':a': {S: 'a'}, ':b': {S: 'a'}}, - ExpressionAttributeNames: {'#a': 'a', '#b': 'b'}, + ExpressionAttributeValues: { ':a': { S: 'a' }, ':b': { S: 'a' } }, + ExpressionAttributeNames: { '#a': 'a', '#b': 'b' }, }, /^Invalid UpdateExpression: Operator or function requires a document path; operator or function: [a-z_]+$/, cb) }, done) }) - it('should return ValidationException for incorrect types to functions in UpdateExpression', function(done) { + it('should return ValidationException for incorrect types to functions in UpdateExpression', function (done) { async.forEach([ - ['set a = list_append(:a, a)', 'list_append', 'S'], - ['set a = list_append(a, :b)', 'list_append', 'N'], - ['set a = list_append(:c, a)', 'list_append', 'B'], - ['set a = list_append(:d, a)', 'list_append', 'BOOL'], - ['set a = list_append(:e, a)', 'list_append', 'NULL'], - ['set a = list_append(:f, a)', 'list_append', 'SS'], - ['set a = list_append(:g, a)', 'list_append', 'NS'], - ['set a = list_append(:h, a)', 'list_append', 'BS'], - ['set a = list_append(:i, a)', 'list_append', 'M'], - ['set a = a + :a', '+', 'S'], - ['set a = :a + :c', '+', 'S'], - ['set a = :c + a', '+', 'B'], - ['set a = a + :d', '+', 'BOOL'], - ['set a = a + :e', '+', 'NULL'], - ['set a = a + :f', '+', 'SS'], - ['set a = a + :g', '+', 'NS'], - ['set a = a + :h', '+', 'BS'], - ['set a = a + :i', '+', 'M'], - ['set a = a + :j', '+', 'L'], - ['set a = a - :a', '-', 'S'], - ['set a = :a - :c', '-', 'S'], - ['set a = :c - a', '-', 'B'], - ['set a = a - :d', '-', 'BOOL'], - ['set a = a - :e', '-', 'NULL'], - ['set a = a - :f', '-', 'SS'], - ['set a = a - :g', '-', 'NS'], - ['set a = a - :h', '-', 'BS'], - ['set a = a - :i', '-', 'M'], - ['set a = a - :j', '-', 'L'], - ], function(expr, cb) { + [ 'set a = list_append(:a, a)', 'list_append', 'S' ], + [ 'set a = list_append(a, :b)', 'list_append', 'N' ], + [ 'set a = list_append(:c, a)', 'list_append', 'B' ], + [ 'set a = list_append(:d, a)', 'list_append', 'BOOL' ], + [ 'set a = list_append(:e, a)', 'list_append', 'NULL' ], + [ 'set a = list_append(:f, a)', 'list_append', 'SS' ], + [ 'set a = list_append(:g, a)', 'list_append', 'NS' ], + [ 'set a = list_append(:h, a)', 'list_append', 'BS' ], + [ 'set a = list_append(:i, a)', 'list_append', 'M' ], + [ 'set a = a + :a', '+', 'S' ], + [ 'set a = :a + :c', '+', 'S' ], + [ 'set a = :c + a', '+', 'B' ], + [ 'set a = a + :d', '+', 'BOOL' ], + [ 'set a = a + :e', '+', 'NULL' ], + [ 'set a = a + :f', '+', 'SS' ], + [ 'set a = a + :g', '+', 'NS' ], + [ 'set a = a + :h', '+', 'BS' ], + [ 'set a = a + :i', '+', 'M' ], + [ 'set a = a + :j', '+', 'L' ], + [ 'set a = a - :a', '-', 'S' ], + [ 'set a = :a - :c', '-', 'S' ], + [ 'set a = :c - a', '-', 'B' ], + [ 'set a = a - :d', '-', 'BOOL' ], + [ 'set a = a - :e', '-', 'NULL' ], + [ 'set a = a - :f', '-', 'SS' ], + [ 'set a = a - :g', '-', 'NS' ], + [ 'set a = a - :h', '-', 'BS' ], + [ 'set a = a - :i', '-', 'M' ], + [ 'set a = a - :j', '-', 'L' ], + ], function (expr, cb) { assertValidation({ TableName: 'abc', Key: {}, UpdateExpression: expr[0], ExpressionAttributeValues: { - ':a': {S: 'a'}, - ':b': {N: '1'}, - ':c': {B: 'YQ=='}, - ':d': {BOOL: 'no'}, - ':e': {NULL: 'true'}, - ':f': {SS: ['a']}, - ':g': {NS: ['1']}, - ':h': {BS: ['YQ==']}, - ':i': {M: {}}, - ':j': {L: []}, + ':a': { S: 'a' }, + ':b': { N: '1' }, + ':c': { B: 'YQ==' }, + ':d': { BOOL: 'no' }, + ':e': { NULL: 'true' }, + ':f': { SS: [ 'a' ] }, + ':g': { NS: [ '1' ] }, + ':h': { BS: [ 'YQ==' ] }, + ':i': { M: {} }, + ':j': { L: [] }, }, - ExpressionAttributeNames: {'#a': 'a', '#b': 'b'}, + ExpressionAttributeNames: { '#a': 'a', '#b': 'b' }, }, 'Invalid UpdateExpression: Incorrect operand type for operator or function; ' + 'operator or function: ' + expr[1] + ', operand type: ' + expr[2], cb) }, done) }) - it('should return ValidationException for extra ExpressionAttributeNames', function(done) { + it('should return ValidationException for extra ExpressionAttributeNames', function (done) { assertValidation({ TableName: 'abc', Key: {}, UpdateExpression: 'remove a set b = list_append(b, if_not_exists(a, :a))', ConditionExpression: 'a = :b', - ExpressionAttributeValues: {':a': {S: 'a'}, ':b': {S: 'a'}}, - ExpressionAttributeNames: {'#a': 'a', '#b': 'b'}, + ExpressionAttributeValues: { ':a': { S: 'a' }, ':b': { S: 'a' } }, + ExpressionAttributeNames: { '#a': 'a', '#b': 'b' }, }, /^Value provided in ExpressionAttributeNames unused in expressions: keys: {(#a, #b|#b, #a)}$/, done) }) - it('should return ValidationException for extra ExpressionAttributeValues', function(done) { + it('should return ValidationException for extra ExpressionAttributeValues', function (done) { assertValidation({ TableName: 'abc', Key: {}, UpdateExpression: 'remove a', ConditionExpression: 'a = :b', - ExpressionAttributeValues: {':a': {S: 'a'}, ':b': {S: 'a'}, ':c': {S: 'a'}}, + ExpressionAttributeValues: { ':a': { S: 'a' }, ':b': { S: 'a' }, ':c': { S: 'a' } }, }, /^Value provided in ExpressionAttributeValues unused in expressions: keys: {(:c, :a|:a, :c)}$/, done) }) - it('should return ResourceNotFoundException if key is empty and table does not exist', function(done) { - assertNotFound({TableName: helpers.randomString(), Key: {}}, + it('should return ResourceNotFoundException if key is empty and table does not exist', function (done) { + assertNotFound({ TableName: helpers.randomString(), Key: {} }, 'Requested resource not found', done) }) - it('should return ValidationException if Key does not match schema', function(done) { + it('should return ValidationException if Key does not match schema', function (done) { async.forEach([ {}, - {b: {S: 'a'}}, - {a: {S: 'a'}, b: {S: 'a'}}, - {a: {B: 'abcd'}}, - {a: {N: '1'}}, - {a: {BOOL: true}}, - {a: {NULL: true}}, - {a: {SS: ['a']}}, - {a: {NS: ['1']}}, - {a: {BS: ['aaaa']}}, - {a: {M: {}}}, - {a: {L: []}}, - ], function(expr, cb) { - assertValidation({TableName: helpers.testHashTable, Key: expr}, + { b: { S: 'a' } }, + { a: { S: 'a' }, b: { S: 'a' } }, + { a: { B: 'abcd' } }, + { a: { N: '1' } }, + { a: { BOOL: true } }, + { a: { NULL: true } }, + { a: { SS: [ 'a' ] } }, + { a: { NS: [ '1' ] } }, + { a: { BS: [ 'aaaa' ] } }, + { a: { M: {} } }, + { a: { L: [] } }, + ], function (expr, cb) { + assertValidation({ TableName: helpers.testHashTable, Key: expr }, 'The provided key element does not match the schema', cb) }, done) }) - it('should return ValidationException if Key does not match range schema', function(done) { - assertValidation({TableName: helpers.testRangeTable, Key: {a: {S: 'a'}}}, + it('should return ValidationException if Key does not match range schema', function (done) { + assertValidation({ TableName: helpers.testRangeTable, Key: { a: { S: 'a' } } }, 'The provided key element does not match the schema', done) }) - it('should return ResourceNotFoundException if table is being created', function(done) { + it('should return ResourceNotFoundException if table is being created', function (done) { var table = { TableName: randomName(), - AttributeDefinitions: [{AttributeName: 'a', AttributeType: 'S'}], - KeySchema: [{KeyType: 'HASH', AttributeName: 'a'}], - ProvisionedThroughput: {ReadCapacityUnits: 1, WriteCapacityUnits: 1}, + AttributeDefinitions: [ { AttributeName: 'a', AttributeType: 'S' } ], + KeySchema: [ { KeyType: 'HASH', AttributeName: 'a' } ], + ProvisionedThroughput: { ReadCapacityUnits: 1, WriteCapacityUnits: 1 }, } - request(helpers.opts('CreateTable', table), function(err) { + request(helpers.opts('CreateTable', table), function (err) { if (err) return done(err) - assertNotFound({TableName: table.TableName, Key: {a: {S: 'a'}}}, + assertNotFound({ TableName: table.TableName, Key: { a: { S: 'a' } } }, 'Requested resource not found', done) helpers.deleteWhenActive(table.TableName) }) }) - it('should return ValidationException if trying to update key', function(done) { + it('should return ValidationException if trying to update key', function (done) { async.forEach([ - {AttributeUpdates: {a: {Value: {S: helpers.randomString()}}}}, - {UpdateExpression: 'add a.b :a', ExpressionAttributeValues: {':a': {N: '1'}}}, - {UpdateExpression: 'delete a :a', ExpressionAttributeValues: {':a': {NS: ['1']}}}, - {UpdateExpression: 'remove d set b = :a, a = :a', ExpressionAttributeValues: {':a': {N: '1'}}}, - {UpdateExpression: 'delete b :a remove a', ExpressionAttributeValues: {':a': {NS: ['1']}}}, - {UpdateExpression: 'set a = a.b + a[1]'}, - ], function(updateOpts, cb) { + { AttributeUpdates: { a: { Value: { S: helpers.randomString() } } } }, + { UpdateExpression: 'add a.b :a', ExpressionAttributeValues: { ':a': { N: '1' } } }, + { UpdateExpression: 'delete a :a', ExpressionAttributeValues: { ':a': { NS: [ '1' ] } } }, + { UpdateExpression: 'remove d set b = :a, a = :a', ExpressionAttributeValues: { ':a': { N: '1' } } }, + { UpdateExpression: 'delete b :a remove a', ExpressionAttributeValues: { ':a': { NS: [ '1' ] } } }, + { UpdateExpression: 'set a = a.b + a[1]' }, + ], function (updateOpts, cb) { updateOpts.TableName = helpers.testHashTable - updateOpts.Key = {a: {S: helpers.randomString()}} + updateOpts.Key = { a: { S: helpers.randomString() } } assertValidation(updateOpts, 'One or more parameter values were invalid: ' + 'Cannot update attribute a. This attribute is part of the key', cb) }, done) }) - it('should return ValidationException if trying to update range key', function(done) { + it('should return ValidationException if trying to update range key', function (done) { async.forEach([ - {AttributeUpdates: {d: {Value: {N: helpers.randomNumber()}}, b: {Value: {S: helpers.randomString()}}}}, - {UpdateExpression: 'set d[1] = :a add b.b :a', ExpressionAttributeValues: {':a': {N: '1'}}}, - ], function(updateOpts, cb) { + { AttributeUpdates: { d: { Value: { N: helpers.randomNumber() } }, b: { Value: { S: helpers.randomString() } } } }, + { UpdateExpression: 'set d[1] = :a add b.b :a', ExpressionAttributeValues: { ':a': { N: '1' } } }, + ], function (updateOpts, cb) { updateOpts.TableName = helpers.testRangeTable - updateOpts.Key = {a: {S: helpers.randomString()}, b: {S: helpers.randomString()}} + updateOpts.Key = { a: { S: helpers.randomString() }, b: { S: helpers.randomString() } } assertValidation(updateOpts, 'One or more parameter values were invalid: ' + 'Cannot update attribute b. This attribute is part of the key', cb) }, done) }) - it('should return ValidationException if trying to update wrong type on index', function(done) { + it('should return ValidationException if trying to update wrong type on index', function (done) { async.forEach([ - {AttributeUpdates: {d: {Value: {N: helpers.randomNumber()}}, c: {Value: {N: helpers.randomNumber()}}}}, - {UpdateExpression: 'set d.a = a add c :a', ExpressionAttributeValues: {':a': {N: '1'}}}, - {UpdateExpression: 'set e = c[1], c = a + :a', ExpressionAttributeValues: {':a': {N: '1'}}}, - ], function(updateOpts, cb) { + { AttributeUpdates: { d: { Value: { N: helpers.randomNumber() } }, c: { Value: { N: helpers.randomNumber() } } } }, + { UpdateExpression: 'set d.a = a add c :a', ExpressionAttributeValues: { ':a': { N: '1' } } }, + { UpdateExpression: 'set e = c[1], c = a + :a', ExpressionAttributeValues: { ':a': { N: '1' } } }, + ], function (updateOpts, cb) { updateOpts.TableName = helpers.testRangeTable - updateOpts.Key = {a: {S: helpers.randomString()}, b: {S: helpers.randomString()}} + updateOpts.Key = { a: { S: helpers.randomString() }, b: { S: helpers.randomString() } } assertValidation(updateOpts, new RegExp('^One or more parameter values were invalid: ' + 'Type mismatch for Index Key c Expected: S Actual: N IndexName: index\\d$'), cb) }, done) }) - it('should return ValidationException if trying to update index map', function(done) { + it('should return ValidationException if trying to update index map', function (done) { async.forEach([ - {UpdateExpression: 'add d.b :a', ExpressionAttributeValues: {':a': {N: '1'}}}, - {UpdateExpression: 'set d[1] = :a', ExpressionAttributeValues: {':a': {N: '1'}}}, - {UpdateExpression: 'set e = list_append(a, b), f = d[1]'}, - ], function(updateOpts, cb) { + { UpdateExpression: 'add d.b :a', ExpressionAttributeValues: { ':a': { N: '1' } } }, + { UpdateExpression: 'set d[1] = :a', ExpressionAttributeValues: { ':a': { N: '1' } } }, + { UpdateExpression: 'set e = list_append(a, b), f = d[1]' }, + ], function (updateOpts, cb) { updateOpts.TableName = helpers.testRangeTable - updateOpts.Key = {a: {S: helpers.randomString()}, b: {S: helpers.randomString()}} + updateOpts.Key = { a: { S: helpers.randomString() }, b: { S: helpers.randomString() } } assertValidation(updateOpts, 'Key attributes must be scalars; ' + 'list random access \'[]\' and map lookup \'.\' are not allowed: IndexKey: d', cb) }, done) }) - it('should return ValidationException if trying to delete/add incorrect types', function(done) { - var key = {a: {S: helpers.randomString()}} - var updates = {b: {Value: {SS: ['1']}}, c: {Value: {N: '1'}}, d: {Value: {NS: ['1']}}} - request(opts({TableName: helpers.testHashTable, Key: key, AttributeUpdates: updates}), function(err) { + it('should return ValidationException if trying to delete/add incorrect types', function (done) { + var key = { a: { S: helpers.randomString() } } + var updates = { b: { Value: { SS: [ '1' ] } }, c: { Value: { N: '1' } }, d: { Value: { NS: [ '1' ] } } } + request(opts({ TableName: helpers.testHashTable, Key: key, AttributeUpdates: updates }), function (err) { if (err) return done(err) async.forEach([ - {AttributeUpdates: {b: {Action: 'DELETE', Value: {NS: ['1']}}}}, - {AttributeUpdates: {b: {Action: 'DELETE', Value: {BS: ['YQ==']}}}}, - {AttributeUpdates: {c: {Action: 'DELETE', Value: {NS: ['1']}}}}, - {AttributeUpdates: {b: {Action: 'ADD', Value: {NS: ['1']}}}}, - {AttributeUpdates: {d: {Action: 'ADD', Value: {N: '1'}}}}, - ], function(updateOpts, cb) { + { AttributeUpdates: { b: { Action: 'DELETE', Value: { NS: [ '1' ] } } } }, + { AttributeUpdates: { b: { Action: 'DELETE', Value: { BS: [ 'YQ==' ] } } } }, + { AttributeUpdates: { c: { Action: 'DELETE', Value: { NS: [ '1' ] } } } }, + { AttributeUpdates: { b: { Action: 'ADD', Value: { NS: [ '1' ] } } } }, + { AttributeUpdates: { d: { Action: 'ADD', Value: { N: '1' } } } }, + ], function (updateOpts, cb) { updateOpts.TableName = helpers.testHashTable updateOpts.Key = key assertValidation(updateOpts, 'Type mismatch for attribute to update', cb) @@ -856,27 +856,27 @@ describe('updateItem', function() { }) }) - it('should return ValidationException if using expression to delete/add incorrect types', function(done) { - var key = {a: {S: helpers.randomString()}} + it('should return ValidationException if using expression to delete/add incorrect types', function (done) { + var key = { a: { S: helpers.randomString() } } request(opts({ TableName: helpers.testHashTable, Key: key, UpdateExpression: 'set b = :b, c = :c, d = :d', - ExpressionAttributeValues: {':b': {M: {a: {SS: ['1']}}}, ':c': {N: '1'}, ':d': {NS: ['1']}}, - }), function(err) { + ExpressionAttributeValues: { ':b': { M: { a: { SS: [ '1' ] } } }, ':c': { N: '1' }, ':d': { NS: [ '1' ] } }, + }), function (err) { if (err) return done(err) async.forEach([ - {UpdateExpression: 'delete d :a', ExpressionAttributeValues: {':a': {SS: ['1']}}}, - {UpdateExpression: 'delete b :a', ExpressionAttributeValues: {':a': {NS: ['1']}}}, - {UpdateExpression: 'delete b.a :a', ExpressionAttributeValues: {':a': {NS: ['1']}}}, - {UpdateExpression: 'delete b.a :a', ExpressionAttributeValues: {':a': {BS: ['YQ==']}}}, - {UpdateExpression: 'delete c :a', ExpressionAttributeValues: {':a': {NS: ['1']}}}, - {UpdateExpression: 'add b :a', ExpressionAttributeValues: {':a': {NS: ['1']}}}, - {UpdateExpression: 'add d :a', ExpressionAttributeValues: {':a': {N: '1'}}}, - {UpdateExpression: 'set e = a + :a', ExpressionAttributeValues: {':a': {N: '1'}}}, - {UpdateExpression: 'set e = b - :a', ExpressionAttributeValues: {':a': {N: '1'}}}, - {UpdateExpression: 'set e = list_append(d, if_not_exists(f, :a))', ExpressionAttributeValues: {':a': {L: []}}}, - ], function(updateOpts, cb) { + { UpdateExpression: 'delete d :a', ExpressionAttributeValues: { ':a': { SS: [ '1' ] } } }, + { UpdateExpression: 'delete b :a', ExpressionAttributeValues: { ':a': { NS: [ '1' ] } } }, + { UpdateExpression: 'delete b.a :a', ExpressionAttributeValues: { ':a': { NS: [ '1' ] } } }, + { UpdateExpression: 'delete b.a :a', ExpressionAttributeValues: { ':a': { BS: [ 'YQ==' ] } } }, + { UpdateExpression: 'delete c :a', ExpressionAttributeValues: { ':a': { NS: [ '1' ] } } }, + { UpdateExpression: 'add b :a', ExpressionAttributeValues: { ':a': { NS: [ '1' ] } } }, + { UpdateExpression: 'add d :a', ExpressionAttributeValues: { ':a': { N: '1' } } }, + { UpdateExpression: 'set e = a + :a', ExpressionAttributeValues: { ':a': { N: '1' } } }, + { UpdateExpression: 'set e = b - :a', ExpressionAttributeValues: { ':a': { N: '1' } } }, + { UpdateExpression: 'set e = list_append(d, if_not_exists(f, :a))', ExpressionAttributeValues: { ':a': { L: [] } } }, + ], function (updateOpts, cb) { updateOpts.TableName = helpers.testHashTable updateOpts.Key = key assertValidation(updateOpts, 'An operand in the update expression has an incorrect data type', cb) @@ -884,40 +884,40 @@ describe('updateItem', function() { }) }) - it('should return ValidationException if trying to reference non-existent attribute', function(done) { + it('should return ValidationException if trying to reference non-existent attribute', function (done) { async.forEach([ 'set c = b', 'set e = list_append(b, c)', - ], function(expr, cb) { + ], function (expr, cb) { assertValidation({ TableName: helpers.testHashTable, - Key: {a: {S: helpers.randomString()}}, + Key: { a: { S: helpers.randomString() } }, UpdateExpression: expr, }, 'The provided expression refers to an attribute that does not exist in the item', cb) }, done) }) - it('should return ValidationException if trying to update non-existent nested attribute in non-existent item', function(done) { + it('should return ValidationException if trying to update non-existent nested attribute in non-existent item', function (done) { async.forEach([ 'set b.a = a', 'set b[1] = a', - ], function(expression, cb) { + ], function (expression, cb) { assertValidation({ TableName: helpers.testHashTable, - Key: {a: {S: helpers.randomString()}}, + Key: { a: { S: helpers.randomString() } }, UpdateExpression: expression, }, 'The document path provided in the update expression is invalid for update', cb) }, done) }) - it('should return ValidationException if trying to update non-existent nested attribute in existing item', function(done) { - var key = {a: {S: helpers.randomString()}} + it('should return ValidationException if trying to update non-existent nested attribute in existing item', function (done) { + var key = { a: { S: helpers.randomString() } } request(opts({ TableName: helpers.testHashTable, Key: key, UpdateExpression: 'set b = a, c = :c, d = :d', - ExpressionAttributeValues: {':c': {M: {1: {S: 'a'}}}, ':d': {L: [{S: 'a'}, {S: 'b'}]}}, - }), function(err, res) { + ExpressionAttributeValues: { ':c': { M: { 1: { S: 'a' } } }, ':d': { L: [ { S: 'a' }, { S: 'b' } ] } }, + }), function (err, res) { if (err) return done(err) res.statusCode.should.equal(200) async.forEach([ @@ -945,32 +945,32 @@ describe('updateItem', function() { 'add y[1] :a set #1 = :a', 'add c[1] :a set #1 = :a', 'add d.#1 :a', - ], function(expression, cb) { + ], function (expression, cb) { assertValidation({ TableName: helpers.testHashTable, Key: key, UpdateExpression: expression, - ExpressionAttributeNames: {'#1': '1'}, - ExpressionAttributeValues: {':a': {SS: ['a']}}, + ExpressionAttributeNames: { '#1': '1' }, + ExpressionAttributeValues: { ':a': { SS: [ 'a' ] } }, }, 'The document path provided in the update expression is invalid for update', cb) }, done) }) }) - it('should return ValidationException if trying to update existing index', function(done) { - var key = {a: {S: helpers.randomString()}, b: {S: helpers.randomString()}} + it('should return ValidationException if trying to update existing index', function (done) { + var key = { a: { S: helpers.randomString() }, b: { S: helpers.randomString() } } request(opts({ TableName: helpers.testRangeTable, Key: key, UpdateExpression: 'set e = :a', - ExpressionAttributeValues: {':a': {N: '1'}}, - }), function(err, res) { + ExpressionAttributeValues: { ':a': { N: '1' } }, + }), function (err, res) { if (err) return done(err) res.statusCode.should.equal(200) async.forEach([ - {UpdateExpression: 'set c = e'}, - {UpdateExpression: 'set d = e'}, - ], function(updateOpts, cb) { + { UpdateExpression: 'set c = e' }, + { UpdateExpression: 'set d = e' }, + ], function (updateOpts, cb) { updateOpts.TableName = helpers.testRangeTable updateOpts.Key = key assertValidation(updateOpts, 'The update expression attempted to update the secondary index key to unsupported type', cb) @@ -978,52 +978,52 @@ describe('updateItem', function() { }) }) - it('should return ValidationException if update item is too big', function(done) { - var key = {a: {S: helpers.randomString()}} + it('should return ValidationException if update item is too big', function (done) { + var key = { a: { S: helpers.randomString() } } var updates = { - b: {Action: 'PUT', Value: {S: new Array(helpers.MAX_SIZE).join('a')}}, - c: {Action: 'PUT', Value: {N: new Array(38 + 1).join('1') + new Array(89).join('0')}}, + b: { Action: 'PUT', Value: { S: new Array(helpers.MAX_SIZE).join('a') } }, + c: { Action: 'PUT', Value: { N: new Array(38 + 1).join('1') + new Array(89).join('0') } }, } - assertValidation({TableName: helpers.testHashTable, Key: key, AttributeUpdates: updates}, + assertValidation({ TableName: helpers.testHashTable, Key: key, AttributeUpdates: updates }, 'Item size to update has exceeded the maximum allowed size', done) }) }) - describe('functionality', function() { - it('should return ConditionalCheckFailedException if expecting non-existent key to exist', function(done) { + describe('functionality', function () { + it('should return ConditionalCheckFailedException if expecting non-existent key to exist', function (done) { async.forEach([ - {Expected: {a: {Value: {S: helpers.randomString()}}}}, - {Expected: {a: {ComparisonOperator: 'NOT_NULL'}}}, - {ConditionExpression: 'a = :a', ExpressionAttributeValues: {':a': {S: helpers.randomString()}}}, - {ConditionExpression: '#a = :a', ExpressionAttributeNames: {'#a': 'a'}, ExpressionAttributeValues: {':a': {S: helpers.randomString()}}}, - {ConditionExpression: 'attribute_exists(a)'}, - {ConditionExpression: 'attribute_exists(#a)', ExpressionAttributeNames: {'#a': 'a'}}, - ], function(updateOpts, cb) { + { Expected: { a: { Value: { S: helpers.randomString() } } } }, + { Expected: { a: { ComparisonOperator: 'NOT_NULL' } } }, + { ConditionExpression: 'a = :a', ExpressionAttributeValues: { ':a': { S: helpers.randomString() } } }, + { ConditionExpression: '#a = :a', ExpressionAttributeNames: { '#a': 'a' }, ExpressionAttributeValues: { ':a': { S: helpers.randomString() } } }, + { ConditionExpression: 'attribute_exists(a)' }, + { ConditionExpression: 'attribute_exists(#a)', ExpressionAttributeNames: { '#a': 'a' } }, + ], function (updateOpts, cb) { updateOpts.TableName = helpers.testHashTable - updateOpts.Key = {a: {S: helpers.randomString()}} + updateOpts.Key = { a: { S: helpers.randomString() } } assertConditional(updateOpts, cb) }, done) }) - it('should just add item with key if no action', function(done) { - var key = {a: {S: helpers.randomString()}} - request(opts({TableName: helpers.testHashTable, Key: key}), function(err, res) { + it('should just add item with key if no action', function (done) { + var key = { a: { S: helpers.randomString() } } + request(opts({ TableName: helpers.testHashTable, Key: key }), function (err, res) { if (err) return done(err) res.statusCode.should.equal(200) res.body.should.eql({}) - request(helpers.opts('GetItem', {TableName: helpers.testHashTable, Key: key, ConsistentRead: true}), function(err, res) { + request(helpers.opts('GetItem', { TableName: helpers.testHashTable, Key: key, ConsistentRead: true }), function (err, res) { if (err) return done(err) res.statusCode.should.equal(200) - res.body.should.eql({Item: key}) + res.body.should.eql({ Item: key }) done() }) }) }) - it('should return empty when there are no old values', function(done) { - var key = {a: {S: helpers.randomString()}} - request(opts({TableName: helpers.testHashTable, Key: key, ReturnValues: 'ALL_OLD'}), function(err, res) { + it('should return empty when there are no old values', function (done) { + var key = { a: { S: helpers.randomString() } } + request(opts({ TableName: helpers.testHashTable, Key: key, ReturnValues: 'ALL_OLD' }), function (err, res) { if (err) return done(err) res.statusCode.should.equal(200) res.body.should.eql({}) @@ -1031,192 +1031,192 @@ describe('updateItem', function() { }) }) - it('should return all old values when they exist', function(done) { - var key = {a: {S: helpers.randomString()}}, updates = {b: {Value: {S: 'a'}}} - request(opts({TableName: helpers.testHashTable, Key: key, AttributeUpdates: updates}), function(err, res) { + it('should return all old values when they exist', function (done) { + var key = { a: { S: helpers.randomString() } }, updates = { b: { Value: { S: 'a' } } } + request(opts({ TableName: helpers.testHashTable, Key: key, AttributeUpdates: updates }), function (err, res) { if (err) return done(err) res.statusCode.should.equal(200) updates.b.Value.S = 'b' - request(opts({TableName: helpers.testHashTable, Key: key, AttributeUpdates: updates, ReturnValues: 'ALL_OLD'}), function(err, res) { + request(opts({ TableName: helpers.testHashTable, Key: key, AttributeUpdates: updates, ReturnValues: 'ALL_OLD' }), function (err, res) { if (err) return done(err) res.statusCode.should.equal(200) - res.body.should.eql({Attributes: {a: key.a, b: {S: 'a'}}}) + res.body.should.eql({ Attributes: { a: key.a, b: { S: 'a' } } }) done() }) }) }) - it('should return updated old values when they exist', function(done) { - var key = {a: {S: helpers.randomString()}}, updates = {b: {Value: {S: 'a'}}, c: {Value: {S: 'a'}}} - request(opts({TableName: helpers.testHashTable, Key: key, AttributeUpdates: updates}), function(err, res) { + it('should return updated old values when they exist', function (done) { + var key = { a: { S: helpers.randomString() } }, updates = { b: { Value: { S: 'a' } }, c: { Value: { S: 'a' } } } + request(opts({ TableName: helpers.testHashTable, Key: key, AttributeUpdates: updates }), function (err, res) { if (err) return done(err) res.statusCode.should.equal(200) updates.b.Value.S = 'b' - request(opts({TableName: helpers.testHashTable, Key: key, AttributeUpdates: updates, ReturnValues: 'UPDATED_OLD'}), function(err, res) { + request(opts({ TableName: helpers.testHashTable, Key: key, AttributeUpdates: updates, ReturnValues: 'UPDATED_OLD' }), function (err, res) { if (err) return done(err) res.statusCode.should.equal(200) - res.body.should.eql({Attributes: {b: {S: 'a'}, c: {S: 'a'}}}) + res.body.should.eql({ Attributes: { b: { S: 'a' }, c: { S: 'a' } } }) done() }) }) }) - it('should return updated old nested values when they exist', function(done) { - var key = {a: {S: helpers.randomString()}}, updates = { - b: {Value: {M: {a: {S: 'a'}, b: {L: []}}}}, - c: {Value: {N: '1'}}, + it('should return updated old nested values when they exist', function (done) { + var key = { a: { S: helpers.randomString() } }, updates = { + b: { Value: { M: { a: { S: 'a' }, b: { L: [] } } } }, + c: { Value: { N: '1' } }, } - request(opts({TableName: helpers.testHashTable, Key: key, AttributeUpdates: updates}), function(err, res) { + request(opts({ TableName: helpers.testHashTable, Key: key, AttributeUpdates: updates }), function (err, res) { if (err) return done(err) res.statusCode.should.equal(200) updates.b.Value.M.a.S = 'b' updates.c.Action = 'ADD' - request(opts({TableName: helpers.testHashTable, Key: key, AttributeUpdates: updates, ReturnValues: 'UPDATED_OLD'}), function(err, res) { + request(opts({ TableName: helpers.testHashTable, Key: key, AttributeUpdates: updates, ReturnValues: 'UPDATED_OLD' }), function (err, res) { if (err) return done(err) res.statusCode.should.equal(200) - res.body.should.eql({Attributes: {b: {M: {a: {S: 'a'}, b: {L: []}}}, c: {N: '1'}}}) + res.body.should.eql({ Attributes: { b: { M: { a: { S: 'a' }, b: { L: [] } } }, c: { N: '1' } } }) done() }) }) }) - it('should return all new values when they exist', function(done) { - var key = {a: {S: helpers.randomString()}}, updates = {b: {Value: {S: 'a'}}} - request(opts({TableName: helpers.testHashTable, Key: key, AttributeUpdates: updates}), function(err, res) { + it('should return all new values when they exist', function (done) { + var key = { a: { S: helpers.randomString() } }, updates = { b: { Value: { S: 'a' } } } + request(opts({ TableName: helpers.testHashTable, Key: key, AttributeUpdates: updates }), function (err, res) { if (err) return done(err) res.statusCode.should.equal(200) updates.b.Value.S = 'b' - request(opts({TableName: helpers.testHashTable, Key: key, AttributeUpdates: updates, ReturnValues: 'ALL_NEW'}), function(err, res) { + request(opts({ TableName: helpers.testHashTable, Key: key, AttributeUpdates: updates, ReturnValues: 'ALL_NEW' }), function (err, res) { if (err) return done(err) res.statusCode.should.equal(200) - res.body.should.eql({Attributes: {a: key.a, b: {S: 'b'}}}) + res.body.should.eql({ Attributes: { a: key.a, b: { S: 'b' } } }) done() }) }) }) - it('should return updated new values when they exist', function(done) { - var key = {a: {S: helpers.randomString()}}, updates = {b: {Value: {S: 'a'}}, c: {Value: {S: 'a'}}} - request(opts({TableName: helpers.testHashTable, Key: key, AttributeUpdates: updates}), function(err, res) { + it('should return updated new values when they exist', function (done) { + var key = { a: { S: helpers.randomString() } }, updates = { b: { Value: { S: 'a' } }, c: { Value: { S: 'a' } } } + request(opts({ TableName: helpers.testHashTable, Key: key, AttributeUpdates: updates }), function (err, res) { if (err) return done(err) res.statusCode.should.equal(200) request(opts({ TableName: helpers.testHashTable, Key: key, UpdateExpression: 'set b=:b,c=:c', - ExpressionAttributeValues: {':b': {S: 'b'}, ':c': {S: 'a'}}, + ExpressionAttributeValues: { ':b': { S: 'b' }, ':c': { S: 'a' } }, ReturnValues: 'UPDATED_NEW', - }), function(err, res) { + }), function (err, res) { if (err) return done(err) res.statusCode.should.equal(200) - res.body.should.eql({Attributes: {b: {S: 'b'}, c: {S: 'a'}}}) + res.body.should.eql({ Attributes: { b: { S: 'b' }, c: { S: 'a' } } }) done() }) }) }) - it('should just add valid ADD actions if nothing exists', function(done) { - async.forEach([{ + it('should just add valid ADD actions if nothing exists', function (done) { + async.forEach([ { AttributeUpdates: { - b: {Action: 'DELETE'}, - c: {Action: 'DELETE', Value: {SS: ['a', 'b']}}, - d: {Action: 'ADD', Value: {N: '5'}}, - e: {Action: 'ADD', Value: {SS: ['a', 'b']}}, - f: {Action: 'ADD', Value: {L: [{S: 'a'}, {N: '1'}]}}, + b: { Action: 'DELETE' }, + c: { Action: 'DELETE', Value: { SS: [ 'a', 'b' ] } }, + d: { Action: 'ADD', Value: { N: '5' } }, + e: { Action: 'ADD', Value: { SS: [ 'a', 'b' ] } }, + f: { Action: 'ADD', Value: { L: [ { S: 'a' }, { N: '1' } ] } }, }, }, { UpdateExpression: 'REMOVE b DELETE c :c ADD d :d, e :e SET f = :f', - ExpressionAttributeValues: {':c': {SS: ['a', 'b']}, ':d': {N: '5'}, ':e': {SS: ['a', 'b']}, ':f': {L: [{S: 'a'}, {N: '1'}]}}, + ExpressionAttributeValues: { ':c': { SS: [ 'a', 'b' ] }, ':d': { N: '5' }, ':e': { SS: [ 'a', 'b' ] }, ':f': { L: [ { S: 'a' }, { N: '1' } ] } }, }, { UpdateExpression: 'ADD #e :e,#d :d DELETE #c :c REMOVE #b SET #f = :f', - ExpressionAttributeValues: {':c': {SS: ['a', 'b']}, ':d': {N: '5'}, ':e': {SS: ['a', 'b']}, ':f': {L: [{S: 'a'}, {N: '1'}]}}, - ExpressionAttributeNames: {'#b': 'b', '#c': 'c', '#d': 'd', '#e': 'e', '#f': 'f'}, - }], function(updateOpts, cb) { - var key = {a: {S: helpers.randomString()}} + ExpressionAttributeValues: { ':c': { SS: [ 'a', 'b' ] }, ':d': { N: '5' }, ':e': { SS: [ 'a', 'b' ] }, ':f': { L: [ { S: 'a' }, { N: '1' } ] } }, + ExpressionAttributeNames: { '#b': 'b', '#c': 'c', '#d': 'd', '#e': 'e', '#f': 'f' }, + } ], function (updateOpts, cb) { + var key = { a: { S: helpers.randomString() } } updateOpts.TableName = helpers.testHashTable updateOpts.Key = key updateOpts.ReturnValues = 'UPDATED_NEW' - request(opts(updateOpts), function(err, res) { + request(opts(updateOpts), function (err, res) { if (err) return cb(err) res.statusCode.should.equal(200) - res.body.should.eql({Attributes: {d: {N: '5'}, e: {SS: ['a', 'b']}, f: {L: [{S: 'a'}, {N: '1'}]}}}) - request(helpers.opts('GetItem', {TableName: helpers.testHashTable, Key: key, ConsistentRead: true}), function(err, res) { + res.body.should.eql({ Attributes: { d: { N: '5' }, e: { SS: [ 'a', 'b' ] }, f: { L: [ { S: 'a' }, { N: '1' } ] } } }) + request(helpers.opts('GetItem', { TableName: helpers.testHashTable, Key: key, ConsistentRead: true }), function (err, res) { if (err) return cb(err) res.statusCode.should.equal(200) - res.body.should.eql({Item: {a: key.a, d: {N: '5'}, e: {SS: ['a', 'b']}, f: {L: [{S: 'a'}, {N: '1'}]}}}) + res.body.should.eql({ Item: { a: key.a, d: { N: '5' }, e: { SS: [ 'a', 'b' ] }, f: { L: [ { S: 'a' }, { N: '1' } ] } } }) cb() }) }) }, done) }) - it('should delete normal values and return updated new', function(done) { - var key = {a: {S: helpers.randomString()}}, updates = {b: {Value: {S: 'a'}}, c: {Value: {S: 'a'}}} - request(opts({TableName: helpers.testHashTable, Key: key, AttributeUpdates: updates}), function(err, res) { + it('should delete normal values and return updated new', function (done) { + var key = { a: { S: helpers.randomString() } }, updates = { b: { Value: { S: 'a' } }, c: { Value: { S: 'a' } } } + request(opts({ TableName: helpers.testHashTable, Key: key, AttributeUpdates: updates }), function (err, res) { if (err) return done(err) res.statusCode.should.equal(200) - updates.b = {Action: 'DELETE'} - request(opts({TableName: helpers.testHashTable, Key: key, AttributeUpdates: updates, ReturnValues: 'UPDATED_NEW'}), function(err, res) { + updates.b = { Action: 'DELETE' } + request(opts({ TableName: helpers.testHashTable, Key: key, AttributeUpdates: updates, ReturnValues: 'UPDATED_NEW' }), function (err, res) { if (err) return done(err) res.statusCode.should.equal(200) - res.body.should.eql({Attributes: {c: {S: 'a'}}}) - request(helpers.opts('GetItem', {TableName: helpers.testHashTable, Key: key, ConsistentRead: true}), function(err, res) { + res.body.should.eql({ Attributes: { c: { S: 'a' } } }) + request(helpers.opts('GetItem', { TableName: helpers.testHashTable, Key: key, ConsistentRead: true }), function (err, res) { if (err) return done(err) res.statusCode.should.equal(200) - res.body.should.eql({Item: {a: key.a, c: {S: 'a'}}}) + res.body.should.eql({ Item: { a: key.a, c: { S: 'a' } } }) done() }) }) }) }) - it('should delete normal values and return updated on index table', function(done) { - var key = {a: {S: helpers.randomString()}, b: {S: helpers.randomString()}}, updates = {c: {Value: {S: 'a'}}, d: {Value: {S: 'a'}}} - request(opts({TableName: helpers.testRangeTable, Key: key, AttributeUpdates: updates}), function(err, res) { + it('should delete normal values and return updated on index table', function (done) { + var key = { a: { S: helpers.randomString() }, b: { S: helpers.randomString() } }, updates = { c: { Value: { S: 'a' } }, d: { Value: { S: 'a' } } } + request(opts({ TableName: helpers.testRangeTable, Key: key, AttributeUpdates: updates }), function (err, res) { if (err) return done(err) res.statusCode.should.equal(200) - updates.c = {Action: 'DELETE'} - request(opts({TableName: helpers.testRangeTable, Key: key, AttributeUpdates: updates, ReturnValues: 'UPDATED_NEW'}), function(err, res) { + updates.c = { Action: 'DELETE' } + request(opts({ TableName: helpers.testRangeTable, Key: key, AttributeUpdates: updates, ReturnValues: 'UPDATED_NEW' }), function (err, res) { if (err) return done(err) res.statusCode.should.equal(200) - res.body.should.eql({Attributes: {d: {S: 'a'}}}) - request(helpers.opts('GetItem', {TableName: helpers.testRangeTable, Key: key, ConsistentRead: true}), function(err, res) { + res.body.should.eql({ Attributes: { d: { S: 'a' } } }) + request(helpers.opts('GetItem', { TableName: helpers.testRangeTable, Key: key, ConsistentRead: true }), function (err, res) { if (err) return done(err) res.statusCode.should.equal(200) - res.body.should.eql({Item: {a: key.a, b: key.b, d: {S: 'a'}}}) + res.body.should.eql({ Item: { a: key.a, b: key.b, d: { S: 'a' } } }) done() }) }) }) }) - it('should delete set values and return updated new', function(done) { - var key = {a: {S: helpers.randomString()}}, updates = {b: {Value: {NS: ['1', '2', '3']}}, c: {Value: {S: 'a'}}} - request(opts({TableName: helpers.testHashTable, Key: key, AttributeUpdates: updates}), function(err, res) { + it('should delete set values and return updated new', function (done) { + var key = { a: { S: helpers.randomString() } }, updates = { b: { Value: { NS: [ '1', '2', '3' ] } }, c: { Value: { S: 'a' } } } + request(opts({ TableName: helpers.testHashTable, Key: key, AttributeUpdates: updates }), function (err, res) { if (err) return done(err) res.statusCode.should.equal(200) - updates.b = {Action: 'DELETE', Value: {NS: ['1', '4']}} - request(opts({TableName: helpers.testHashTable, Key: key, AttributeUpdates: updates, ReturnValues: 'UPDATED_NEW'}), function(err, res) { + updates.b = { Action: 'DELETE', Value: { NS: [ '1', '4' ] } } + request(opts({ TableName: helpers.testHashTable, Key: key, AttributeUpdates: updates, ReturnValues: 'UPDATED_NEW' }), function (err, res) { if (err) return done(err) res.statusCode.should.equal(200) res.body.Attributes.b.NS.should.containEql('2') res.body.Attributes.b.NS.should.containEql('3') - res.body.Attributes.c.should.eql({S: 'a'}) - request(helpers.opts('GetItem', {TableName: helpers.testHashTable, Key: key, ConsistentRead: true}), function(err, res) { + res.body.Attributes.c.should.eql({ S: 'a' }) + request(helpers.opts('GetItem', { TableName: helpers.testHashTable, Key: key, ConsistentRead: true }), function (err, res) { if (err) return done(err) res.statusCode.should.equal(200) res.body.Item.b.NS.should.containEql('2') res.body.Item.b.NS.should.containEql('3') - res.body.Item.c.should.eql({S: 'a'}) - updates.b = {Action: 'DELETE', Value: {NS: ['2', '3']}} - request(opts({TableName: helpers.testHashTable, Key: key, AttributeUpdates: updates, ReturnValues: 'UPDATED_NEW'}), function(err, res) { + res.body.Item.c.should.eql({ S: 'a' }) + updates.b = { Action: 'DELETE', Value: { NS: [ '2', '3' ] } } + request(opts({ TableName: helpers.testHashTable, Key: key, AttributeUpdates: updates, ReturnValues: 'UPDATED_NEW' }), function (err, res) { if (err) return done(err) res.statusCode.should.equal(200) - res.body.Attributes.should.eql({c: {S: 'a'}}) - request(helpers.opts('GetItem', {TableName: helpers.testHashTable, Key: key, ConsistentRead: true}), function(err, res) { + res.body.Attributes.should.eql({ c: { S: 'a' } }) + request(helpers.opts('GetItem', { TableName: helpers.testHashTable, Key: key, ConsistentRead: true }), function (err, res) { if (err) return done(err) res.statusCode.should.equal(200) - res.body.Item.should.eql({a: key.a, c: {S: 'a'}}) + res.body.Item.should.eql({ a: key.a, c: { S: 'a' } }) done() }) }) @@ -1225,73 +1225,73 @@ describe('updateItem', function() { }) }) - it('should add numerical value and return updated new', function(done) { - var key = {a: {S: helpers.randomString()}}, updates = {b: {Value: {N: '1'}}} - request(opts({TableName: helpers.testHashTable, Key: key, AttributeUpdates: updates}), function(err, res) { + it('should add numerical value and return updated new', function (done) { + var key = { a: { S: helpers.randomString() } }, updates = { b: { Value: { N: '1' } } } + request(opts({ TableName: helpers.testHashTable, Key: key, AttributeUpdates: updates }), function (err, res) { if (err) return done(err) res.statusCode.should.equal(200) - updates.b = {Action: 'ADD', Value: {N: '3'}} - request(opts({TableName: helpers.testHashTable, Key: key, AttributeUpdates: updates, ReturnValues: 'UPDATED_NEW'}), function(err, res) { + updates.b = { Action: 'ADD', Value: { N: '3' } } + request(opts({ TableName: helpers.testHashTable, Key: key, AttributeUpdates: updates, ReturnValues: 'UPDATED_NEW' }), function (err, res) { if (err) return done(err) res.statusCode.should.equal(200) - res.body.should.eql({Attributes: {b: {N: '4'}}}) - request(helpers.opts('GetItem', {TableName: helpers.testHashTable, Key: key, ConsistentRead: true}), function(err, res) { + res.body.should.eql({ Attributes: { b: { N: '4' } } }) + request(helpers.opts('GetItem', { TableName: helpers.testHashTable, Key: key, ConsistentRead: true }), function (err, res) { if (err) return done(err) res.statusCode.should.equal(200) - res.body.should.eql({Item: {a: key.a, b: {N: '4'}}}) + res.body.should.eql({ Item: { a: key.a, b: { N: '4' } } }) done() }) }) }) }) - it('should add set value and return updated new', function(done) { - var key = {a: {S: helpers.randomString()}}, updates = {b: {Value: {SS: ['a', 'b']}}} - request(opts({TableName: helpers.testHashTable, Key: key, AttributeUpdates: updates}), function(err, res) { + it('should add set value and return updated new', function (done) { + var key = { a: { S: helpers.randomString() } }, updates = { b: { Value: { SS: [ 'a', 'b' ] } } } + request(opts({ TableName: helpers.testHashTable, Key: key, AttributeUpdates: updates }), function (err, res) { if (err) return done(err) res.statusCode.should.equal(200) - updates.b = {Action: 'ADD', Value: {SS: ['c', 'd']}} - request(opts({TableName: helpers.testHashTable, Key: key, AttributeUpdates: updates, ReturnValues: 'UPDATED_NEW'}), function(err, res) { + updates.b = { Action: 'ADD', Value: { SS: [ 'c', 'd' ] } } + request(opts({ TableName: helpers.testHashTable, Key: key, AttributeUpdates: updates, ReturnValues: 'UPDATED_NEW' }), function (err, res) { if (err) return done(err) res.statusCode.should.equal(200) - res.body.should.eql({Attributes: {b: {SS: ['a', 'b', 'c', 'd']}}}) - request(helpers.opts('GetItem', {TableName: helpers.testHashTable, Key: key, ConsistentRead: true}), function(err, res) { + res.body.should.eql({ Attributes: { b: { SS: [ 'a', 'b', 'c', 'd' ] } } }) + request(helpers.opts('GetItem', { TableName: helpers.testHashTable, Key: key, ConsistentRead: true }), function (err, res) { if (err) return done(err) res.statusCode.should.equal(200) - res.body.should.eql({Item: {a: key.a, b: {SS: ['a', 'b', 'c', 'd']}}}) + res.body.should.eql({ Item: { a: key.a, b: { SS: [ 'a', 'b', 'c', 'd' ] } } }) done() }) }) }) }) - it('should add list value and return updated new', function(done) { - var key = {a: {S: helpers.randomString()}}, updates = {b: {Value: {L: [{S: 'a'}, {N: '1'}]}}} - request(opts({TableName: helpers.testHashTable, Key: key, AttributeUpdates: updates}), function(err, res) { + it('should add list value and return updated new', function (done) { + var key = { a: { S: helpers.randomString() } }, updates = { b: { Value: { L: [ { S: 'a' }, { N: '1' } ] } } } + request(opts({ TableName: helpers.testHashTable, Key: key, AttributeUpdates: updates }), function (err, res) { if (err) return done(err) res.statusCode.should.equal(200) - updates.b = {Action: 'ADD', Value: {L: [{S: 'b'}, {N: '2'}]}} - request(opts({TableName: helpers.testHashTable, Key: key, AttributeUpdates: updates, ReturnValues: 'UPDATED_NEW'}), function(err, res) { + updates.b = { Action: 'ADD', Value: { L: [ { S: 'b' }, { N: '2' } ] } } + request(opts({ TableName: helpers.testHashTable, Key: key, AttributeUpdates: updates, ReturnValues: 'UPDATED_NEW' }), function (err, res) { if (err) return done(err) res.statusCode.should.equal(200) - res.body.should.eql({Attributes: {b: {L: [{S: 'a'}, {N: '1'}, {S: 'b'}, {N: '2'}]}}}) - request(helpers.opts('GetItem', {TableName: helpers.testHashTable, Key: key, ConsistentRead: true}), function(err, res) { + res.body.should.eql({ Attributes: { b: { L: [ { S: 'a' }, { N: '1' }, { S: 'b' }, { N: '2' } ] } } }) + request(helpers.opts('GetItem', { TableName: helpers.testHashTable, Key: key, ConsistentRead: true }), function (err, res) { if (err) return done(err) res.statusCode.should.equal(200) - res.body.should.eql({Item: {a: key.a, b: {L: [{S: 'a'}, {N: '1'}, {S: 'b'}, {N: '2'}]}}}) + res.body.should.eql({ Item: { a: key.a, b: { L: [ { S: 'a' }, { N: '1' }, { S: 'b' }, { N: '2' } ] } } }) done() }) }) }) }) - it('should throw away duplicate string values', function(done) { - var key = {a: {S: helpers.randomString()}}, updates = {b: {Value: {SS: ['a', 'b']}}} - request(opts({TableName: helpers.testHashTable, Key: key, AttributeUpdates: updates}), function(err, res) { + it('should throw away duplicate string values', function (done) { + var key = { a: { S: helpers.randomString() } }, updates = { b: { Value: { SS: [ 'a', 'b' ] } } } + request(opts({ TableName: helpers.testHashTable, Key: key, AttributeUpdates: updates }), function (err, res) { if (err) return done(err) res.statusCode.should.equal(200) - updates.b = {Action: 'ADD', Value: {SS: ['b', 'c', 'd']}} - request(opts({TableName: helpers.testHashTable, Key: key, AttributeUpdates: updates, ReturnValues: 'UPDATED_NEW'}), function(err, res) { + updates.b = { Action: 'ADD', Value: { SS: [ 'b', 'c', 'd' ] } } + request(opts({ TableName: helpers.testHashTable, Key: key, AttributeUpdates: updates, ReturnValues: 'UPDATED_NEW' }), function (err, res) { if (err) return done(err) res.statusCode.should.equal(200) res.body.Attributes.b.SS.should.have.lengthOf(4) @@ -1299,7 +1299,7 @@ describe('updateItem', function() { res.body.Attributes.b.SS.should.containEql('b') res.body.Attributes.b.SS.should.containEql('c') res.body.Attributes.b.SS.should.containEql('d') - request(helpers.opts('GetItem', {TableName: helpers.testHashTable, Key: key, ConsistentRead: true}), function(err, res) { + request(helpers.opts('GetItem', { TableName: helpers.testHashTable, Key: key, ConsistentRead: true }), function (err, res) { if (err) return done(err) res.statusCode.should.equal(200) res.body.Item.b.SS.should.have.lengthOf(4) @@ -1313,13 +1313,13 @@ describe('updateItem', function() { }) }) - it('should throw away duplicate numeric values', function(done) { - var key = {a: {S: helpers.randomString()}}, updates = {b: {Value: {NS: ['1', '2']}}} - request(opts({TableName: helpers.testHashTable, Key: key, AttributeUpdates: updates}), function(err, res) { + it('should throw away duplicate numeric values', function (done) { + var key = { a: { S: helpers.randomString() } }, updates = { b: { Value: { NS: [ '1', '2' ] } } } + request(opts({ TableName: helpers.testHashTable, Key: key, AttributeUpdates: updates }), function (err, res) { if (err) return done(err) res.statusCode.should.equal(200) - updates.b = {Action: 'ADD', Value: {NS: ['2', '3', '4']}} - request(opts({TableName: helpers.testHashTable, Key: key, AttributeUpdates: updates, ReturnValues: 'UPDATED_NEW'}), function(err, res) { + updates.b = { Action: 'ADD', Value: { NS: [ '2', '3', '4' ] } } + request(opts({ TableName: helpers.testHashTable, Key: key, AttributeUpdates: updates, ReturnValues: 'UPDATED_NEW' }), function (err, res) { if (err) return done(err) res.statusCode.should.equal(200) res.body.Attributes.b.NS.should.have.lengthOf(4) @@ -1327,7 +1327,7 @@ describe('updateItem', function() { res.body.Attributes.b.NS.should.containEql('2') res.body.Attributes.b.NS.should.containEql('3') res.body.Attributes.b.NS.should.containEql('4') - request(helpers.opts('GetItem', {TableName: helpers.testHashTable, Key: key, ConsistentRead: true}), function(err, res) { + request(helpers.opts('GetItem', { TableName: helpers.testHashTable, Key: key, ConsistentRead: true }), function (err, res) { if (err) return done(err) res.statusCode.should.equal(200) res.body.Item.b.NS.should.have.lengthOf(4) @@ -1341,20 +1341,20 @@ describe('updateItem', function() { }) }) - it('should throw away duplicate binary values', function(done) { - var key = {a: {S: helpers.randomString()}}, updates = {b: {Value: {BS: ['AQI=', 'Ag==']}}} - request(opts({TableName: helpers.testHashTable, Key: key, AttributeUpdates: updates}), function(err, res) { + it('should throw away duplicate binary values', function (done) { + var key = { a: { S: helpers.randomString() } }, updates = { b: { Value: { BS: [ 'AQI=', 'Ag==' ] } } } + request(opts({ TableName: helpers.testHashTable, Key: key, AttributeUpdates: updates }), function (err, res) { if (err) return done(err) res.statusCode.should.equal(200) - updates.b = {Action: 'ADD', Value: {BS: ['Ag==', 'AQ==']}} - request(opts({TableName: helpers.testHashTable, Key: key, AttributeUpdates: updates, ReturnValues: 'UPDATED_NEW'}), function(err, res) { + updates.b = { Action: 'ADD', Value: { BS: [ 'Ag==', 'AQ==' ] } } + request(opts({ TableName: helpers.testHashTable, Key: key, AttributeUpdates: updates, ReturnValues: 'UPDATED_NEW' }), function (err, res) { if (err) return done(err) res.statusCode.should.equal(200) res.body.Attributes.b.BS.should.have.lengthOf(3) res.body.Attributes.b.BS.should.containEql('AQI=') res.body.Attributes.b.BS.should.containEql('Ag==') res.body.Attributes.b.BS.should.containEql('AQ==') - request(helpers.opts('GetItem', {TableName: helpers.testHashTable, Key: key, ConsistentRead: true}), function(err, res) { + request(helpers.opts('GetItem', { TableName: helpers.testHashTable, Key: key, ConsistentRead: true }), function (err, res) { if (err) return done(err) res.statusCode.should.equal(200) res.body.Item.b.BS.should.have.lengthOf(3) @@ -1367,150 +1367,150 @@ describe('updateItem', function() { }) }) - it('should return ConsumedCapacity for creating small item', function(done) { - var key = {a: {S: helpers.randomString()}}, b = new Array(1010 - key.a.S.length).join('b'), - updates = {b: {Value: {S: b}}, c: {Value: {N: '12.3456'}}, d: {Value: {B: 'AQI='}}, e: {Value: {BS: ['AQI=', 'Ag==', 'AQ==']}}}, - req = {TableName: helpers.testHashTable, Key: key, AttributeUpdates: updates, ReturnConsumedCapacity: 'TOTAL'} - request(opts(req), function(err, res) { + it('should return ConsumedCapacity for creating small item', function (done) { + var key = { a: { S: helpers.randomString() } }, b = new Array(1010 - key.a.S.length).join('b'), + updates = { b: { Value: { S: b } }, c: { Value: { N: '12.3456' } }, d: { Value: { B: 'AQI=' } }, e: { Value: { BS: [ 'AQI=', 'Ag==', 'AQ==' ] } } }, + req = { TableName: helpers.testHashTable, Key: key, AttributeUpdates: updates, ReturnConsumedCapacity: 'TOTAL' } + request(opts(req), function (err, res) { if (err) return done(err) res.statusCode.should.equal(200) - res.body.should.eql({ConsumedCapacity: {CapacityUnits: 1, TableName: helpers.testHashTable}}) + res.body.should.eql({ ConsumedCapacity: { CapacityUnits: 1, TableName: helpers.testHashTable } }) req.ReturnConsumedCapacity = 'INDEXES' - request(opts(req), function(err, res) { + request(opts(req), function (err, res) { if (err) return done(err) res.statusCode.should.equal(200) - res.body.should.eql({ConsumedCapacity: {CapacityUnits: 1, Table: {CapacityUnits: 1}, TableName: helpers.testHashTable}}) + res.body.should.eql({ ConsumedCapacity: { CapacityUnits: 1, Table: { CapacityUnits: 1 }, TableName: helpers.testHashTable } }) done() }) }) }) - it('should return ConsumedCapacity for creating larger item', function(done) { - var key = {a: {S: helpers.randomString()}}, b = new Array(1012 - key.a.S.length).join('b'), - updates = {b: {Value: {S: b}}, c: {Value: {N: '12.3456'}}, d: {Value: {B: 'AQI='}}, e: {Value: {BS: ['AQI=', 'Ag==']}}}, - req = {TableName: helpers.testHashTable, Key: key, AttributeUpdates: updates, ReturnConsumedCapacity: 'TOTAL'} - request(opts(req), function(err, res) { + it('should return ConsumedCapacity for creating larger item', function (done) { + var key = { a: { S: helpers.randomString() } }, b = new Array(1012 - key.a.S.length).join('b'), + updates = { b: { Value: { S: b } }, c: { Value: { N: '12.3456' } }, d: { Value: { B: 'AQI=' } }, e: { Value: { BS: [ 'AQI=', 'Ag==' ] } } }, + req = { TableName: helpers.testHashTable, Key: key, AttributeUpdates: updates, ReturnConsumedCapacity: 'TOTAL' } + request(opts(req), function (err, res) { if (err) return done(err) res.statusCode.should.equal(200) - res.body.should.eql({ConsumedCapacity: {CapacityUnits: 2, TableName: helpers.testHashTable}}) + res.body.should.eql({ ConsumedCapacity: { CapacityUnits: 2, TableName: helpers.testHashTable } }) req.ReturnConsumedCapacity = 'INDEXES' - request(opts(req), function(err, res) { + request(opts(req), function (err, res) { if (err) return done(err) res.statusCode.should.equal(200) - res.body.should.eql({ConsumedCapacity: {CapacityUnits: 2, Table: {CapacityUnits: 2}, TableName: helpers.testHashTable}}) + res.body.should.eql({ ConsumedCapacity: { CapacityUnits: 2, Table: { CapacityUnits: 2 }, TableName: helpers.testHashTable } }) done() }) }) }) - it('should return ConsumedCapacity for creating and updating small item', function(done) { - var key = {a: {S: helpers.randomString()}}, b = new Array(1009 - key.a.S.length).join('b'), - updates = {b: {Value: {S: b}}, c: {Value: {N: '12.3456'}}, d: {Value: {B: 'AQI='}}, e: {Value: {BS: ['AQI=', 'Ag==', 'AQ==']}}} - request(opts({TableName: helpers.testHashTable, Key: key, AttributeUpdates: updates, ReturnConsumedCapacity: 'TOTAL'}), function(err, res) { + it('should return ConsumedCapacity for creating and updating small item', function (done) { + var key = { a: { S: helpers.randomString() } }, b = new Array(1009 - key.a.S.length).join('b'), + updates = { b: { Value: { S: b } }, c: { Value: { N: '12.3456' } }, d: { Value: { B: 'AQI=' } }, e: { Value: { BS: [ 'AQI=', 'Ag==', 'AQ==' ] } } } + request(opts({ TableName: helpers.testHashTable, Key: key, AttributeUpdates: updates, ReturnConsumedCapacity: 'TOTAL' }), function (err, res) { if (err) return done(err) res.statusCode.should.equal(200) - res.body.should.eql({ConsumedCapacity: {CapacityUnits: 1, TableName: helpers.testHashTable}}) - updates = {b: {Value: {S: b + 'b'}}} - request(opts({TableName: helpers.testHashTable, Key: key, AttributeUpdates: updates, ReturnConsumedCapacity: 'TOTAL'}), function(err, res) { + res.body.should.eql({ ConsumedCapacity: { CapacityUnits: 1, TableName: helpers.testHashTable } }) + updates = { b: { Value: { S: b + 'b' } } } + request(opts({ TableName: helpers.testHashTable, Key: key, AttributeUpdates: updates, ReturnConsumedCapacity: 'TOTAL' }), function (err, res) { if (err) return done(err) res.statusCode.should.equal(200) - res.body.should.eql({ConsumedCapacity: {CapacityUnits: 1, TableName: helpers.testHashTable}}) + res.body.should.eql({ ConsumedCapacity: { CapacityUnits: 1, TableName: helpers.testHashTable } }) done() }) }) }) - it('should return ConsumedCapacity for creating and updating larger item', function(done) { - var key = {a: {S: helpers.randomString()}}, b = new Array(1011 - key.a.S.length).join('b'), - updates = {b: {Value: {S: b}}, c: {Value: {N: '12.3456'}}, d: {Value: {B: 'AQI='}}, e: {Value: {BS: ['AQI=', 'Ag==']}}} - request(opts({TableName: helpers.testHashTable, Key: key, AttributeUpdates: updates, ReturnConsumedCapacity: 'TOTAL'}), function(err, res) { + it('should return ConsumedCapacity for creating and updating larger item', function (done) { + var key = { a: { S: helpers.randomString() } }, b = new Array(1011 - key.a.S.length).join('b'), + updates = { b: { Value: { S: b } }, c: { Value: { N: '12.3456' } }, d: { Value: { B: 'AQI=' } }, e: { Value: { BS: [ 'AQI=', 'Ag==' ] } } } + request(opts({ TableName: helpers.testHashTable, Key: key, AttributeUpdates: updates, ReturnConsumedCapacity: 'TOTAL' }), function (err, res) { if (err) return done(err) res.statusCode.should.equal(200) - res.body.should.eql({ConsumedCapacity: {CapacityUnits: 1, TableName: helpers.testHashTable}}) - updates = {b: {Value: {S: b + 'b'}}} - request(opts({TableName: helpers.testHashTable, Key: key, AttributeUpdates: updates, ReturnConsumedCapacity: 'TOTAL'}), function(err, res) { + res.body.should.eql({ ConsumedCapacity: { CapacityUnits: 1, TableName: helpers.testHashTable } }) + updates = { b: { Value: { S: b + 'b' } } } + request(opts({ TableName: helpers.testHashTable, Key: key, AttributeUpdates: updates, ReturnConsumedCapacity: 'TOTAL' }), function (err, res) { if (err) return done(err) res.statusCode.should.equal(200) - res.body.should.eql({ConsumedCapacity: {CapacityUnits: 2, TableName: helpers.testHashTable}}) + res.body.should.eql({ ConsumedCapacity: { CapacityUnits: 2, TableName: helpers.testHashTable } }) done() }) }) }) - it('should update when boolean value expect matches', function(done) { - async.forEach([{ - Expected: {active: {Value: {BOOL: false}, Exists: true}}, - AttributeUpdates: {active: {Action: 'PUT', Value: {BOOL: true}}}, + it('should update when boolean value expect matches', function (done) { + async.forEach([ { + Expected: { active: { Value: { BOOL: false }, Exists: true } }, + AttributeUpdates: { active: { Action: 'PUT', Value: { BOOL: true } } }, }, { ConditionExpression: 'active = :a', UpdateExpression: 'SET active = :b', - ExpressionAttributeValues: {':a': {BOOL: false}, ':b': {BOOL: true}}, + ExpressionAttributeValues: { ':a': { BOOL: false }, ':b': { BOOL: true } }, }, { ConditionExpression: '#a = :a', UpdateExpression: 'SET #b = :b', - ExpressionAttributeNames: {'#a': 'active', '#b': 'active'}, - ExpressionAttributeValues: {':a': {BOOL: false}, ':b': {BOOL: true}}, - }], function(updateOpts, cb) { - var item = {a: {S: helpers.randomString()}, active: {BOOL: false}} - request(helpers.opts('PutItem', {TableName: helpers.testHashTable, Item: item}), function(err, res) { + ExpressionAttributeNames: { '#a': 'active', '#b': 'active' }, + ExpressionAttributeValues: { ':a': { BOOL: false }, ':b': { BOOL: true } }, + } ], function (updateOpts, cb) { + var item = { a: { S: helpers.randomString() }, active: { BOOL: false } } + request(helpers.opts('PutItem', { TableName: helpers.testHashTable, Item: item }), function (err, res) { if (err) return cb(err) res.statusCode.should.equal(200) res.body.should.eql({}) updateOpts.TableName = helpers.testHashTable - updateOpts.Key = {a: item.a} + updateOpts.Key = { a: item.a } updateOpts.ReturnValues = 'UPDATED_NEW' - request(opts(updateOpts), function(err, res) { + request(opts(updateOpts), function (err, res) { if (err) return cb(err) res.statusCode.should.equal(200) - res.body.should.eql({Attributes: {active: {BOOL: true}}}) + res.body.should.eql({ Attributes: { active: { BOOL: true } } }) cb() }) }) }, done) }) - it('should update values from other attributes', function(done) { - var key = {a: {S: helpers.randomString()}} + it('should update values from other attributes', function (done) { + var key = { a: { S: helpers.randomString() } } request(opts({ TableName: helpers.testHashTable, Key: key, UpdateExpression: 'set b = if_not_exists(b, a)', ReturnValues: 'UPDATED_NEW', - }), function(err, res) { + }), function (err, res) { if (err) return done(err) res.statusCode.should.equal(200) - res.body.should.eql({Attributes: {b: key.a}}) + res.body.should.eql({ Attributes: { b: key.a } }) done() }) }) - it('should update nested attributes', function(done) { - var key = {a: {S: helpers.randomString()}} + it('should update nested attributes', function (done) { + var key = { a: { S: helpers.randomString() } } request(opts({ TableName: helpers.testHashTable, Key: key, UpdateExpression: 'set b = :b, c = :c', - ExpressionAttributeValues: {':b': {M: {a: {N: '1'}, b: {N: '2'}, c: {N: '3'}}}, ':c': {L: [{N: '1'}, {N: '3'}]}}, - }), function(err, res) { + ExpressionAttributeValues: { ':b': { M: { a: { N: '1' }, b: { N: '2' }, c: { N: '3' } } }, ':c': { L: [ { N: '1' }, { N: '3' } ] } }, + }), function (err, res) { if (err) return done(err) res.statusCode.should.equal(200) request(opts({ TableName: helpers.testHashTable, Key: key, UpdateExpression: 'set b.c=((c[1])+(b.a)),b.a = a,c[1] = a, c[4] = b.a - b.b, c[2] = b.c add c[8] :b, c[6] :a', - ExpressionAttributeValues: {':a': {N: '2'}, ':b': {SS: ['a']}}, + ExpressionAttributeValues: { ':a': { N: '2' }, ':b': { SS: [ 'a' ] } }, ReturnValues: 'UPDATED_NEW', - }), function(err, res) { + }), function (err, res) { if (err) return done(err) res.statusCode.should.equal(200) - res.body.should.eql({Attributes: {b: {M: {a: key.a, c: {N: '4'}}}, c: {L: [key.a, {N: '3'}, {N: '2'}]}}}) - request(helpers.opts('GetItem', {TableName: helpers.testHashTable, Key: key, ConsistentRead: true}), function(err, res) { + res.body.should.eql({ Attributes: { b: { M: { a: key.a, c: { N: '4' } } }, c: { L: [ key.a, { N: '3' }, { N: '2' } ] } } }) + request(helpers.opts('GetItem', { TableName: helpers.testHashTable, Key: key, ConsistentRead: true }), function (err, res) { if (err) return done(err) res.statusCode.should.equal(200) res.body.Item.should.eql({ a: key.a, - b: {M: {a: key.a, b: {N: '2'}, - c: {N: '4'}}}, c: {L: [{N: '1'}, key.a, {N: '3'}, {N: '-1'}, {N: '2'}, {SS: ['a']}]}, + b: { M: { a: key.a, b: { N: '2' }, + c: { N: '4' } } }, c: { L: [ { N: '1' }, key.a, { N: '3' }, { N: '-1' }, { N: '2' }, { SS: [ 'a' ] } ] }, }) done() }) @@ -1518,46 +1518,46 @@ describe('updateItem', function() { }) }) - it('should update indexed attributes', function(done) { - var key = {a: {S: helpers.randomString()}, b: {S: helpers.randomString()}} + it('should update indexed attributes', function (done) { + var key = { a: { S: helpers.randomString() }, b: { S: helpers.randomString() } } request(opts({ TableName: helpers.testRangeTable, Key: key, UpdateExpression: 'set c = a, d = b, e = a, f = b', ReturnValues: 'UPDATED_NEW', - }), function(err, res) { + }), function (err, res) { if (err) return done(err) res.statusCode.should.equal(200) - res.body.should.eql({Attributes: {c: key.a, d: key.b, e: key.a, f: key.b}}) + res.body.should.eql({ Attributes: { c: key.a, d: key.b, e: key.a, f: key.b } }) request(helpers.opts('Query', { TableName: helpers.testRangeTable, ConsistentRead: true, IndexName: 'index1', KeyConditions: { - a: {ComparisonOperator: 'EQ', AttributeValueList: [key.a]}, - c: {ComparisonOperator: 'EQ', AttributeValueList: [key.a]}, + a: { ComparisonOperator: 'EQ', AttributeValueList: [ key.a ] }, + c: { ComparisonOperator: 'EQ', AttributeValueList: [ key.a ] }, }, - }), function(err, res) { + }), function (err, res) { if (err) return done(err) res.statusCode.should.equal(200) - res.body.Items.should.eql([{a: key.a, b: key.b, c: key.a, d: key.b, e: key.a, f: key.b}]) + res.body.Items.should.eql([ { a: key.a, b: key.b, c: key.a, d: key.b, e: key.a, f: key.b } ]) request(helpers.opts('Query', { TableName: helpers.testRangeTable, ConsistentRead: true, IndexName: 'index2', KeyConditions: { - a: {ComparisonOperator: 'EQ', AttributeValueList: [key.a]}, - d: {ComparisonOperator: 'EQ', AttributeValueList: [key.b]}, + a: { ComparisonOperator: 'EQ', AttributeValueList: [ key.a ] }, + d: { ComparisonOperator: 'EQ', AttributeValueList: [ key.b ] }, }, - }), function(err, res) { + }), function (err, res) { if (err) return done(err) res.statusCode.should.equal(200) - res.body.Items.should.eql([{a: key.a, b: key.b, c: key.a, d: key.b}]) + res.body.Items.should.eql([ { a: key.a, b: key.b, c: key.a, d: key.b } ]) request(opts({ TableName: helpers.testRangeTable, Key: key, UpdateExpression: 'set c = b, d = a, e = b, f = a', - }), function(err, res) { + }), function (err, res) { if (err) return done(err) res.statusCode.should.equal(200) request(helpers.opts('Query', { @@ -1565,10 +1565,10 @@ describe('updateItem', function() { ConsistentRead: true, IndexName: 'index1', KeyConditions: { - a: {ComparisonOperator: 'EQ', AttributeValueList: [key.a]}, - c: {ComparisonOperator: 'EQ', AttributeValueList: [key.a]}, + a: { ComparisonOperator: 'EQ', AttributeValueList: [ key.a ] }, + c: { ComparisonOperator: 'EQ', AttributeValueList: [ key.a ] }, }, - }), function(err, res) { + }), function (err, res) { if (err) return done(err) res.statusCode.should.equal(200) res.body.Items.should.eql([]) @@ -1577,10 +1577,10 @@ describe('updateItem', function() { ConsistentRead: true, IndexName: 'index2', KeyConditions: { - a: {ComparisonOperator: 'EQ', AttributeValueList: [key.a]}, - d: {ComparisonOperator: 'EQ', AttributeValueList: [key.b]}, + a: { ComparisonOperator: 'EQ', AttributeValueList: [ key.a ] }, + d: { ComparisonOperator: 'EQ', AttributeValueList: [ key.b ] }, }, - }), function(err, res) { + }), function (err, res) { if (err) return done(err) res.statusCode.should.equal(200) res.body.Items.should.eql([]) @@ -1589,46 +1589,46 @@ describe('updateItem', function() { ConsistentRead: true, IndexName: 'index1', KeyConditions: { - a: {ComparisonOperator: 'EQ', AttributeValueList: [key.a]}, - c: {ComparisonOperator: 'EQ', AttributeValueList: [key.b]}, + a: { ComparisonOperator: 'EQ', AttributeValueList: [ key.a ] }, + c: { ComparisonOperator: 'EQ', AttributeValueList: [ key.b ] }, }, - }), function(err, res) { + }), function (err, res) { if (err) return done(err) res.statusCode.should.equal(200) - res.body.Items.should.eql([{a: key.a, b: key.b, c: key.b, d: key.a, e: key.b, f: key.a}]) + res.body.Items.should.eql([ { a: key.a, b: key.b, c: key.b, d: key.a, e: key.b, f: key.a } ]) request(helpers.opts('Query', { TableName: helpers.testRangeTable, ConsistentRead: true, IndexName: 'index2', KeyConditions: { - a: {ComparisonOperator: 'EQ', AttributeValueList: [key.a]}, - d: {ComparisonOperator: 'EQ', AttributeValueList: [key.a]}, + a: { ComparisonOperator: 'EQ', AttributeValueList: [ key.a ] }, + d: { ComparisonOperator: 'EQ', AttributeValueList: [ key.a ] }, }, - }), function(err, res) { + }), function (err, res) { if (err) return done(err) res.statusCode.should.equal(200) - res.body.Items.should.eql([{a: key.a, b: key.b, c: key.b, d: key.a}]) + res.body.Items.should.eql([ { a: key.a, b: key.b, c: key.b, d: key.a } ]) request(helpers.opts('Query', { TableName: helpers.testRangeTable, IndexName: 'index3', KeyConditions: { - c: {ComparisonOperator: 'EQ', AttributeValueList: [key.b]}, + c: { ComparisonOperator: 'EQ', AttributeValueList: [ key.b ] }, }, - }), function(err, res) { + }), function (err, res) { if (err) return done(err) res.statusCode.should.equal(200) - res.body.Items.should.eql([{a: key.a, b: key.b, c: key.b, d: key.a, e: key.b, f: key.a}]) + res.body.Items.should.eql([ { a: key.a, b: key.b, c: key.b, d: key.a, e: key.b, f: key.a } ]) request(helpers.opts('Query', { TableName: helpers.testRangeTable, IndexName: 'index4', KeyConditions: { - c: {ComparisonOperator: 'EQ', AttributeValueList: [key.b]}, - d: {ComparisonOperator: 'EQ', AttributeValueList: [key.a]}, + c: { ComparisonOperator: 'EQ', AttributeValueList: [ key.b ] }, + d: { ComparisonOperator: 'EQ', AttributeValueList: [ key.a ] }, }, - }), function(err, res) { + }), function (err, res) { if (err) return done(err) res.statusCode.should.equal(200) - res.body.Items.should.eql([{a: key.a, b: key.b, c: key.b, d: key.a, e: key.b}]) + res.body.Items.should.eql([ { a: key.a, b: key.b, c: key.b, d: key.a, e: key.b } ]) done() }) }) diff --git a/test/updateTable.js b/test/updateTable.js index bce0013..8a621bc 100644 --- a/test/updateTable.js +++ b/test/updateTable.js @@ -1,158 +1,158 @@ var helpers = require('./helpers') var target = 'UpdateTable', - request = helpers.request, - opts = helpers.opts.bind(null, target), - assertType = helpers.assertType.bind(null, target), - assertValidation = helpers.assertValidation.bind(null, target), - assertNotFound = helpers.assertNotFound.bind(null, target) + request = helpers.request, + opts = helpers.opts.bind(null, target), + assertType = helpers.assertType.bind(null, target), + assertValidation = helpers.assertValidation.bind(null, target), + assertNotFound = helpers.assertNotFound.bind(null, target) -describe('updateTable', function() { +describe('updateTable', function () { - describe('serializations', function() { + describe('serializations', function () { - it('should return SerializationException when TableName is not a string', function(done) { + it('should return SerializationException when TableName is not a string', function (done) { assertType('TableName', 'String', done) }) - it('should return SerializationException when ProvisionedThroughput is not a struct', function(done) { + it('should return SerializationException when ProvisionedThroughput is not a struct', function (done) { assertType('ProvisionedThroughput', 'FieldStruct', done) }) - it('should return SerializationException when ProvisionedThroughput.WriteCapacityUnits is not a long', function(done) { + it('should return SerializationException when ProvisionedThroughput.WriteCapacityUnits is not a long', function (done) { assertType('ProvisionedThroughput.WriteCapacityUnits', 'Long', done) }) - it('should return SerializationException when ProvisionedThroughput.ReadCapacityUnits is not a long', function(done) { + it('should return SerializationException when ProvisionedThroughput.ReadCapacityUnits is not a long', function (done) { assertType('ProvisionedThroughput.ReadCapacityUnits', 'Long', done) }) - it('should return SerializationException when GlobalSecondaryIndexUpdates is not a list', function(done) { + it('should return SerializationException when GlobalSecondaryIndexUpdates is not a list', function (done) { assertType('GlobalSecondaryIndexUpdates', 'List', done) }) - it('should return SerializationException when GlobalSecondaryIndexUpdates.0 is not a struct', function(done) { + it('should return SerializationException when GlobalSecondaryIndexUpdates.0 is not a struct', function (done) { assertType('GlobalSecondaryIndexUpdates.0', 'ValueStruct', done) }) - it('should return SerializationException when GlobalSecondaryIndexUpdates.0.Update is not a struct', function(done) { + it('should return SerializationException when GlobalSecondaryIndexUpdates.0.Update is not a struct', function (done) { assertType('GlobalSecondaryIndexUpdates.0.Update', 'FieldStruct', done) }) - it('should return SerializationException when GlobalSecondaryIndexUpdates.0.Update.IndexName is not a string', function(done) { + it('should return SerializationException when GlobalSecondaryIndexUpdates.0.Update.IndexName is not a string', function (done) { assertType('GlobalSecondaryIndexUpdates.0.Update.IndexName', 'String', done) }) - it('should return SerializationException when GlobalSecondaryIndexUpdates.0.Update.ProvisionedThroughput is not a struct', function(done) { + it('should return SerializationException when GlobalSecondaryIndexUpdates.0.Update.ProvisionedThroughput is not a struct', function (done) { assertType('GlobalSecondaryIndexUpdates.0.Update.ProvisionedThroughput', 'FieldStruct', done) }) - it('should return SerializationException when GlobalSecondaryIndexUpdates.0.Update.ProvisionedThroughput.WriteCapacityUnits is not a long', function(done) { + it('should return SerializationException when GlobalSecondaryIndexUpdates.0.Update.ProvisionedThroughput.WriteCapacityUnits is not a long', function (done) { assertType('GlobalSecondaryIndexUpdates.0.Update.ProvisionedThroughput.WriteCapacityUnits', 'Long', done) }) - it('should return SerializationException when GlobalSecondaryIndexUpdates.0.Update.ProvisionedThroughput.ReadCapacityUnits is not a long', function(done) { + it('should return SerializationException when GlobalSecondaryIndexUpdates.0.Update.ProvisionedThroughput.ReadCapacityUnits is not a long', function (done) { assertType('GlobalSecondaryIndexUpdates.0.Update.ProvisionedThroughput.ReadCapacityUnits', 'Long', done) }) - it('should return SerializationException when GlobalSecondaryIndexUpdates.0.Create is not a struct', function(done) { + it('should return SerializationException when GlobalSecondaryIndexUpdates.0.Create is not a struct', function (done) { assertType('GlobalSecondaryIndexUpdates.0.Create', 'FieldStruct', done) }) - it('should return SerializationException when GlobalSecondaryIndexUpdates.0.Create.IndexName is not a string', function(done) { + it('should return SerializationException when GlobalSecondaryIndexUpdates.0.Create.IndexName is not a string', function (done) { assertType('GlobalSecondaryIndexUpdates.0.Create.IndexName', 'String', done) }) - it('should return SerializationException when GlobalSecondaryIndexUpdates.0.Create.ProvisionedThroughput is not a struct', function(done) { + it('should return SerializationException when GlobalSecondaryIndexUpdates.0.Create.ProvisionedThroughput is not a struct', function (done) { assertType('GlobalSecondaryIndexUpdates.0.Create.ProvisionedThroughput', 'FieldStruct', done) }) - it('should return SerializationException when GlobalSecondaryIndexUpdates.0.Create.ProvisionedThroughput.WriteCapacityUnits is not a long', function(done) { + it('should return SerializationException when GlobalSecondaryIndexUpdates.0.Create.ProvisionedThroughput.WriteCapacityUnits is not a long', function (done) { assertType('GlobalSecondaryIndexUpdates.0.Create.ProvisionedThroughput.WriteCapacityUnits', 'Long', done) }) - it('should return SerializationException when GlobalSecondaryIndexUpdates.0.Create.ProvisionedThroughput.ReadCapacityUnits is not a long', function(done) { + it('should return SerializationException when GlobalSecondaryIndexUpdates.0.Create.ProvisionedThroughput.ReadCapacityUnits is not a long', function (done) { assertType('GlobalSecondaryIndexUpdates.0.Create.ProvisionedThroughput.ReadCapacityUnits', 'Long', done) }) - it('should return SerializationException when GlobalSecondaryIndexUpdates.0.Create.KeySchema is not a list', function(done) { + it('should return SerializationException when GlobalSecondaryIndexUpdates.0.Create.KeySchema is not a list', function (done) { assertType('GlobalSecondaryIndexUpdates.0.Create.KeySchema', 'List', done) }) - it('should return SerializationException when GlobalSecondaryIndexUpdates.0.Create.KeySchema.0 is not a struct', function(done) { + it('should return SerializationException when GlobalSecondaryIndexUpdates.0.Create.KeySchema.0 is not a struct', function (done) { assertType('GlobalSecondaryIndexUpdates.0.Create.KeySchema.0', 'ValueStruct', done) }) - it('should return SerializationException when GlobalSecondaryIndexUpdates.0.Create.KeySchema.0.AttributeName is not a string', function(done) { + it('should return SerializationException when GlobalSecondaryIndexUpdates.0.Create.KeySchema.0.AttributeName is not a string', function (done) { assertType('GlobalSecondaryIndexUpdates.0.Create.KeySchema.0.AttributeName', 'String', done) }) - it('should return SerializationException when GlobalSecondaryIndexUpdates.0.Create.KeySchema.0.KeyType is not a string', function(done) { + it('should return SerializationException when GlobalSecondaryIndexUpdates.0.Create.KeySchema.0.KeyType is not a string', function (done) { assertType('GlobalSecondaryIndexUpdates.0.Create.KeySchema.0.KeyType', 'String', done) }) - it('should return SerializationException when GlobalSecondaryIndexUpdates.0.Create.Projection is not a struct', function(done) { + it('should return SerializationException when GlobalSecondaryIndexUpdates.0.Create.Projection is not a struct', function (done) { assertType('GlobalSecondaryIndexUpdates.0.Create.Projection', 'FieldStruct', done) }) - it('should return SerializationException when GlobalSecondaryIndexUpdates.0.Create.Projection.NonKeyAttributes is not a list', function(done) { + it('should return SerializationException when GlobalSecondaryIndexUpdates.0.Create.Projection.NonKeyAttributes is not a list', function (done) { assertType('GlobalSecondaryIndexUpdates.0.Create.Projection.NonKeyAttributes', 'List', done) }) - it('should return SerializationException when GlobalSecondaryIndexUpdates.0.Create.Projection.ProjectionType is not a string', function(done) { + it('should return SerializationException when GlobalSecondaryIndexUpdates.0.Create.Projection.ProjectionType is not a string', function (done) { assertType('GlobalSecondaryIndexUpdates.0.Create.Projection.ProjectionType', 'String', done) }) - it('should return SerializationException when GlobalSecondaryIndexUpdates.0.Create.Projection.NonKeyAttributes.0 is not a string', function(done) { + it('should return SerializationException when GlobalSecondaryIndexUpdates.0.Create.Projection.NonKeyAttributes.0 is not a string', function (done) { assertType('GlobalSecondaryIndexUpdates.0.Create.Projection.NonKeyAttributes.0', 'String', done) }) - it('should return SerializationException when GlobalSecondaryIndexUpdates.0.Delete is not a struct', function(done) { + it('should return SerializationException when GlobalSecondaryIndexUpdates.0.Delete is not a struct', function (done) { assertType('GlobalSecondaryIndexUpdates.0.Delete', 'FieldStruct', done) }) - it('should return SerializationException when GlobalSecondaryIndexUpdates.0.Delete.IndexName is not a strin', function(done) { + it('should return SerializationException when GlobalSecondaryIndexUpdates.0.Delete.IndexName is not a strin', function (done) { assertType('GlobalSecondaryIndexUpdates.0.Delete.IndexName', 'String', done) }) - it('should return SerializationException when BillingMode is not a string', function(done) { + it('should return SerializationException when BillingMode is not a string', function (done) { assertType('BillingMode', 'String', done) }) }) - describe('validations', function() { + describe('validations', function () { - it('should return ValidationException for no TableName', function(done) { + it('should return ValidationException for no TableName', function (done) { assertValidation({}, 'The parameter \'TableName\' is required but was not present in the request', done) }) - it('should return ValidationException for empty TableName', function(done) { - assertValidation({TableName: ''}, + it('should return ValidationException for empty TableName', function (done) { + assertValidation({ TableName: '' }, 'TableName must be at least 3 characters long and at most 255 characters long', done) }) - it('should return ValidationException for short TableName', function(done) { - assertValidation({TableName: 'a;'}, + it('should return ValidationException for short TableName', function (done) { + assertValidation({ TableName: 'a;' }, 'TableName must be at least 3 characters long and at most 255 characters long', done) }) - it('should return ValidationException for long TableName', function(done) { + it('should return ValidationException for long TableName', function (done) { var name = new Array(256 + 1).join('a') - assertValidation({TableName: name}, + assertValidation({ TableName: name }, 'TableName must be at least 3 characters long and at most 255 characters long', done) }) - it('should return ValidationException for null attributes', function(done) { - assertValidation({TableName: 'abc;'}, + it('should return ValidationException for null attributes', function (done) { + assertValidation({ TableName: 'abc;' }, '1 validation error detected: ' + 'Value \'abc;\' at \'tableName\' failed to satisfy constraint: ' + 'Member must satisfy regular expression pattern: [a-zA-Z0-9_.-]+', done) }) - it('should return ValidationException for empty ProvisionedThroughput', function(done) { - assertValidation({TableName: 'abc', ProvisionedThroughput: {}}, [ + it('should return ValidationException for empty ProvisionedThroughput', function (done) { + assertValidation({ TableName: 'abc', ProvisionedThroughput: {} }, [ 'Value null at \'provisionedThroughput.writeCapacityUnits\' failed to satisfy constraint: ' + 'Member must not be null', 'Value null at \'provisionedThroughput.readCapacityUnits\' failed to satisfy constraint: ' + @@ -160,8 +160,8 @@ describe('updateTable', function() { ], done) }) - it('should return ValidationException for low ProvisionedThroughput.WriteCapacityUnits', function(done) { - assertValidation({TableName: 'abc', ProvisionedThroughput: {ReadCapacityUnits: -1, WriteCapacityUnits: -1}}, [ + it('should return ValidationException for low ProvisionedThroughput.WriteCapacityUnits', function (done) { + assertValidation({ TableName: 'abc', ProvisionedThroughput: { ReadCapacityUnits: -1, WriteCapacityUnits: -1 } }, [ 'Value \'-1\' at \'provisionedThroughput.writeCapacityUnits\' failed to satisfy constraint: ' + 'Member must have value greater than or equal to 1', 'Value \'-1\' at \'provisionedThroughput.readCapacityUnits\' failed to satisfy constraint: ' + @@ -169,39 +169,39 @@ describe('updateTable', function() { ], done) }) - it('should return ValidationException for high ProvisionedThroughput.ReadCapacityUnits and neg', function(done) { - assertValidation({TableName: 'abc', - ProvisionedThroughput: {ReadCapacityUnits: 1000000000001, WriteCapacityUnits: -1}}, - '1 validation error detected: ' + + it('should return ValidationException for high ProvisionedThroughput.ReadCapacityUnits and neg', function (done) { + assertValidation({ TableName: 'abc', + ProvisionedThroughput: { ReadCapacityUnits: 1000000000001, WriteCapacityUnits: -1 } }, + '1 validation error detected: ' + 'Value \'-1\' at \'provisionedThroughput.writeCapacityUnits\' failed to satisfy constraint: ' + 'Member must have value greater than or equal to 1', done) }) - it('should return ValidationException for high ProvisionedThroughput.ReadCapacityUnits', function(done) { - assertValidation({TableName: 'abc', - ProvisionedThroughput: {ReadCapacityUnits: 1000000000001, WriteCapacityUnits: 1000000000001}}, - 'Given value 1000000000001 for ReadCapacityUnits is out of bounds', done) + it('should return ValidationException for high ProvisionedThroughput.ReadCapacityUnits', function (done) { + assertValidation({ TableName: 'abc', + ProvisionedThroughput: { ReadCapacityUnits: 1000000000001, WriteCapacityUnits: 1000000000001 } }, + 'Given value 1000000000001 for ReadCapacityUnits is out of bounds', done) }) - it('should return ValidationException for high ProvisionedThroughput.ReadCapacityUnits second', function(done) { - assertValidation({TableName: 'abc', - ProvisionedThroughput: {WriteCapacityUnits: 1000000000001, ReadCapacityUnits: 1000000000001}}, - 'Given value 1000000000001 for ReadCapacityUnits is out of bounds', done) + it('should return ValidationException for high ProvisionedThroughput.ReadCapacityUnits second', function (done) { + assertValidation({ TableName: 'abc', + ProvisionedThroughput: { WriteCapacityUnits: 1000000000001, ReadCapacityUnits: 1000000000001 } }, + 'Given value 1000000000001 for ReadCapacityUnits is out of bounds', done) }) - it('should return ValidationException for high ProvisionedThroughput.WriteCapacityUnits', function(done) { - assertValidation({TableName: 'abc', - ProvisionedThroughput: {ReadCapacityUnits: 1000000000000, WriteCapacityUnits: 1000000000001}}, - 'Given value 1000000000001 for WriteCapacityUnits is out of bounds', done) + it('should return ValidationException for high ProvisionedThroughput.WriteCapacityUnits', function (done) { + assertValidation({ TableName: 'abc', + ProvisionedThroughput: { ReadCapacityUnits: 1000000000000, WriteCapacityUnits: 1000000000001 } }, + 'Given value 1000000000001 for WriteCapacityUnits is out of bounds', done) }) - it('should return ValidationException for empty GlobalSecondaryIndexUpdates', function(done) { - assertValidation({TableName: 'abc', GlobalSecondaryIndexUpdates: []}, + it('should return ValidationException for empty GlobalSecondaryIndexUpdates', function (done) { + assertValidation({ TableName: 'abc', GlobalSecondaryIndexUpdates: [] }, 'At least one of ProvisionedThroughput, BillingMode, UpdateStreamEnabled, GlobalSecondaryIndexUpdates or SSESpecification or ReplicaUpdates is required', done) }) - it('should return ValidationException for empty Update', function(done) { - assertValidation({TableName: 'abc', GlobalSecondaryIndexUpdates: [{Update: {}}]}, [ + it('should return ValidationException for empty Update', function (done) { + assertValidation({ TableName: 'abc', GlobalSecondaryIndexUpdates: [ { Update: {} } ] }, [ 'Value null at \'globalSecondaryIndexUpdates.1.member.update.indexName\' failed to satisfy constraint: ' + 'Member must not be null', 'Value null at \'globalSecondaryIndexUpdates.1.member.update.provisionedThroughput\' failed to satisfy constraint: ' + @@ -209,11 +209,11 @@ describe('updateTable', function() { ], done) }) - it('should return ValidationException for bad IndexName and ProvisionedThroughput', function(done) { - assertValidation({TableName: 'abc', GlobalSecondaryIndexUpdates: [ - {Update: {IndexName: 'a', ProvisionedThroughput: {}}}, - {Update: {IndexName: 'abc;', ProvisionedThroughput: {ReadCapacityUnits: 1000000000001, WriteCapacityUnits: 0}}}, - ]}, [ + it('should return ValidationException for bad IndexName and ProvisionedThroughput', function (done) { + assertValidation({ TableName: 'abc', GlobalSecondaryIndexUpdates: [ + { Update: { IndexName: 'a', ProvisionedThroughput: {} } }, + { Update: { IndexName: 'abc;', ProvisionedThroughput: { ReadCapacityUnits: 1000000000001, WriteCapacityUnits: 0 } } }, + ] }, [ 'Value \'a\' at \'globalSecondaryIndexUpdates.1.member.update.indexName\' failed to satisfy constraint: ' + 'Member must have length greater than or equal to 3', 'Value null at \'globalSecondaryIndexUpdates.1.member.update.provisionedThroughput.writeCapacityUnits\' failed to satisfy constraint: ' + @@ -227,93 +227,95 @@ describe('updateTable', function() { ], done) }) - it('should return ValidationException for empty index struct', function(done) { - assertValidation({TableName: 'abc', GlobalSecondaryIndexUpdates: [{}]}, + it('should return ValidationException for empty index struct', function (done) { + assertValidation({ TableName: 'abc', GlobalSecondaryIndexUpdates: [ {} ] }, 'One or more parameter values were invalid: ' + 'One of GlobalSecondaryIndexUpdate.Update, ' + 'GlobalSecondaryIndexUpdate.Create, ' + 'GlobalSecondaryIndexUpdate.Delete must not be null', done) }) - it('should return ValidationException for too many empty GlobalSecondaryIndexUpdates', function(done) { - assertValidation({TableName: 'abc', GlobalSecondaryIndexUpdates: [{}, {}, {}, {}, {}, {}]}, + it('should return ValidationException for too many empty GlobalSecondaryIndexUpdates', function (done) { + assertValidation({ TableName: 'abc', GlobalSecondaryIndexUpdates: [ {}, {}, {}, {}, {}, {} ] }, 'One or more parameter values were invalid: ' + 'One of GlobalSecondaryIndexUpdate.Update, ' + 'GlobalSecondaryIndexUpdate.Create, ' + 'GlobalSecondaryIndexUpdate.Delete must not be null', done) }) - it('should return ValidationException for repeated GlobalSecondaryIndexUpdates', function(done) { - assertValidation({TableName: 'abc', GlobalSecondaryIndexUpdates: [{Delete: {IndexName: 'abc'}}, {Delete: {IndexName: 'abc'}}]}, + it('should return ValidationException for repeated GlobalSecondaryIndexUpdates', function (done) { + assertValidation({ TableName: 'abc', GlobalSecondaryIndexUpdates: [ { Delete: { IndexName: 'abc' } }, { Delete: { IndexName: 'abc' } } ] }, 'One or more parameter values were invalid: ' + 'Only one global secondary index update per index is allowed simultaneously. Index: abc', done) }) - it('should return ValidationException for ProvisionedThroughput update when PAY_PER_REQUEST', function(done) { - assertValidation({TableName: helpers.testHashNTable, ProvisionedThroughput: {ReadCapacityUnits: 1, WriteCapacityUnits: 1}}, + it('should return ValidationException for ProvisionedThroughput update when PAY_PER_REQUEST', function (done) { + assertValidation({ TableName: helpers.testHashNTable, ProvisionedThroughput: { ReadCapacityUnits: 1, WriteCapacityUnits: 1 } }, 'One or more parameter values were invalid: ' + 'Neither ReadCapacityUnits nor WriteCapacityUnits can be specified when BillingMode is PAY_PER_REQUEST', done) }) - it('should return ValidationException for PROVISIONED without ProvisionedThroughput', function(done) { - assertValidation({TableName: helpers.testHashNTable, BillingMode: 'PROVISIONED'}, + it('should return ValidationException for PROVISIONED without ProvisionedThroughput', function (done) { + assertValidation({ TableName: helpers.testHashNTable, BillingMode: 'PROVISIONED' }, 'One or more parameter values were invalid: ' + 'ProvisionedThroughput must be specified when BillingMode is PROVISIONED', done) }) - it('should return ResourceNotFoundException if table does not exist', function(done) { + it('should return ResourceNotFoundException if table does not exist', function (done) { var name = helpers.randomString() - assertNotFound({TableName: name, ProvisionedThroughput: {ReadCapacityUnits: 1, WriteCapacityUnits: 1}}, + assertNotFound({ TableName: name, ProvisionedThroughput: { ReadCapacityUnits: 1, WriteCapacityUnits: 1 } }, 'Requested resource not found: Table: ' + name + ' not found', done) }) - it('should return NotFoundException for high index ReadCapacityUnits when table does not exist', function(done) { - assertNotFound({TableName: 'abc', GlobalSecondaryIndexUpdates: [ - {Update: {IndexName: 'abc', ProvisionedThroughput: {ReadCapacityUnits: 1000000000001, WriteCapacityUnits: 1000000000001}}}, - ]}, 'Requested resource not found: Table: abc not found', done) + it('should return NotFoundException for high index ReadCapacityUnits when table does not exist', function (done) { + assertNotFound({ TableName: 'abc', GlobalSecondaryIndexUpdates: [ + { Update: { IndexName: 'abc', ProvisionedThroughput: { ReadCapacityUnits: 1000000000001, WriteCapacityUnits: 1000000000001 } } }, + ] }, 'Requested resource not found: Table: abc not found', done) }) - it('should return NotFoundException for high index WriteCapacityUnits when table does not exist', function(done) { - assertNotFound({TableName: 'abc', GlobalSecondaryIndexUpdates: [ - {Update: {IndexName: 'abc', ProvisionedThroughput: {ReadCapacityUnits: 1000000000000, WriteCapacityUnits: 1000000000001}}}, - ]}, 'Requested resource not found: Table: abc not found', done) + it('should return NotFoundException for high index WriteCapacityUnits when table does not exist', function (done) { + assertNotFound({ TableName: 'abc', GlobalSecondaryIndexUpdates: [ + { Update: { IndexName: 'abc', ProvisionedThroughput: { ReadCapacityUnits: 1000000000000, WriteCapacityUnits: 1000000000001 } } }, + ] }, 'Requested resource not found: Table: abc not found', done) }) - it('should return ValidationException for high index ReadCapacityUnits when index does not exist', function(done) { - assertValidation({TableName: helpers.testHashTable, GlobalSecondaryIndexUpdates: [ - {Update: {IndexName: 'abc', ProvisionedThroughput: {ReadCapacityUnits: 1000000000001, WriteCapacityUnits: 1000000000001}}}, - ]}, 'This operation cannot be performed with given input values. Please contact DynamoDB service team for more info: Action Blocked: IndexUpdate', done) + it('should return ValidationException for high index ReadCapacityUnits when index does not exist', function (done) { + assertValidation({ TableName: helpers.testHashTable, GlobalSecondaryIndexUpdates: [ + { Update: { IndexName: 'abc', ProvisionedThroughput: { ReadCapacityUnits: 1000000000001, WriteCapacityUnits: 1000000000001 } } }, + ] }, 'This operation cannot be performed with given input values. Please contact DynamoDB service team for more info: Action Blocked: IndexUpdate', done) }) - it('should return ValidationException for high index WriteCapacityUnits when index does not exist', function(done) { - assertValidation({TableName: helpers.testHashTable, GlobalSecondaryIndexUpdates: [ - {Update: {IndexName: 'abc', ProvisionedThroughput: {ReadCapacityUnits: 1000000000000, WriteCapacityUnits: 1000000000001}}}, - ]}, 'This operation cannot be performed with given input values. Please contact DynamoDB service team for more info: Action Blocked: IndexUpdate', done) + it('should return ValidationException for high index WriteCapacityUnits when index does not exist', function (done) { + assertValidation({ TableName: helpers.testHashTable, GlobalSecondaryIndexUpdates: [ + { Update: { IndexName: 'abc', ProvisionedThroughput: { ReadCapacityUnits: 1000000000000, WriteCapacityUnits: 1000000000001 } } }, + ] }, 'This operation cannot be performed with given input values. Please contact DynamoDB service team for more info: Action Blocked: IndexUpdate', done) }) - it('should return ValidationException if read and write are same', function(done) { - request(helpers.opts('DescribeTable', {TableName: helpers.testHashTable}), function(err, res) { + it('should return ValidationException if read and write are same', function (done) { + request(helpers.opts('DescribeTable', { TableName: helpers.testHashTable }), function (err, res) { if (err) return err(done) var readUnits = res.body.Table.ProvisionedThroughput.ReadCapacityUnits var writeUnits = res.body.Table.ProvisionedThroughput.WriteCapacityUnits - assertValidation({TableName: helpers.testHashTable, - ProvisionedThroughput: {ReadCapacityUnits: readUnits, WriteCapacityUnits: writeUnits}}, - 'The provisioned throughput for the table will not change. The requested value equals the current value. ' + + assertValidation({ TableName: helpers.testHashTable, + ProvisionedThroughput: { ReadCapacityUnits: readUnits, WriteCapacityUnits: writeUnits } }, + 'The provisioned throughput for the table will not change. The requested value equals the current value. ' + 'Current ReadCapacityUnits provisioned for the table: ' + readUnits + '. Requested ReadCapacityUnits: ' + readUnits + '. ' + 'Current WriteCapacityUnits provisioned for the table: ' + writeUnits + '. Requested WriteCapacityUnits: ' + writeUnits + '. ' + 'Refer to the Amazon DynamoDB Developer Guide for current limits and how to request higher limits.', done) }) }) - it('should return LimitExceededException for too many GlobalSecondaryIndexUpdates', function(done) { - request(opts({TableName: helpers.testHashTable, GlobalSecondaryIndexUpdates: [ - {Delete: {IndexName: 'abc'}}, - {Delete: {IndexName: 'abd'}}, - {Delete: {IndexName: 'abe'}}, - {Delete: {IndexName: 'abf'}}, - {Delete: {IndexName: 'abg'}}, - {Delete: {IndexName: 'abh'}}, - ]}), function(err, res) { + it('should return LimitExceededException for too many GlobalSecondaryIndexUpdates', function (done) { + request(opts({ TableName: helpers.testHashTable, GlobalSecondaryIndexUpdates: [ + { Delete: { IndexName: 'abc' } }, + { Delete: { IndexName: 'abd' } }, + { Delete: { IndexName: 'abe' } }, + { Delete: { IndexName: 'abf' } }, + { Delete: { IndexName: 'abg' } }, + { Delete: { IndexName: 'abh' } }, + ] }), function (err, res) { + if (err) return done(err) + res.body.__type.should.equal('com.amazonaws.dynamodb.v20120810#LimitExceededException') res.body.message.should.equal('Subscriber limit exceeded: Only 1 online index can be created or deleted simultaneously per table') res.statusCode.should.equal(400) @@ -324,22 +326,22 @@ describe('updateTable', function() { // TODO: No more than four decreases in a single UTC calendar day }) - describe('functionality', function() { + describe('functionality', function () { - it('should triple rates and then reduce if requested', function(done) { + it('should triple rates and then reduce if requested', function (done) { this.timeout(200000) var oldRead = helpers.readCapacity, oldWrite = helpers.writeCapacity, newRead = oldRead * 3, newWrite = oldWrite * 3, increase = Date.now() / 1000, - throughput = {ReadCapacityUnits: newRead, WriteCapacityUnits: newWrite} - request(opts({TableName: helpers.testHashTable, ProvisionedThroughput: throughput}), function(err, res) { + throughput = { ReadCapacityUnits: newRead, WriteCapacityUnits: newWrite } + request(opts({ TableName: helpers.testHashTable, ProvisionedThroughput: throughput }), function (err, res) { if (err) return done(err) res.statusCode.should.equal(200) var desc = res.body.TableDescription - desc.AttributeDefinitions.should.eql([{AttributeName: 'a', AttributeType: 'S'}]) + desc.AttributeDefinitions.should.eql([ { AttributeName: 'a', AttributeType: 'S' } ]) desc.CreationDateTime.should.be.below(Date.now() / 1000) desc.ItemCount.should.be.above(-1) - desc.KeySchema.should.eql([{AttributeName: 'a', KeyType: 'HASH'}]) + desc.KeySchema.should.eql([ { AttributeName: 'a', KeyType: 'HASH' } ]) desc.ProvisionedThroughput.LastIncreaseDateTime.should.be.above(increase - 5) desc.ProvisionedThroughput.NumberOfDecreasesToday.should.be.above(-1) desc.ProvisionedThroughput.ReadCapacityUnits.should.equal(oldRead) @@ -351,7 +353,7 @@ describe('updateTable', function() { var numDecreases = desc.ProvisionedThroughput.NumberOfDecreasesToday increase = desc.ProvisionedThroughput.LastIncreaseDateTime - helpers.waitUntilActive(helpers.testHashTable, function(err, res) { + helpers.waitUntilActive(helpers.testHashTable, function (err, res) { if (err) return done(err) var decrease = Date.now() / 1000 @@ -362,8 +364,8 @@ describe('updateTable', function() { increase = desc.ProvisionedThroughput.LastIncreaseDateTime - throughput = {ReadCapacityUnits: oldRead, WriteCapacityUnits: oldWrite} - request(opts({TableName: helpers.testHashTable, ProvisionedThroughput: throughput}), function(err, res) { + throughput = { ReadCapacityUnits: oldRead, WriteCapacityUnits: oldWrite } + request(opts({ TableName: helpers.testHashTable, ProvisionedThroughput: throughput }), function (err, res) { if (err) return done(err) res.statusCode.should.equal(200) @@ -377,7 +379,7 @@ describe('updateTable', function() { decrease = desc.ProvisionedThroughput.LastDecreaseDateTime - helpers.waitUntilActive(helpers.testHashTable, function(err, res) { + helpers.waitUntilActive(helpers.testHashTable, function (err, res) { if (err) return done(err) desc = res.body.Table @@ -395,24 +397,24 @@ describe('updateTable', function() { }) // XXX: this takes more than 20 mins to run - it.skip('should allow table to be converted to PAY_PER_REQUEST and back again', function(done) { + it.skip('should allow table to be converted to PAY_PER_REQUEST and back again', function (done) { this.timeout(1500000) var read = helpers.readCapacity, write = helpers.writeCapacity, - throughput = {ReadCapacityUnits: read, WriteCapacityUnits: write}, decrease = Date.now() / 1000 - request(opts({TableName: helpers.testRangeTable, BillingMode: 'PAY_PER_REQUEST'}), function(err, res) { + throughput = { ReadCapacityUnits: read, WriteCapacityUnits: write }, decrease = Date.now() / 1000 + request(opts({ TableName: helpers.testRangeTable, BillingMode: 'PAY_PER_REQUEST' }), function (err, res) { if (err) return done(err) res.statusCode.should.equal(200) var desc = res.body.TableDescription desc.TableStatus.should.equal('UPDATING') - desc.BillingModeSummary.should.eql({BillingMode: 'PAY_PER_REQUEST'}) - desc.TableThroughputModeSummary.should.eql({TableThroughputMode: 'PAY_PER_REQUEST'}) + desc.BillingModeSummary.should.eql({ BillingMode: 'PAY_PER_REQUEST' }) + desc.TableThroughputModeSummary.should.eql({ TableThroughputMode: 'PAY_PER_REQUEST' }) desc.ProvisionedThroughput.LastDecreaseDateTime.should.be.above(decrease - 5) desc.ProvisionedThroughput.NumberOfDecreasesToday.should.be.above(-1) desc.ProvisionedThroughput.ReadCapacityUnits.should.equal(0) desc.ProvisionedThroughput.WriteCapacityUnits.should.equal(0) - desc.GlobalSecondaryIndexes.forEach(function(index) { + desc.GlobalSecondaryIndexes.forEach(function (index) { index.IndexStatus.should.equal('UPDATING') index.ProvisionedThroughput.should.eql({ NumberOfDecreasesToday: 0, @@ -421,7 +423,7 @@ describe('updateTable', function() { }) }) - helpers.waitUntilActive(helpers.testRangeTable, function(err, res) { + helpers.waitUntilActive(helpers.testRangeTable, function (err, res) { if (err) return done(err) var desc = res.body.Table @@ -432,59 +434,39 @@ describe('updateTable', function() { desc.ProvisionedThroughput.NumberOfDecreasesToday.should.be.above(-1) desc.ProvisionedThroughput.ReadCapacityUnits.should.equal(0) desc.ProvisionedThroughput.WriteCapacityUnits.should.equal(0) - desc.GlobalSecondaryIndexes.forEach(function(index) { + desc.GlobalSecondaryIndexes.forEach(function (index) { index.ProvisionedThroughput.LastDecreaseDateTime.should.be.above(decrease - 5) index.ProvisionedThroughput.NumberOfDecreasesToday.should.be.above(0) index.ProvisionedThroughput.ReadCapacityUnits.should.equal(0) index.ProvisionedThroughput.WriteCapacityUnits.should.equal(0) }) - assertValidation({TableName: helpers.testRangeTable, BillingMode: 'PROVISIONED', ProvisionedThroughput: throughput}, - 'One or more parameter values were invalid: ' + - 'ProvisionedThroughput must be specified for index: index3,index4', function(err) { - if (err) return done(err) - - request(opts({ - TableName: helpers.testRangeTable, - BillingMode: 'PROVISIONED', - ProvisionedThroughput: throughput, - GlobalSecondaryIndexUpdates: [{ - Update: { - IndexName: 'index3', - ProvisionedThroughput: throughput, - }, - }, { - Update: { - IndexName: 'index4', - ProvisionedThroughput: throughput, - }, - }], - }), function(err, res) { + assertValidation({ TableName: helpers.testRangeTable, BillingMode: 'PROVISIONED', ProvisionedThroughput: throughput }, + 'One or more parameter values were invalid: ' + + 'ProvisionedThroughput must be specified for index: index3,index4', function (err) { if (err) return done(err) - res.statusCode.should.equal(200) - - var desc = res.body.TableDescription - desc.TableStatus.should.equal('UPDATING') - desc.BillingModeSummary.BillingMode.should.equal('PROVISIONED') - desc.BillingModeSummary.LastUpdateToPayPerRequestDateTime.should.be.above(decrease - 5) - desc.TableThroughputModeSummary.TableThroughputMode.should.equal('PROVISIONED') - desc.TableThroughputModeSummary.LastUpdateToPayPerRequestDateTime.should.be.above(decrease - 5) - desc.ProvisionedThroughput.NumberOfDecreasesToday.should.be.above(-1) - desc.ProvisionedThroughput.ReadCapacityUnits.should.equal(read) - desc.ProvisionedThroughput.WriteCapacityUnits.should.equal(write) - - desc.GlobalSecondaryIndexes.forEach(function(index) { - index.IndexStatus.should.equal('UPDATING') - index.ProvisionedThroughput.LastDecreaseDateTime.should.be.above(decrease - 5) - index.ProvisionedThroughput.NumberOfDecreasesToday.should.be.above(0) - index.ProvisionedThroughput.ReadCapacityUnits.should.equal(read) - index.ProvisionedThroughput.WriteCapacityUnits.should.equal(write) - }) - helpers.waitUntilActive(helpers.testRangeTable, function(err, res) { + request(opts({ + TableName: helpers.testRangeTable, + BillingMode: 'PROVISIONED', + ProvisionedThroughput: throughput, + GlobalSecondaryIndexUpdates: [ { + Update: { + IndexName: 'index3', + ProvisionedThroughput: throughput, + }, + }, { + Update: { + IndexName: 'index4', + ProvisionedThroughput: throughput, + }, + } ], + }), function (err, res) { if (err) return done(err) + res.statusCode.should.equal(200) - var desc = res.body.Table + var desc = res.body.TableDescription + desc.TableStatus.should.equal('UPDATING') desc.BillingModeSummary.BillingMode.should.equal('PROVISIONED') desc.BillingModeSummary.LastUpdateToPayPerRequestDateTime.should.be.above(decrease - 5) desc.TableThroughputModeSummary.TableThroughputMode.should.equal('PROVISIONED') @@ -493,17 +475,37 @@ describe('updateTable', function() { desc.ProvisionedThroughput.ReadCapacityUnits.should.equal(read) desc.ProvisionedThroughput.WriteCapacityUnits.should.equal(write) - desc.GlobalSecondaryIndexes.forEach(function(index) { + desc.GlobalSecondaryIndexes.forEach(function (index) { + index.IndexStatus.should.equal('UPDATING') index.ProvisionedThroughput.LastDecreaseDateTime.should.be.above(decrease - 5) index.ProvisionedThroughput.NumberOfDecreasesToday.should.be.above(0) index.ProvisionedThroughput.ReadCapacityUnits.should.equal(read) index.ProvisionedThroughput.WriteCapacityUnits.should.equal(write) }) - done() + helpers.waitUntilActive(helpers.testRangeTable, function (err, res) { + if (err) return done(err) + + var desc = res.body.Table + desc.BillingModeSummary.BillingMode.should.equal('PROVISIONED') + desc.BillingModeSummary.LastUpdateToPayPerRequestDateTime.should.be.above(decrease - 5) + desc.TableThroughputModeSummary.TableThroughputMode.should.equal('PROVISIONED') + desc.TableThroughputModeSummary.LastUpdateToPayPerRequestDateTime.should.be.above(decrease - 5) + desc.ProvisionedThroughput.NumberOfDecreasesToday.should.be.above(-1) + desc.ProvisionedThroughput.ReadCapacityUnits.should.equal(read) + desc.ProvisionedThroughput.WriteCapacityUnits.should.equal(write) + + desc.GlobalSecondaryIndexes.forEach(function (index) { + index.ProvisionedThroughput.LastDecreaseDateTime.should.be.above(decrease - 5) + index.ProvisionedThroughput.NumberOfDecreasesToday.should.be.above(0) + index.ProvisionedThroughput.ReadCapacityUnits.should.equal(read) + index.ProvisionedThroughput.WriteCapacityUnits.should.equal(write) + }) + + done() + }) }) }) - }) }) }) }) diff --git a/validations/batchGetItem.js b/validations/batchGetItem.js index 6fbea27..22ebaa8 100644 --- a/validations/batchGetItem.js +++ b/validations/batchGetItem.js @@ -1,10 +1,10 @@ var validations = require('./index'), - db = require('../db') + db = require('../db') exports.types = { ReturnConsumedCapacity: { type: 'String', - enum: ['INDEXES', 'TOTAL', 'NONE'], + enum: [ 'INDEXES', 'TOTAL', 'NONE' ], }, RequestItems: { type: 'Map', @@ -47,13 +47,13 @@ exports.types = { }, } -exports.custom = function(data) { +exports.custom = function (data) { var numReqs = 0 for (var table in data.RequestItems) { var tableData = data.RequestItems[table] - var msg = validations.validateExpressionParams(tableData, ['ProjectionExpression'], ['AttributesToGet']) + var msg = validations.validateExpressionParams(tableData, [ 'ProjectionExpression' ], [ 'AttributesToGet' ]) if (msg) return msg if (tableData.AttributesToGet) { @@ -74,7 +74,7 @@ exports.custom = function(data) { } // TODO: this is unnecessarily expensive - var keyStr = Object.keys(key).sort().map(function(attr) { return db.toRangeStr(key[attr]) }).join('/') + var keyStr = Object.keys(key).sort().map(function (attr) { return db.toRangeStr(key[attr]) }).join('/') if (seenKeys[keyStr]) return 'Provided list of item keys contains duplicates' seenKeys[keyStr] = true diff --git a/validations/batchWriteItem.js b/validations/batchWriteItem.js index 27d92ce..7130cb3 100644 --- a/validations/batchWriteItem.js +++ b/validations/batchWriteItem.js @@ -1,14 +1,14 @@ var validations = require('./index'), - db = require('../db') + db = require('../db') exports.types = { ReturnConsumedCapacity: { type: 'String', - enum: ['INDEXES', 'TOTAL', 'NONE'], + enum: [ 'INDEXES', 'TOTAL', 'NONE' ], }, ReturnItemCollectionMetrics: { type: 'String', - enum: ['SIZE', 'NONE'], + enum: [ 'SIZE', 'NONE' ], }, RequestItems: { type: 'Map>', @@ -54,10 +54,10 @@ exports.types = { }, } -exports.custom = function(data, store) { +exports.custom = function (data, store) { var table, i, request, key, msg for (table in data.RequestItems) { - if (data.RequestItems[table].some(function(item) { return !Object.keys(item).length })) // eslint-disable-line no-loop-func + if (data.RequestItems[table].some(function (item) { return !Object.keys(item).length })) // eslint-disable-line no-loop-func return 'Supplied AttributeValue has more than one datatypes set, ' + 'must contain exactly one of the supported datatypes' for (i = 0; i < data.RequestItems[table].length; i++) { @@ -69,7 +69,8 @@ exports.custom = function(data, store) { } if (db.itemSize(request.PutRequest.Item) > store.options.maxItemSize) return 'Item size has exceeded the maximum allowed size' - } else if (request.DeleteRequest) { + } + else if (request.DeleteRequest) { for (key in request.DeleteRequest.Key) { msg = validations.validateAttributeValue(request.DeleteRequest.Key[key]) if (msg) return msg diff --git a/validations/createTable.js b/validations/createTable.js index 4bd9fc6..1a8e472 100644 --- a/validations/createTable.js +++ b/validations/createTable.js @@ -12,7 +12,7 @@ exports.types = { AttributeType: { type: 'String', notNull: true, - enum: ['B', 'N', 'S'], + enum: [ 'B', 'N', 'S' ], }, }, }, @@ -25,7 +25,7 @@ exports.types = { }, BillingMode: { type: 'String', - enum: ['PROVISIONED', 'PAY_PER_REQUEST'], + enum: [ 'PROVISIONED', 'PAY_PER_REQUEST' ], }, ProvisionedThroughput: { type: 'FieldStruct', @@ -57,7 +57,7 @@ exports.types = { KeyType: { type: 'String', notNull: true, - enum: ['HASH', 'RANGE'], + enum: [ 'HASH', 'RANGE' ], }, }, }, @@ -99,7 +99,7 @@ exports.types = { children: { ProjectionType: { type: 'String', - enum: ['ALL', 'INCLUDE', 'KEYS_ONLY'], + enum: [ 'ALL', 'INCLUDE', 'KEYS_ONLY' ], }, NonKeyAttributes: { type: 'List', @@ -148,7 +148,7 @@ exports.types = { children: { ProjectionType: { type: 'String', - enum: ['ALL', 'INCLUDE', 'KEYS_ONLY'], + enum: [ 'ALL', 'INCLUDE', 'KEYS_ONLY' ], }, NonKeyAttributes: { type: 'List', @@ -177,14 +177,15 @@ exports.types = { }, } -exports.custom = function(data) { +exports.custom = function (data) { if (data.BillingMode == 'PAY_PER_REQUEST') { if (data.ProvisionedThroughput) { return 'One or more parameter values were invalid: ' + 'Neither ReadCapacityUnits nor WriteCapacityUnits can be specified when BillingMode is PAY_PER_REQUEST' } - } else { + } + else { if (data.BillingMode != 'PAY_PER_REQUEST' && (!data.ProvisionedThroughput || !data.ProvisionedThroughput.ReadCapacityUnits || !data.ProvisionedThroughput.WriteCapacityUnits)) { return 'One or more parameter values were invalid: ' + @@ -197,13 +198,13 @@ exports.custom = function(data) { return 'Given value ' + data.ProvisionedThroughput.WriteCapacityUnits + ' for WriteCapacityUnits is out of bounds' } - var defns = data.AttributeDefinitions.map(function(key) { return key.AttributeName }) - var keys = data.KeySchema.map(function(key) { return key.AttributeName }) + var defns = data.AttributeDefinitions.map(function (key) { return key.AttributeName }) + var keys = data.KeySchema.map(function (key) { return key.AttributeName }) if (keys.length > defns.length) return 'Invalid KeySchema: Some index key attribute have no definition' - if (keys.some(function(key) { return !~defns.indexOf(key) })) + if (keys.some(function (key) { return !~defns.indexOf(key) })) return 'One or more parameter values were invalid: Some index key attributes are not defined in ' + 'AttributeDefinitions. Keys: [' + keys.join(', ') + '], AttributeDefinitions: [' + defns.join(', ') + ']' @@ -235,8 +236,8 @@ exports.custom = function(data) { for (i = 0; i < data.LocalSecondaryIndexes.length; i++) { indexName = data.LocalSecondaryIndexes[i].IndexName - indexKeys = data.LocalSecondaryIndexes[i].KeySchema.map(function(key) { return key.AttributeName }) // eslint-disable-line no-loop-func - if (indexKeys.some(function(key) { return !~defns.indexOf(key) })) // eslint-disable-line no-loop-func + indexKeys = data.LocalSecondaryIndexes[i].KeySchema.map(function (key) { return key.AttributeName }) // eslint-disable-line no-loop-func + if (indexKeys.some(function (key) { return !~defns.indexOf(key) })) // eslint-disable-line no-loop-func return 'One or more parameter values were invalid: ' + 'Some index key attributes are not defined in AttributeDefinitions. ' + 'Keys: [' + indexKeys.join(', ') + '], AttributeDefinitions: [' + defns.join(', ') + ']' @@ -286,8 +287,8 @@ exports.custom = function(data) { for (i = 0; i < data.GlobalSecondaryIndexes.length; i++) { indexName = data.GlobalSecondaryIndexes[i].IndexName - indexKeys = data.GlobalSecondaryIndexes[i].KeySchema.map(function(key) { return key.AttributeName }) // eslint-disable-line no-loop-func - if (indexKeys.some(function(key) { return !~defns.indexOf(key) })) // eslint-disable-line no-loop-func + indexKeys = data.GlobalSecondaryIndexes[i].KeySchema.map(function (key) { return key.AttributeName }) // eslint-disable-line no-loop-func + if (indexKeys.some(function (key) { return !~defns.indexOf(key) })) // eslint-disable-line no-loop-func return 'One or more parameter values were invalid: ' + 'Some index key attributes are not defined in AttributeDefinitions. ' + 'Keys: [' + indexKeys.join(', ') + '], AttributeDefinitions: [' + defns.join(', ') + ']' diff --git a/validations/deleteItem.js b/validations/deleteItem.js index 17be7c4..a4418b7 100644 --- a/validations/deleteItem.js +++ b/validations/deleteItem.js @@ -3,7 +3,7 @@ var validations = require('./index') exports.types = { ReturnConsumedCapacity: { type: 'String', - enum: ['INDEXES', 'TOTAL', 'NONE'], + enum: [ 'INDEXES', 'TOTAL', 'NONE' ], }, TableName: { type: 'String', @@ -14,11 +14,11 @@ exports.types = { }, ReturnValues: { type: 'String', - enum: ['ALL_NEW', 'UPDATED_OLD', 'ALL_OLD', 'NONE', 'UPDATED_NEW'], + enum: [ 'ALL_NEW', 'UPDATED_OLD', 'ALL_OLD', 'NONE', 'UPDATED_NEW' ], }, ReturnItemCollectionMetrics: { type: 'String', - enum: ['SIZE', 'NONE'], + enum: [ 'SIZE', 'NONE' ], }, Key: { type: 'Map', @@ -27,7 +27,7 @@ exports.types = { }, ConditionalOperator: { type: 'String', - enum: ['OR', 'AND'], + enum: [ 'OR', 'AND' ], }, Expected: { type: 'Map', @@ -40,7 +40,7 @@ exports.types = { }, ComparisonOperator: { type: 'String', - enum: ['IN', 'NULL', 'BETWEEN', 'LT', 'NOT_CONTAINS', 'EQ', 'GT', 'NOT_NULL', 'NE', 'LE', 'BEGINS_WITH', 'GE', 'CONTAINS'], + enum: [ 'IN', 'NULL', 'BETWEEN', 'LT', 'NOT_CONTAINS', 'EQ', 'GT', 'NOT_NULL', 'NE', 'LE', 'BEGINS_WITH', 'GE', 'CONTAINS' ], }, Exists: 'Boolean', Value: 'AttrStruct', @@ -60,9 +60,9 @@ exports.types = { }, } -exports.custom = function(data) { +exports.custom = function (data) { - var msg = validations.validateExpressionParams(data, ['ConditionExpression'], ['Expected']) + var msg = validations.validateExpressionParams(data, [ 'ConditionExpression' ], [ 'Expected' ]) if (msg) return msg for (var key in data.Key) { diff --git a/validations/getItem.js b/validations/getItem.js index 4559cf0..3b4908f 100644 --- a/validations/getItem.js +++ b/validations/getItem.js @@ -3,7 +3,7 @@ var validations = require('./index') exports.types = { ReturnConsumedCapacity: { type: 'String', - enum: ['INDEXES', 'TOTAL', 'NONE'], + enum: [ 'INDEXES', 'TOTAL', 'NONE' ], }, AttributesToGet: { type: 'List', @@ -33,9 +33,9 @@ exports.types = { }, } -exports.custom = function(data) { +exports.custom = function (data) { - var msg = validations.validateExpressionParams(data, ['ProjectionExpression'], ['AttributesToGet']) + var msg = validations.validateExpressionParams(data, [ 'ProjectionExpression' ], [ 'AttributesToGet' ]) if (msg) return msg for (var key in data.Key) { diff --git a/validations/index.js b/validations/index.js index 3b55ba5..8a591a1 100644 --- a/validations/index.js +++ b/validations/index.js @@ -1,8 +1,8 @@ var Big = require('big.js'), - db = require('../db'), - conditionParser = require('../db/conditionParser'), - projectionParser = require('../db/projectionParser'), - updateParser = require('../db/updateParser') + db = require('../db'), + conditionParser = require('../db/conditionParser'), + projectionParser = require('../db/projectionParser'), + updateParser = require('../db/updateParser') exports.checkTypes = checkTypes exports.checkValidations = checkValidations @@ -15,7 +15,7 @@ exports.validateExpressionParams = validateExpressionParams exports.validateExpressions = validateExpressions exports.convertKeyCondition = convertKeyCondition -function checkTypes(data, types) { +function checkTypes (data, types) { var key for (key in data) { // TODO: deal with nulls @@ -23,13 +23,13 @@ function checkTypes(data, types) { delete data[key] } - return Object.keys(types).reduce(function(newData, key) { + return Object.keys(types).reduce(function (newData, key) { var val = checkType(data[key], types[key]) if (val != null) newData[key] = val return newData }, {}) - function typeError(msg) { + function typeError (msg) { var err = new Error(msg) err.statusCode = 400 err.body = { @@ -39,10 +39,10 @@ function checkTypes(data, types) { return err } - function checkType(val, type) { + function checkType (val, type) { if (val == null) return null var children = type.children - if (typeof children == 'string') children = {type: children} + if (typeof children == 'string') children = { type: children } if (type.type) type = type.type var subtypeMatch = type.match(/(.+?)<(.+)>$/), subtype if (subtypeMatch != null) { @@ -84,147 +84,149 @@ function checkTypes(data, types) { } switch (type) { - case 'Boolean': - switch (typeof val) { - case 'number': - throw typeError((val % 1 === 0 ? 'NUMBER_VALUE' : 'DECIMAL_VALUE') + ' cannot be converted to ' + type) - case 'string': - // 'true'/'false'/'1'/'0'/'no'/'yes' seem to convert fine - val = val.toUpperCase() - if (~['TRUE', '1', 'YES'].indexOf(val)) { - val = true - } else if (~['FALSE', '0', 'NO'].indexOf(val)) { - val = false - } else { - throw typeError('Unexpected token received from parser') - } - break - case 'object': - if (Array.isArray(val)) throw typeError('Unrecognized collection type class java.lang.' + type) - throw typeError('Start of structure or map found where not expected') + case 'Boolean': + switch (typeof val) { + case 'number': + throw typeError((val % 1 === 0 ? 'NUMBER_VALUE' : 'DECIMAL_VALUE') + ' cannot be converted to ' + type) + case 'string': + // 'true'/'false'/'1'/'0'/'no'/'yes' seem to convert fine + val = val.toUpperCase() + if (~[ 'TRUE', '1', 'YES' ].indexOf(val)) { + val = true } - return val - case 'Short': - case 'Integer': - case 'Long': - case 'Double': - switch (typeof val) { - case 'boolean': - throw typeError((val ? 'TRUE_VALUE' : 'FALSE_VALUE') + ' cannot be converted to ' + type) - case 'number': - if (type != 'Double') val = Math.floor(val) - break - case 'string': - throw typeError('STRING_VALUE cannot be converted to ' + type) - case 'object': - if (Array.isArray(val)) throw typeError('Unrecognized collection type class java.lang.' + type) - throw typeError('Start of structure or map found where not expected') + else if (~[ 'FALSE', '0', 'NO' ].indexOf(val)) { + val = false } - return val - case 'String': - switch (typeof val) { - case 'boolean': - throw typeError((val ? 'TRUE_VALUE' : 'FALSE_VALUE') + ' cannot be converted to ' + type) - case 'number': - throw typeError((val % 1 === 0 ? 'NUMBER_VALUE' : 'DECIMAL_VALUE') + ' cannot be converted to ' + type) - case 'object': - if (Array.isArray(val)) throw typeError('Unrecognized collection type class java.lang.' + type) - throw typeError('Start of structure or map found where not expected') + else { + throw typeError('Unexpected token received from parser') } - return val - case 'Blob': - switch (typeof val) { - case 'boolean': - case 'number': - throw typeError('only base-64-encoded strings are convertible to bytes') - case 'object': - if (Array.isArray(val)) throw typeError('Unrecognized collection type class java.nio.ByteBuffer') - throw typeError('Start of structure or map found where not expected') - } - if (val.length % 4) - throw typeError('Base64 encoded length is expected a multiple of 4 bytes but found: ' + val.length) + break + case 'object': + if (Array.isArray(val)) throw typeError('Unrecognized collection type class java.lang.' + type) + throw typeError('Start of structure or map found where not expected') + } + return val + case 'Short': + case 'Integer': + case 'Long': + case 'Double': + switch (typeof val) { + case 'boolean': + throw typeError((val ? 'TRUE_VALUE' : 'FALSE_VALUE') + ' cannot be converted to ' + type) + case 'number': + if (type != 'Double') val = Math.floor(val) + break + case 'string': + throw typeError('STRING_VALUE cannot be converted to ' + type) + case 'object': + if (Array.isArray(val)) throw typeError('Unrecognized collection type class java.lang.' + type) + throw typeError('Start of structure or map found where not expected') + } + return val + case 'String': + switch (typeof val) { + case 'boolean': + throw typeError((val ? 'TRUE_VALUE' : 'FALSE_VALUE') + ' cannot be converted to ' + type) + case 'number': + throw typeError((val % 1 === 0 ? 'NUMBER_VALUE' : 'DECIMAL_VALUE') + ' cannot be converted to ' + type) + case 'object': + if (Array.isArray(val)) throw typeError('Unrecognized collection type class java.lang.' + type) + throw typeError('Start of structure or map found where not expected') + } + return val + case 'Blob': + switch (typeof val) { + case 'boolean': + case 'number': + throw typeError('only base-64-encoded strings are convertible to bytes') + case 'object': + if (Array.isArray(val)) throw typeError('Unrecognized collection type class java.nio.ByteBuffer') + throw typeError('Start of structure or map found where not expected') + } + if (val.length % 4) + throw typeError('Base64 encoded length is expected a multiple of 4 bytes but found: ' + val.length) // TODO: need a better check than this... - if (Buffer.from(val, 'base64').toString('base64') != val) - throw typeError('Invalid last non-pad Base64 character dectected') - return val - case 'List': - switch (typeof val) { - case 'boolean': - case 'number': - case 'string': - throw typeError('Unexpected field type') - case 'object': - if (!Array.isArray(val)) throw typeError('Start of structure or map found where not expected') - } - return val.map(function(child) { return checkType(child, children) }) - case 'ParameterizedList': - switch (typeof val) { - case 'boolean': - case 'number': - case 'string': - throw typeError("class sun.reflect.generics.reflectiveObjects.ParameterizedTypeImpl cannot be cast to class java.lang.Class (sun.reflect.generics.reflectiveObjects.ParameterizedTypeImpl and java.lang.Class are in module java.base of loader 'bootstrap')") - case 'object': - if (!Array.isArray(val)) throw typeError('Start of structure or map found where not expected') - } - return val.map(function(child) { return checkType(child, children) }) - case 'ParameterizedMap': - switch (typeof val) { - case 'boolean': - case 'number': - case 'string': - throw typeError("class sun.reflect.generics.reflectiveObjects.ParameterizedTypeImpl cannot be cast to class java.lang.Class (sun.reflect.generics.reflectiveObjects.ParameterizedTypeImpl and java.lang.Class are in module java.base of loader 'bootstrap')") - case 'object': - if (Array.isArray(val)) throw typeError('Unrecognized collection type java.util.Map') - } - return Object.keys(val).reduce(function(newVal, key) { - newVal[key] = checkType(val[key], children) - return newVal - }, {}) - case 'Map': - switch (typeof val) { - case 'boolean': - case 'number': - case 'string': - throw typeError('Unexpected field type') - case 'object': - if (Array.isArray(val)) { - throw typeError('Unrecognized collection type java.util.Map') + } + return Object.keys(val).reduce(function (newVal, key) { + newVal[key] = checkType(val[key], children) + return newVal + }, {}) + case 'Map': + switch (typeof val) { + case 'boolean': + case 'number': + case 'string': + throw typeError('Unexpected field type') + case 'object': + if (Array.isArray(val)) { + throw typeError('Unrecognized collection type java.util.Map') - } - } - return Object.keys(val).reduce(function(newVal, key) { - newVal[key] = checkType(val[key], children) - return newVal - }, {}) - case 'ValueStruct': - switch (typeof val) { - case 'boolean': - case 'number': - case 'string': - throw typeError('Unexpected value type in payload') - case 'object': - if (Array.isArray(val)) throw typeError('Unrecognized collection type class com.amazonaws.dynamodb.v20120810.' + subtype) } - return checkTypes(val, children) - case 'FieldStruct': - switch (typeof val) { - case 'boolean': - case 'number': - case 'string': - throw typeError('Unexpected field type') - case 'object': - if (Array.isArray(val)) throw typeError('Unrecognized collection type class com.amazonaws.dynamodb.v20120810.' + subtype) - } - return checkTypes(val, children) - default: - throw new Error('Unknown type: ' + type) + } + return Object.keys(val).reduce(function (newVal, key) { + newVal[key] = checkType(val[key], children) + return newVal + }, {}) + case 'ValueStruct': + switch (typeof val) { + case 'boolean': + case 'number': + case 'string': + throw typeError('Unexpected value type in payload') + case 'object': + if (Array.isArray(val)) throw typeError('Unrecognized collection type class com.amazonaws.dynamodb.v20120810.' + subtype) + } + return checkTypes(val, children) + case 'FieldStruct': + switch (typeof val) { + case 'boolean': + case 'number': + case 'string': + throw typeError('Unexpected field type') + case 'object': + if (Array.isArray(val)) throw typeError('Unrecognized collection type class com.amazonaws.dynamodb.v20120810.' + subtype) + } + return checkTypes(val, children) + default: + throw new Error('Unknown type: ' + type) } } } var validateFns = {} -function checkValidations(data, validations, custom, store) { +function checkValidations (data, validations, custom, store) { var attr, msg, errors = [] for (attr in validations) { @@ -237,7 +239,7 @@ function checkValidations(data, validations, custom, store) { } } - function checkNonRequireds(data, types, parent) { + function checkNonRequireds (data, types, parent) { for (attr in types) { checkNonRequired(attr, data[attr], types[attr], parent) } @@ -245,11 +247,11 @@ function checkValidations(data, validations, custom, store) { checkNonRequireds(data, validations) - function checkNonRequired(attr, data, validations, parent) { + function checkNonRequired (attr, data, validations, parent) { if (validations == null || typeof validations != 'object') return for (var validation in validations) { if (errors.length >= 10) return - if (~['type', 'required', 'tableName'].indexOf(validation)) continue + if (~[ 'type', 'required', 'tableName' ].indexOf(validation)) continue if (validation != 'notNull' && data == null) continue if (validation == 'children') { if (/List$/.test(validations.type)) { @@ -258,8 +260,9 @@ function checkValidations(data, validations, custom, store) { (parent ? parent + '.' : '') + toLowerFirst(attr) + '.' + (i + 1)) } continue - } else if (/Map/.test(validations.type)) { - Object.keys(data).forEach(function(key) { // eslint-disable-line no-loop-func + } + else if (/Map/.test(validations.type)) { + Object.keys(data).forEach(function (key) { // eslint-disable-line no-loop-func checkNonRequired('member', data[key], validations.children, (parent ? parent + '.' : '') + toLowerFirst(attr) + '.' + key) }) @@ -281,37 +284,38 @@ function checkValidations(data, validations, custom, store) { } } -validateFns.notNull = function(parent, key, val, data, errors) { +validateFns.notNull = function (parent, key, val, data, errors) { validate(data != null, 'Member must not be null', data, parent, key, errors) } -validateFns.greaterThanOrEqual = function(parent, key, val, data, errors) { +validateFns.greaterThanOrEqual = function (parent, key, val, data, errors) { validate(data >= val, 'Member must have value greater than or equal to ' + val, data, parent, key, errors) } -validateFns.lessThanOrEqual = function(parent, key, val, data, errors) { +validateFns.lessThanOrEqual = function (parent, key, val, data, errors) { validate(data <= val, 'Member must have value less than or equal to ' + val, data, parent, key, errors) } -validateFns.regex = function(parent, key, pattern, data, errors) { +validateFns.regex = function (parent, key, pattern, data, errors) { validate(RegExp('^' + pattern + '$').test(data), 'Member must satisfy regular expression pattern: ' + pattern, data, parent, key, errors) } -validateFns.lengthGreaterThanOrEqual = function(parent, key, val, data, errors) { +validateFns.lengthGreaterThanOrEqual = function (parent, key, val, data, errors) { var length = (typeof data == 'object' && !Array.isArray(data)) ? Object.keys(data).length : data.length validate(length >= val, 'Member must have length greater than or equal to ' + val, data, parent, key, errors) } -validateFns.lengthLessThanOrEqual = function(parent, key, val, data, errors) { +validateFns.lengthLessThanOrEqual = function (parent, key, val, data, errors) { var length = (typeof data == 'object' && !Array.isArray(data)) ? Object.keys(data).length : data.length validate(length <= val, 'Member must have length less than or equal to ' + val, data, parent, key, errors) } -validateFns.enum = function(parent, key, val, data, errors) { +validateFns.enum = function (parent, key, val, data, errors) { validate(~val.indexOf(data), 'Member must satisfy enum value set: [' + val.join(', ') + ']', data, parent, key, errors) } -validateFns.keys = function(parent, key, val, data, errors) { - Object.keys(data).forEach(function(mapKey) { +validateFns.keys = function (parent, key, val, data, errors) { + Object.keys(data).forEach(function (mapKey) { try { - Object.keys(val).forEach(function(validation) { + Object.keys(val).forEach(function (validation) { validateFns[validation]('', '', val[validation], mapKey, []) }) - } catch (e) { - var msgs = Object.keys(val).map(function(validation) { + } + catch (e) { + var msgs = Object.keys(val).map(function (validation) { if (validation == 'lengthGreaterThanOrEqual') return 'Member must have length greater than or equal to ' + val[validation] if (validation == 'lengthLessThanOrEqual') @@ -323,14 +327,15 @@ validateFns.keys = function(parent, key, val, data, errors) { } }) } -validateFns.values = function(parent, key, val, data, errors) { - Object.keys(data).forEach(function(mapKey) { +validateFns.values = function (parent, key, val, data, errors) { + Object.keys(data).forEach(function (mapKey) { try { - Object.keys(val).forEach(function(validation) { + Object.keys(val).forEach(function (validation) { validateFns[validation]('', '', val[validation], data[mapKey], []) }) - } catch (e) { - var msgs = Object.keys(val).map(function(validation) { + } + catch (e) { + var msgs = Object.keys(val).map(function (validation) { if (validation == 'lengthGreaterThanOrEqual') return 'Member must have length greater than or equal to ' + val[validation] if (validation == 'lengthLessThanOrEqual') @@ -341,7 +346,7 @@ validateFns.values = function(parent, key, val, data, errors) { }) } -function validate(predicate, msg, data, parent, key, errors) { +function validate (predicate, msg, data, parent, key, errors) { if (predicate) return var value = valueStr(data) if (value != 'null') value = '\'' + value + '\'' @@ -349,17 +354,17 @@ function validate(predicate, msg, data, parent, key, errors) { errors.push('Value ' + value + ' at \'' + parent + toLowerFirst(key) + '\' failed to satisfy constraint: ' + msg) } -function validateTableName(key, val) { +function validateTableName (key, val) { if (val == null) return null if (val.length < 3 || val.length > 255) return key + ' must be at least 3 characters long and at most 255 characters long' } -function toLowerFirst(str) { +function toLowerFirst (str) { return str[0].toLowerCase() + str.slice(1) } -function validateAttributeValue(value) { +function validateAttributeValue (value) { var types = Object.keys(value), msg, i, attr if (!types.length) return 'Supplied AttributeValue is empty, must contain exactly one of the supported datatypes' @@ -417,14 +422,15 @@ function validateAttributeValue(value) { return 'Supplied AttributeValue has more than one datatypes set, must contain exactly one of the supported datatypes' } -function checkNum(attr, obj) { +function checkNum (attr, obj) { if (!obj[attr]) return 'The parameter cannot be converted to a numeric value' var bigNum try { bigNum = new Big(obj[attr]) - } catch (e) { + } + catch (e) { return 'The parameter cannot be converted to a numeric value: ' + obj[attr] } if (bigNum.e > 125) @@ -437,12 +443,12 @@ function checkNum(attr, obj) { obj[attr] = bigNum.toFixed() } -function valueStr(data) { +function valueStr (data) { return data == null ? 'null' : Array.isArray(data) ? '[' + data.map(valueStr).join(', ') + ']' : typeof data == 'object' ? JSON.stringify(data) : data } -function findDuplicate(arr) { +function findDuplicate (arr) { if (!arr) return null var vals = Object.create(null) for (var i = 0; i < arr.length; i++) { @@ -451,7 +457,7 @@ function findDuplicate(arr) { } } -function validateAttributeConditions(data) { +function validateAttributeConditions (data) { for (var key in data.Expected) { var condition = data.Expected[key] @@ -475,27 +481,27 @@ function validateAttributeConditions(data) { var validAttrCount = false switch (condition.ComparisonOperator) { - case 'EQ': - case 'NE': - case 'LE': - case 'LT': - case 'GE': - case 'GT': - case 'CONTAINS': - case 'NOT_CONTAINS': - case 'BEGINS_WITH': - if (values === 1) validAttrCount = true - break - case 'NOT_NULL': - case 'NULL': - if (values === 0) validAttrCount = true - break - case 'IN': - if (values > 0) validAttrCount = true - break - case 'BETWEEN': - if (values === 2) validAttrCount = true - break + case 'EQ': + case 'NE': + case 'LE': + case 'LT': + case 'GE': + case 'GT': + case 'CONTAINS': + case 'NOT_CONTAINS': + case 'BEGINS_WITH': + if (values === 1) validAttrCount = true + break + case 'NOT_NULL': + case 'NULL': + if (values === 0) validAttrCount = true + break + case 'IN': + if (values > 0) validAttrCount = true + break + case 'BETWEEN': + if (values === 2) validAttrCount = true + break } if (!validAttrCount) return 'One or more parameter values were invalid: ' + @@ -503,17 +509,19 @@ function validateAttributeConditions(data) { if (condition.AttributeValueList && condition.AttributeValueList.length) { var type = Object.keys(condition.AttributeValueList[0])[0] - if (condition.AttributeValueList.some(function(attr) { return Object.keys(attr)[0] != type })) { + if (condition.AttributeValueList.some(function (attr) { return Object.keys(attr)[0] != type })) { return 'One or more parameter values were invalid: AttributeValues inside AttributeValueList must be of same type' } if (condition.ComparisonOperator == 'BETWEEN' && db.compare('GT', condition.AttributeValueList[0], condition.AttributeValueList[1])) { return 'The BETWEEN condition was provided a range where the lower bound is greater than the upper bound' } } - } else if ('AttributeValueList' in condition) { + } + else if ('AttributeValueList' in condition) { return 'One or more parameter values were invalid: ' + 'AttributeValueList can only be used with a ComparisonOperator for Attribute: ' + key - } else { + } + else { var exists = condition.Exists == null || condition.Exists if (exists && condition.Value == null) return 'One or more parameter values were invalid: ' + @@ -531,7 +539,7 @@ function validateAttributeConditions(data) { } } -function validateConditions(conditions) { +function validateConditions (conditions) { var lengths = { NULL: 0, NOT_NULL: 0, @@ -544,21 +552,21 @@ function validateConditions(conditions) { CONTAINS: 1, NOT_CONTAINS: 1, BEGINS_WITH: 1, - IN: [1], + IN: [ 1 ], BETWEEN: 2, } var types = { - EQ: ['S', 'N', 'B', 'SS', 'NS', 'BS'], - NE: ['S', 'N', 'B', 'SS', 'NS', 'BS'], - LE: ['S', 'N', 'B'], - LT: ['S', 'N', 'B'], - GE: ['S', 'N', 'B'], - GT: ['S', 'N', 'B'], - CONTAINS: ['S', 'N', 'B'], - NOT_CONTAINS: ['S', 'N', 'B'], - BEGINS_WITH: ['S', 'B'], - IN: ['S', 'N', 'B'], - BETWEEN: ['S', 'N', 'B'], + EQ: [ 'S', 'N', 'B', 'SS', 'NS', 'BS' ], + NE: [ 'S', 'N', 'B', 'SS', 'NS', 'BS' ], + LE: [ 'S', 'N', 'B' ], + LT: [ 'S', 'N', 'B' ], + GE: [ 'S', 'N', 'B' ], + GT: [ 'S', 'N', 'B' ], + CONTAINS: [ 'S', 'N', 'B' ], + NOT_CONTAINS: [ 'S', 'N', 'B' ], + BEGINS_WITH: [ 'S', 'B' ], + IN: [ 'S', 'N', 'B' ], + BETWEEN: [ 'S', 'N', 'B' ], } for (var key in conditions) { var comparisonOperator = conditions[key].ComparisonOperator @@ -575,7 +583,7 @@ function validateConditions(conditions) { if (attrValList.length) { var type = Object.keys(attrValList[0])[0] - if (attrValList.some(function(attr) { return Object.keys(attr)[0] != type })) { + if (attrValList.some(function (attr) { return Object.keys(attr)[0] != type })) { return 'One or more parameter values were invalid: AttributeValues inside AttributeValueList must be of same type' } } @@ -594,15 +602,15 @@ function validateConditions(conditions) { } } -function validateExpressionParams(data, expressions, nonExpressions) { - var exprParams = expressions.filter(function(expr) { return data[expr] != null }) +function validateExpressionParams (data, expressions, nonExpressions) { + var exprParams = expressions.filter(function (expr) { return data[expr] != null }) if (exprParams.length) { // Special case for KeyConditions and KeyConditionExpression if (data.KeyConditions != null && data.KeyConditionExpression == null) { nonExpressions.splice(nonExpressions.indexOf('KeyConditions'), 1) } - var nonExprParams = nonExpressions.filter(function(expr) { return data[expr] != null }) + var nonExprParams = nonExpressions.filter(function (expr) { return data[expr] != null }) if (nonExprParams.length) { return 'Can not use both expression and non-expression parameters in the same request: ' + 'Non-expression parameters: {' + nonExprParams.join(', ') + '} ' + @@ -614,15 +622,15 @@ function validateExpressionParams(data, expressions, nonExpressions) { return 'ExpressionAttributeNames can only be specified when using expressions' } - var valExprs = expressions.filter(function(expr) { return expr != 'ProjectionExpression' }) + var valExprs = expressions.filter(function (expr) { return expr != 'ProjectionExpression' }) if (valExprs.length && data.ExpressionAttributeValues != null && - valExprs.every(function(expr) { return data[expr] == null })) { + valExprs.every(function (expr) { return data[expr] == null })) { return 'ExpressionAttributeValues can only be specified when using expressions: ' + valExprs.join(' and ') + ' ' + (valExprs.length > 1 ? 'are' : 'is') + ' null' } } -function validateExpressions(data) { +function validateExpressions (data) { var key, msg, result, context = { attrNames: data.ExpressionAttributeNames, attrVals: data.ExpressionAttributeValues, @@ -711,28 +719,29 @@ function validateExpressions(data) { } } -function parse(str, parser, context) { +function parse (str, parser, context) { if (str == '') return 'The expression can not be empty;' context.isReserved = isReserved context.compare = db.compare try { - return parser.parse(str, {context: context}) - } catch (e) { + return parser.parse(str, { context: context }) + } + catch (e) { return e.name == 'SyntaxError' ? 'Syntax error; ' + e.message : e.message } } -function convertKeyCondition(expression) { +function convertKeyCondition (expression) { var keyConds = Object.create(null) return checkExpr(expression, keyConds) || keyConds } -function checkExpr(expr, keyConds) { +function checkExpr (expr, keyConds) { if (!expr || !expr.type) return - if (~['or', 'not', 'in', '<>'].indexOf(expr.type)) { + if (~[ 'or', 'not', 'in', '<>' ].indexOf(expr.type)) { return 'Invalid operator used in KeyConditionExpression: ' + expr.type.toUpperCase() } - if (expr.type == 'function' && ~['attribute_exists', 'attribute_not_exists', 'attribute_type', 'contains'].indexOf(expr.name)) { + if (expr.type == 'function' && ~[ 'attribute_exists', 'attribute_not_exists', 'attribute_type', 'contains' ].indexOf(expr.name)) { return 'Invalid operator used in KeyConditionExpression: ' + expr.name } if (expr.type == 'function' && expr.name == 'size') { @@ -756,7 +765,8 @@ function checkExpr(expr, keyConds) { } attrName = expr.args[i][0] attrIx = i - } else if (expr.args[i].type) { + } + else if (expr.args[i].type) { var result = checkExpr(expr.args[i], keyConds) if (result) return result } @@ -1371,6 +1381,6 @@ var RESERVED_WORDS = { ZONE: true, } -function isReserved(name) { +function isReserved (name) { return RESERVED_WORDS[name.toUpperCase()] != null } diff --git a/validations/listTagsOfResource.js b/validations/listTagsOfResource.js index 6748c2e..72c4644 100644 --- a/validations/listTagsOfResource.js +++ b/validations/listTagsOfResource.js @@ -4,7 +4,7 @@ exports.types = { }, } -exports.custom = function(data, store) { +exports.custom = function (data, store) { if (data.ResourceArn == null) { return 'Invalid TableArn' } diff --git a/validations/putItem.js b/validations/putItem.js index 6967fd9..d0b64a1 100644 --- a/validations/putItem.js +++ b/validations/putItem.js @@ -1,10 +1,10 @@ var validations = require('./index'), - db = require('../db') + db = require('../db') exports.types = { ReturnConsumedCapacity: { type: 'String', - enum: ['INDEXES', 'TOTAL', 'NONE'], + enum: [ 'INDEXES', 'TOTAL', 'NONE' ], }, TableName: { type: 'String', @@ -20,7 +20,7 @@ exports.types = { }, ConditionalOperator: { type: 'String', - enum: ['OR', 'AND'], + enum: [ 'OR', 'AND' ], }, Expected: { type: 'Map', @@ -33,7 +33,7 @@ exports.types = { }, ComparisonOperator: { type: 'String', - enum: ['IN', 'NULL', 'BETWEEN', 'LT', 'NOT_CONTAINS', 'EQ', 'GT', 'NOT_NULL', 'NE', 'LE', 'BEGINS_WITH', 'GE', 'CONTAINS'], + enum: [ 'IN', 'NULL', 'BETWEEN', 'LT', 'NOT_CONTAINS', 'EQ', 'GT', 'NOT_NULL', 'NE', 'LE', 'BEGINS_WITH', 'GE', 'CONTAINS' ], }, Exists: 'Boolean', Value: 'AttrStruct', @@ -42,11 +42,11 @@ exports.types = { }, ReturnValues: { type: 'String', - enum: ['ALL_NEW', 'UPDATED_OLD', 'ALL_OLD', 'NONE', 'UPDATED_NEW'], + enum: [ 'ALL_NEW', 'UPDATED_OLD', 'ALL_OLD', 'NONE', 'UPDATED_NEW' ], }, ReturnItemCollectionMetrics: { type: 'String', - enum: ['SIZE', 'NONE'], + enum: [ 'SIZE', 'NONE' ], }, ConditionExpression: { type: 'String', @@ -61,9 +61,9 @@ exports.types = { }, } -exports.custom = function(data, store) { +exports.custom = function (data, store) { - var msg = validations.validateExpressionParams(data, ['ConditionExpression'], ['Expected']) + var msg = validations.validateExpressionParams(data, [ 'ConditionExpression' ], [ 'Expected' ]) if (msg) return msg for (var key in data.Item) { diff --git a/validations/query.js b/validations/query.js index 4a8fd77..4045c78 100644 --- a/validations/query.js +++ b/validations/query.js @@ -3,7 +3,7 @@ var validations = require('./index') exports.types = { Select: { type: 'String', - enum: ['SPECIFIC_ATTRIBUTES', 'COUNT', 'ALL_ATTRIBUTES', 'ALL_PROJECTED_ATTRIBUTES'], + enum: [ 'SPECIFIC_ATTRIBUTES', 'COUNT', 'ALL_ATTRIBUTES', 'ALL_PROJECTED_ATTRIBUTES' ], }, IndexName: { type: 'String', @@ -13,7 +13,7 @@ exports.types = { }, ReturnConsumedCapacity: { type: 'String', - enum: ['INDEXES', 'TOTAL', 'NONE'], + enum: [ 'INDEXES', 'TOTAL', 'NONE' ], }, QueryFilter: { type: 'Map', @@ -27,7 +27,7 @@ exports.types = { ComparisonOperator: { type: 'String', notNull: true, - enum: ['IN', 'NULL', 'BETWEEN', 'LT', 'NOT_CONTAINS', 'EQ', 'GT', 'NOT_NULL', 'NE', 'LE', 'BEGINS_WITH', 'GE', 'CONTAINS'], + enum: [ 'IN', 'NULL', 'BETWEEN', 'LT', 'NOT_CONTAINS', 'EQ', 'GT', 'NOT_NULL', 'NE', 'LE', 'BEGINS_WITH', 'GE', 'CONTAINS' ], }, }, }, @@ -41,7 +41,7 @@ exports.types = { }, ConditionalOperator: { type: 'String', - enum: ['OR', 'AND'], + enum: [ 'OR', 'AND' ], }, AttributesToGet: { type: 'List', @@ -61,7 +61,7 @@ exports.types = { ComparisonOperator: { type: 'String', notNull: true, - enum: ['IN', 'NULL', 'BETWEEN', 'LT', 'NOT_CONTAINS', 'EQ', 'GT', 'NOT_NULL', 'NE', 'LE', 'BEGINS_WITH', 'GE', 'CONTAINS'], + enum: [ 'IN', 'NULL', 'BETWEEN', 'LT', 'NOT_CONTAINS', 'EQ', 'GT', 'NOT_NULL', 'NE', 'LE', 'BEGINS_WITH', 'GE', 'CONTAINS' ], }, AttributeValueList: { type: 'List', @@ -95,11 +95,11 @@ exports.types = { }, } -exports.custom = function(data) { +exports.custom = function (data) { var msg = validations.validateExpressionParams(data, - ['ProjectionExpression', 'FilterExpression', 'KeyConditionExpression'], - ['AttributesToGet', 'QueryFilter', 'ConditionalOperator', 'KeyConditions']) + [ 'ProjectionExpression', 'FilterExpression', 'KeyConditionExpression' ], + [ 'AttributesToGet', 'QueryFilter', 'ConditionalOperator', 'KeyConditions' ]) if (msg) return msg var key diff --git a/validations/scan.js b/validations/scan.js index b7cd562..48ce684 100644 --- a/validations/scan.js +++ b/validations/scan.js @@ -3,7 +3,7 @@ var validations = require('./index') exports.types = { Select: { type: 'String', - enum: ['SPECIFIC_ATTRIBUTES', 'COUNT', 'ALL_ATTRIBUTES', 'ALL_PROJECTED_ATTRIBUTES'], + enum: [ 'SPECIFIC_ATTRIBUTES', 'COUNT', 'ALL_ATTRIBUTES', 'ALL_PROJECTED_ATTRIBUTES' ], }, IndexName: { type: 'String', @@ -17,7 +17,7 @@ exports.types = { }, ReturnConsumedCapacity: { type: 'String', - enum: ['INDEXES', 'TOTAL', 'NONE'], + enum: [ 'INDEXES', 'TOTAL', 'NONE' ], }, TableName: { type: 'String', @@ -28,7 +28,7 @@ exports.types = { }, ConditionalOperator: { type: 'String', - enum: ['OR', 'AND'], + enum: [ 'OR', 'AND' ], }, ScanFilter: { type: 'Map', @@ -42,7 +42,7 @@ exports.types = { ComparisonOperator: { type: 'String', notNull: true, - enum: ['IN', 'NULL', 'BETWEEN', 'LT', 'NOT_CONTAINS', 'EQ', 'GT', 'NOT_NULL', 'NE', 'LE', 'BEGINS_WITH', 'GE', 'CONTAINS'], + enum: [ 'IN', 'NULL', 'BETWEEN', 'LT', 'NOT_CONTAINS', 'EQ', 'GT', 'NOT_NULL', 'NE', 'LE', 'BEGINS_WITH', 'GE', 'CONTAINS' ], }, }, }, @@ -81,11 +81,11 @@ exports.types = { }, } -exports.custom = function(data) { +exports.custom = function (data) { var msg = validations.validateExpressionParams(data, - ['ProjectionExpression', 'FilterExpression'], - ['AttributesToGet', 'ScanFilter', 'ConditionalOperator']) + [ 'ProjectionExpression', 'FilterExpression' ], + [ 'AttributesToGet', 'ScanFilter', 'ConditionalOperator' ]) if (msg) return msg if (data.AttributesToGet) { @@ -117,6 +117,6 @@ exports.custom = function(data) { } } - msg = validations.validateExpressions(data, ['ProjectionExpression', 'FilterExpression']) + msg = validations.validateExpressions(data, [ 'ProjectionExpression', 'FilterExpression' ]) if (msg) return msg } diff --git a/validations/tagResource.js b/validations/tagResource.js index ea6b763..b69bb81 100644 --- a/validations/tagResource.js +++ b/validations/tagResource.js @@ -14,7 +14,7 @@ exports.types = { }, } -exports.custom = function(data, store) { +exports.custom = function (data, store) { if (data.ResourceArn == null) { return 'Invalid TableArn' } diff --git a/validations/untagResource.js b/validations/untagResource.js index 40995a1..7602ac1 100644 --- a/validations/untagResource.js +++ b/validations/untagResource.js @@ -8,7 +8,7 @@ exports.types = { }, } -exports.custom = function(data, store) { +exports.custom = function (data, store) { if (data.ResourceArn == null) { return 'Invalid TableArn' } diff --git a/validations/updateItem.js b/validations/updateItem.js index 3cde15a..bcf9bdc 100644 --- a/validations/updateItem.js +++ b/validations/updateItem.js @@ -3,7 +3,7 @@ var validations = require('./index') exports.types = { ReturnConsumedCapacity: { type: 'String', - enum: ['INDEXES', 'TOTAL', 'NONE'], + enum: [ 'INDEXES', 'TOTAL', 'NONE' ], }, TableName: { type: 'String', @@ -14,11 +14,11 @@ exports.types = { }, ReturnItemCollectionMetrics: { type: 'String', - enum: ['SIZE', 'NONE'], + enum: [ 'SIZE', 'NONE' ], }, ReturnValues: { type: 'String', - enum: ['ALL_NEW', 'UPDATED_OLD', 'ALL_OLD', 'NONE', 'UPDATED_NEW'], + enum: [ 'ALL_NEW', 'UPDATED_OLD', 'ALL_OLD', 'NONE', 'UPDATED_NEW' ], }, Key: { type: 'Map', @@ -27,7 +27,7 @@ exports.types = { }, ConditionalOperator: { type: 'String', - enum: ['OR', 'AND'], + enum: [ 'OR', 'AND' ], }, Expected: { type: 'Map', @@ -40,7 +40,7 @@ exports.types = { }, ComparisonOperator: { type: 'String', - enum: ['IN', 'NULL', 'BETWEEN', 'LT', 'NOT_CONTAINS', 'EQ', 'GT', 'NOT_NULL', 'NE', 'LE', 'BEGINS_WITH', 'GE', 'CONTAINS'], + enum: [ 'IN', 'NULL', 'BETWEEN', 'LT', 'NOT_CONTAINS', 'EQ', 'GT', 'NOT_NULL', 'NE', 'LE', 'BEGINS_WITH', 'GE', 'CONTAINS' ], }, Exists: 'Boolean', Value: 'AttrStruct', @@ -73,11 +73,11 @@ exports.types = { }, } -exports.custom = function(data) { +exports.custom = function (data) { var msg = validations.validateExpressionParams(data, - ['UpdateExpression', 'ConditionExpression'], - ['AttributeUpdates', 'Expected']) + [ 'UpdateExpression', 'ConditionExpression' ], + [ 'AttributeUpdates', 'Expected' ]) if (msg) return msg for (var key in data.Key) { diff --git a/validations/updateTable.js b/validations/updateTable.js index f8a647a..b396bfe 100644 --- a/validations/updateTable.js +++ b/validations/updateTable.js @@ -22,7 +22,7 @@ exports.types = { }, BillingMode: { type: 'String', - enum: ['PROVISIONED', 'PAY_PER_REQUEST'], + enum: [ 'PROVISIONED', 'PAY_PER_REQUEST' ], }, GlobalSecondaryIndexUpdates: { type: 'List', @@ -66,7 +66,7 @@ exports.types = { children: { ProjectionType: { type: 'String', - enum: ['ALL', 'INCLUDE', 'KEYS_ONLY'], + enum: [ 'ALL', 'INCLUDE', 'KEYS_ONLY' ], }, NonKeyAttributes: { type: 'List', @@ -136,7 +136,7 @@ exports.types = { }, } -exports.custom = function(data) { +exports.custom = function (data) { if (!data.ProvisionedThroughput && !data.BillingMode && !data.UpdateStreamEnabled && (!data.GlobalSecondaryIndexUpdates || !data.GlobalSecondaryIndexUpdates.length) && !data.SSESpecification) {