Skip to content

Commit 834248c

Browse files
committed
feat: integ tests for dynamodb from v2 (#480)
1 parent 2581969 commit 834248c

File tree

8 files changed

+1205
-448
lines changed

8 files changed

+1205
-448
lines changed

features/dynamodb/crc32.feature

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
11
# language: en
2+
"""
23
@dynamodb @dynamodb-2011-12-05 @crc32
34
Feature: CRC32 response validation
45
@@ -16,3 +17,4 @@ Feature: CRC32 response validation
1617
Given my first request is corrupted with CRC checking OFF
1718
Then the request should not be retried
1819
And the request should not fail with a CRC checking error
20+
"""

features/dynamodb/step_definitions/dynamodb.js

Lines changed: 88 additions & 29 deletions
Original file line numberDiff line numberDiff line change
@@ -1,32 +1,99 @@
11
var jmespath = require('jmespath');
2+
var { DynamoDB } = require('../../../clients/node/client-dynamodb-node');
23

3-
module.exports = function() {
4-
this.Before("@dynamodb-2011-12-05", function (next) {
5-
this.service = new this.AWS.DynamoDB({
6-
apiVersion: '2011-12-05',
7-
maxRetries: 2
4+
function waitForTableExists(tableName, callback) {
5+
const db = new DynamoDB({});
6+
const params = {
7+
TableName: tableName
8+
};
9+
10+
// Iterate totalTries times
11+
const totalTries = 25;
12+
let currentTry = 0;
13+
14+
const checkForTableExists = (params, callback) => {
15+
currentTry++;
16+
db.describeTable(params, function(err, data) {
17+
if (err) {
18+
if (currentTry > totalTries) {
19+
callback.fail(err);
20+
}
21+
setTimeout(function() {
22+
checkForTableExists(params, callback);
23+
}, 20000);
24+
} else if (data) {
25+
if (data.Table && data.Table.TableStatus === "ACTIVE") {
26+
callback();
27+
} else {
28+
if (currentTry > totalTries) {
29+
callback.fail(err);
30+
}
31+
setTimeout(function() {
32+
checkForTableExists(params, callback);
33+
}, 20000);
34+
}
35+
}
836
});
9-
next();
10-
});
37+
}
38+
checkForTableExists(params, callback);
39+
};
40+
41+
function waitForTableNotExists(tableName, callback) {
42+
const db = new DynamoDB({});
43+
const params = {
44+
TableName: tableName
45+
};
46+
47+
// Iterate totalTries times
48+
const totalTries = 25;
49+
let currentTry = 0;
1150

12-
this.Before("@dynamodb-2012-08-10", function (next) {
13-
this.service = new this.AWS.DynamoDB({
14-
apiVersion: '2012-08-10',
51+
const checkForTableNotExists = (params, callback) => {
52+
currentTry++;
53+
db.describeTable(params, function(err, data) {
54+
if (err) {
55+
if (currentTry > totalTries) {
56+
callback.fail(err);
57+
}
58+
if (e.name === "ResourceNotFoundException") {
59+
callback();
60+
}
61+
setTimeout(function() {
62+
checkForTableNotExists(params, callback);
63+
}, 20000);
64+
} else if (data) {
65+
if (currentTry > totalTries) {
66+
callback.fail(err);
67+
}
68+
setTimeout(function() {
69+
checkForTableNotExists(params, callback);
70+
}, 20000);
71+
}
72+
});
73+
checkForTableNotExists(params, callback);
74+
}
75+
checkForTableNotExists(params, callback);
76+
};
77+
78+
module.exports = function() {
79+
this.Before("@dynamodb", function (next) {
80+
this.service = new DynamoDB({
1581
maxRetries: 2
1682
});
1783
next();
1884
});
1985

2086
function createTable(world, callback) {
21-
var db = new world.AWS.DynamoDB({
22-
apiVersion: '2011-12-05',
23-
});
87+
var db = new DynamoDB({});
2488

2589
var params = {
2690
TableName: world.tableName,
27-
KeySchema: {
28-
HashKeyElement: { AttributeName: 'id', AttributeType: 'S' }
29-
},
91+
AttributeDefinitions: [
92+
{ AttributeName: 'id', AttributeType: 'S' }
93+
],
94+
KeySchema: [
95+
{ AttributeName: 'id', KeyType: 'HASH' }
96+
],
3097
ProvisionedThroughput: {
3198
ReadCapacityUnits: 10,
3299
WriteCapacityUnits: 5,
@@ -38,15 +105,14 @@ module.exports = function() {
38105
callback.fail(err);
39106
return;
40107
}
41-
params = { TableName: world.tableName };
42-
db.waitFor('tableExists', params, callback);
108+
waitForTableExists(world.tableName, callback);
43109
});
44110
}
45111

46112
this.Given(/^I have a table$/, function(callback) {
47113
var world = this;
48114
this.tableName = 'aws-sdk-js-integration-test';
49-
this.service.listTables(function(err, data) {
115+
this.service.listTables({}, function(err, data) {
50116
for (var i = 0; i < data.TableNames.length; i++) {
51117
if (data.TableNames[i] == world.tableName) {
52118
callback();
@@ -63,13 +129,7 @@ module.exports = function() {
63129
});
64130

65131
this.Then(/^the item with id "([^"]*)" should exist$/, function(key, next) {
66-
var world = this;
67-
var params;
68-
if (this.service.config.apiVersion === '2011-12-05') {
69-
params = {TableName: this.tableName, Key: {HashKeyElement: {S: key}}};
70-
} else if (this.service.config.apiVersion === '2012-08-10') {
71-
params = {TableName: this.tableName, Key: {id: {S: key}}};
72-
}
132+
var params = {TableName: this.tableName, Key: {id: {S: key}}};
73133
this.request(null, 'getItem', params, next);
74134
});
75135

@@ -84,8 +144,7 @@ module.exports = function() {
84144
});
85145

86146
this.Then(/^the table should eventually not exist$/, function(callback) {
87-
var params = {TableName: this.tableName};
88-
this.service.waitFor('tableNotExists', params, callback);
147+
waitForTableNotExists(this.tableName, calback);
89148
});
90149

91150
this.Given(/^my first request is corrupted with CRC checking (ON|OFF)$/, function(toggle, callback) {
@@ -143,7 +202,7 @@ module.exports = function() {
143202
});
144203

145204
this.Given(/^I try to delete an item with key "([^"]*)" from table "([^"]*)"$/, function(key, table, callback) {
146-
var params = {TableName: table, Key: {HashKeyElement: {S: key}}};
205+
var params = {TableName: table, Key: {id: {S: key}}};
147206
this.request(null, 'deleteItem', params, callback, false);
148207
});
149208

features/dynamodb/tables.feature

Lines changed: 3 additions & 27 deletions
Original file line numberDiff line numberDiff line change
@@ -1,31 +1,7 @@
11
# language: en
2-
@dynamodb @dynamodb-2011-12-05 @tables
3-
Feature: DynamoDB Tables (2011-12-05)
42

5-
Scenario: Item CRUD
6-
Given I have a table
7-
When I put the item:
8-
"""
9-
{"id": {"S": "foo"}, "data": {"S": "bår"}}
10-
"""
11-
Then the item with id "foo" should exist
12-
And it should have attribute "data.S" containing "bår"
13-
14-
Scenario: UTF-8 support
15-
Given I try to delete an item with key "føø" from table "table"
16-
Then the error code should be "ResourceNotFoundException"
17-
18-
Scenario: Improper table deletion
19-
Given I try to delete a table with an empty table parameter
20-
Then the error code should be "ValidationException"
21-
And the error message should be:
22-
"""
23-
TableName must be at least 3 characters long and at most 255 characters long
24-
"""
25-
And the status code should be 400
26-
27-
@dynamodb @dynamodb-2012-08-10 @tables
28-
Feature: DynamoDB Tables (2012-08-10)
3+
@dynamodb @tables
4+
Feature: DynamoDB Tables
295

306
Scenario: Item CRUD
317
Given I have a table
@@ -47,7 +23,7 @@ Feature: DynamoDB Tables (2012-08-10)
4723
"""
4824
TableName must be at least 3 characters long and at most 255 characters long
4925
"""
50-
And the status code should be 400
26+
And the error status code should be 400
5127

5228
@recursive
5329
Scenario: Recursive Attributes

features/extra/cleanup.js

Lines changed: 19 additions & 28 deletions
Original file line numberDiff line numberDiff line change
@@ -8,23 +8,25 @@ module.exports = function() {
88
this.registerHandler('AfterFeatures', function(event, callback) {
99
var path = require('path');
1010
var fs = require('fs');
11-
try {
12-
var filePath = path.resolve('integ.buckets.json');
13-
if (!fs.existsSync(filePath)) return callback();
14-
deleteFixtures();
15-
var cache = JSON.parse(fs.readFileSync(filePath));
16-
var buckets = cache.buckets;
17-
if (buckets.length) {
18-
eachSeries(buckets, cleanBucket, function(err) {
19-
fs.unlinkSync(filePath);
20-
callback(err);
21-
});
22-
} else {
23-
callback();
24-
}
25-
} catch (fileErr) {
26-
callback(fileErr);
27-
}
11+
12+
// Reintroduce when writing S3 integration tests
13+
// try {
14+
// var filePath = path.resolve('integ.buckets.json');
15+
// if (!fs.existsSync(filePath)) return callback();
16+
// deleteFixtures();
17+
// var cache = JSON.parse(fs.readFileSync(filePath));
18+
// var buckets = cache.buckets;
19+
// if (buckets.length) {
20+
// eachSeries(buckets, cleanBucket, function(err) {
21+
// fs.unlinkSync(filePath);
22+
// callback(err);
23+
// });
24+
// } else {
25+
// callback();
26+
// }
27+
// } catch (fileErr) {
28+
// callback(fileErr);
29+
// }
2830
});
2931

3032
/**
@@ -99,15 +101,4 @@ module.exports = function() {
99101
}
100102
});
101103
};
102-
103-
var bootSDK = function () {
104-
var path = require('path');
105-
var SDK = require(path.resolve('./'));
106-
SDK.config.update({
107-
region: process.env['CONFIGURED_REGION']
108-
});
109-
return SDK;
110-
};
111-
112-
var AWS = bootSDK();
113104
};

features/extra/hooks.js

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -84,7 +84,7 @@ module.exports = function () {
8484

8585
this.Then(/^the error code should be "([^"]*)"$/, function(code, callback) {
8686
this.assert.ok(this.error, 'Response does not contain an error');
87-
this.assert.equal(this.error.code, code);
87+
this.assert.equal(this.error.name, code);
8888
callback();
8989
});
9090

@@ -101,6 +101,11 @@ module.exports = function () {
101101
callback();
102102
});
103103

104+
this.Then(/^the error status code should be (\d+)$/, function(status, callback) {
105+
this.assert.equal(this.error.$metadata.httpStatusCode, parseInt(status));
106+
callback();
107+
});
108+
104109
this.Then(/^I should get the error:$/, function(table, callback) {
105110
var err = table.hashes()[0];
106111
this.assert.equal(this.error.code, err.code);

features/extra/world.js

Lines changed: 5 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,13 @@
11
var world = require('./helpers');
2+
var fs = require('fs');
23
var path = require('path');
34

4-
world.AWS = require('../../lib/aws');
55
try {
6-
world.AWS.config.loadFromPath(path.resolve('./configuration'));
6+
world.config = JSON.parse(
7+
fs.readFileSync(path.resolve('./configuration'))
8+
);
79
} catch (e) {} finally {
8-
process.env['CONFIGURED_REGION'] = world.AWS.config.region || new world.AWS.Config().region;
10+
process.env['CONFIGURED_REGION'] = 'us-west-2';
911
}
1012

1113
var WorldConstructor = function WorldConstructor(callback) {

package.json

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,8 @@
1616
"pretest": "yarn build:crypto-dependencies && yarn build:smithy-client",
1717
"test": "jest --coverage --passWithNoTests",
1818
"pretest-all": "lerna run pretest",
19-
"test-all": "jest --coverage"
19+
"test-all": "jest --coverage",
20+
"integ-test": "cucumber.js"
2021
},
2122
"repository": {
2223
"type": "git",
@@ -37,10 +38,12 @@
3738
"@commitlint/config-conventional": "^8.1.0",
3839
"@types/jest": "^24.0.12",
3940
"codecov": "^3.4.0",
41+
"cucumber": "0.5.x",
4042
"generate-changelog": "^1.7.1",
4143
"husky": "^3.0.0",
4244
"jest": "^24.7.1",
43-
"lerna": "3.16.4",
45+
"jmespath": "^0.15.0",
46+
"lerna": "3.18.3",
4447
"lint-staged": "^9.0.0",
4548
"prettier": "1.18.2",
4649
"typescript": "^3.7.0",

0 commit comments

Comments
 (0)