Skip to content

Commit 0cb7b12

Browse files
committed
test: add multiple-integration tests for dynamodb proxy
1 parent 0b79646 commit 0cb7b12

File tree

6 files changed

+260
-18
lines changed

6 files changed

+260
-18
lines changed
Lines changed: 68 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,68 @@
1+
service: multiple-dynamodb-proxy
2+
3+
provider:
4+
name: aws
5+
runtime: nodejs10.x
6+
7+
plugins:
8+
localPath: './../../../../../../'
9+
modules:
10+
- serverless-apigateway-service-proxy
11+
12+
custom:
13+
apiGatewayServiceProxies:
14+
- dynamodb:
15+
path: /dynamodb/{id}
16+
method: put
17+
tableName:
18+
Ref: MyMuTestTable
19+
hashKey:
20+
pathParam: id
21+
attributeType: S
22+
cors: true
23+
- dynamodb:
24+
path: /dynamodb
25+
method: get
26+
tableName:
27+
Ref: MyMuTestTable
28+
hashKey:
29+
queryStringParam: id
30+
attributeType: S
31+
cors: true
32+
- dynamodb:
33+
path: /dynamodb/{id}
34+
method: post
35+
action: UpdateItem
36+
tableName:
37+
Ref: MyMuTestTable
38+
hashKey:
39+
pathParam: id
40+
attributeType: S
41+
cors: true
42+
- dynamodb:
43+
path: /dynamodb/{id}
44+
method: delete
45+
tableName:
46+
Ref: MyMuTestTable
47+
hashKey:
48+
pathParam: id
49+
attributeType: S
50+
cors: true
51+
52+
resources:
53+
Resources:
54+
MyMuTestTable:
55+
Type: AWS::DynamoDB::Table
56+
Properties:
57+
TableName: MyMuTestTable
58+
AttributeDefinitions:
59+
-
60+
AttributeName: id
61+
AttributeType: S
62+
KeySchema:
63+
-
64+
AttributeName: id
65+
KeyType: HASH
66+
ProvisionedThroughput:
67+
ReadCapacityUnits: 1
68+
WriteCapacityUnits: 1
Lines changed: 146 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,146 @@
1+
'use strict'
2+
3+
const expect = require('chai').expect
4+
const fetch = require('node-fetch')
5+
const _ = require('lodash')
6+
const {
7+
deployWithRandomStage,
8+
removeService,
9+
getDynamodbItem,
10+
putDynamodbItem,
11+
cleanUpDynamodbItems
12+
} = require('../../../utils')
13+
14+
describe('Multiple Dynamodb Proxies Integration Test', () => {
15+
let endpoint
16+
let stage
17+
const tableName = 'MyMuTestTable'
18+
const hashKeyAttribute = 'id'
19+
const hashKey = { S: 'myid' }
20+
const config = '__tests__/integration/dynamodb/multiple-integrations/service/serverless.yml'
21+
22+
beforeAll(async () => {
23+
const result = await deployWithRandomStage(config)
24+
25+
stage = result.stage
26+
endpoint = result.endpoint
27+
})
28+
29+
afterAll(async () => {
30+
removeService(stage, config)
31+
})
32+
33+
afterEach(async () => {
34+
await cleanUpDynamodbItems(tableName, hashKeyAttribute)
35+
})
36+
37+
it('should get correct response from dynamodb PutItem action endpoint', async () => {
38+
const putEndpoint = `${endpoint}/dynamodb/${hashKey.S}`
39+
40+
const putResponse = await fetch(putEndpoint, {
41+
method: 'PUT',
42+
headers: { 'Content-Type': 'application/json' },
43+
body: JSON.stringify({ message: { S: 'test' } })
44+
})
45+
expect(putResponse.headers.get('access-control-allow-origin')).to.deep.equal('*')
46+
expect(putResponse.status).to.be.equal(200)
47+
48+
const item = await getDynamodbItem(tableName, hashKeyAttribute, hashKey)
49+
expect(item).to.be.deep.equal({
50+
Item: {
51+
[hashKeyAttribute]: hashKey,
52+
message: { S: 'test' }
53+
}
54+
})
55+
})
56+
57+
it('should get correct response from dynamodb GetItem action endpoint', async () => {
58+
await putDynamodbItem(
59+
tableName,
60+
_.merge({}, { [hashKeyAttribute]: hashKey }, { message: { S: 'testtest' } })
61+
)
62+
const getEndpoint = `${endpoint}/dynamodb?id=${hashKey.S}`
63+
64+
const getResponse = await fetch(getEndpoint, {
65+
method: 'GET',
66+
headers: { 'Content-Type': 'application/json' }
67+
})
68+
expect(getResponse.headers.get('access-control-allow-origin')).to.deep.equal('*')
69+
expect(getResponse.status).to.be.equal(200)
70+
71+
const item = await getResponse.json()
72+
expect(item).to.be.deep.equal({
73+
id: hashKey.S,
74+
message: 'testtest'
75+
})
76+
})
77+
78+
it('should get correct response from dynamodb UpdateItem action endpoint', async () => {
79+
await putDynamodbItem(
80+
tableName,
81+
_.merge({}, { [hashKeyAttribute]: hashKey }, { message: { S: 'testtesttest' } })
82+
)
83+
const updateEndpoint = `${endpoint}/dynamodb/${hashKey.S}`
84+
85+
const updateResponse1 = await fetch(updateEndpoint, {
86+
method: 'POST',
87+
headers: { 'Content-Type': 'application/json' },
88+
body: JSON.stringify({
89+
UpdateExpression: 'ADD QuantityOnHand :q',
90+
ExpressionAttributeValues: { ':q': { N: '5' } }
91+
})
92+
})
93+
expect(updateResponse1.headers.get('access-control-allow-origin')).to.deep.equal('*')
94+
expect(updateResponse1.status).to.be.equal(200)
95+
96+
const item1 = await getDynamodbItem(tableName, hashKeyAttribute, hashKey)
97+
expect(item1).to.be.deep.equal({
98+
Item: {
99+
[hashKeyAttribute]: hashKey,
100+
QuantityOnHand: { N: '5' },
101+
message: { S: 'testtesttest' }
102+
}
103+
})
104+
105+
const updateResponse2 = await fetch(updateEndpoint, {
106+
method: 'POST',
107+
headers: { 'Content-Type': 'application/json' },
108+
body: JSON.stringify({
109+
UpdateExpression: 'SET #n = :newName',
110+
ExpressionAttributeValues: { ':newName': { S: 'myname' } },
111+
ExpressionAttributeNames: {
112+
'#n': 'name'
113+
}
114+
})
115+
})
116+
expect(updateResponse2.headers.get('access-control-allow-origin')).to.deep.equal('*')
117+
expect(updateResponse2.status).to.be.equal(200)
118+
const item2 = await getDynamodbItem(tableName, hashKeyAttribute, hashKey)
119+
expect(item2).to.be.deep.equal({
120+
Item: {
121+
[hashKeyAttribute]: hashKey,
122+
QuantityOnHand: { N: '5' },
123+
name: { S: 'myname' },
124+
message: { S: 'testtesttest' }
125+
}
126+
})
127+
})
128+
129+
it('should get correct response from dynamodb DeleteItem action endpoint', async () => {
130+
await putDynamodbItem(
131+
tableName,
132+
_.merge({}, { [hashKeyAttribute]: hashKey }, { message: { S: 'test' } })
133+
)
134+
const deleteEndpoint = `${endpoint}/dynamodb/${hashKey.S}`
135+
136+
const deleteResponse = await fetch(deleteEndpoint, {
137+
method: 'DELETE',
138+
headers: { 'Content-Type': 'application/json' }
139+
})
140+
expect(deleteResponse.headers.get('access-control-allow-origin')).to.deep.equal('*')
141+
expect(deleteResponse.status).to.be.equal(200)
142+
143+
const item = await getDynamodbItem(tableName, hashKeyAttribute, hashKey)
144+
expect(item).to.be.empty
145+
})
146+
})

__tests__/integration/dynamodb/single-integration/tests.js

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@ describe('Single dynamodb Proxy Integration Test', () => {
88
let endpoint
99
let stage
1010
const tableName = 'MyTestTable'
11+
const hashKeyAttribute = 'id'
1112
const config = '__tests__/integration/dynamodb/single-integration/service/serverless.yml'
1213

1314
beforeAll(async () => {
@@ -33,7 +34,7 @@ describe('Single dynamodb Proxy Integration Test', () => {
3334
expect(response.status).to.be.equal(200)
3435
const body = await response.json()
3536

36-
const item = await getDynamodbItem(tableName, body.id)
37+
const item = await getDynamodbItem(tableName, hashKeyAttribute, { S: body.id })
3738
expect(item).to.be.deep.equal({
3839
Item: {
3940
id: { S: body.id },

__tests__/utils.js

Lines changed: 32 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -26,19 +26,44 @@ async function getStackOutputs(stackName) {
2626
return _.zipObject(keys, values)
2727
}
2828

29-
async function getDynamodbItem(tableName, hashKey) {
29+
async function getDynamodbItem(tableName, hashKeyAttribute, hashKey) {
3030
return await dynamodb
3131
.getItem({
3232
Key: {
33-
id: {
34-
S: hashKey
35-
}
33+
[hashKeyAttribute]: hashKey
3634
},
3735
TableName: tableName
3836
})
3937
.promise()
4038
}
4139

40+
async function putDynamodbItem(tableName, item) {
41+
await dynamodb
42+
.putItem({
43+
Item: item,
44+
TableName: tableName
45+
})
46+
.promise()
47+
}
48+
49+
async function cleanUpDynamodbItems(tableName, hashKeyAttribute) {
50+
const items = await dynamodb.scan({ TableName: tableName }).promise()
51+
if (items.Count > 0) {
52+
await Promise.all(
53+
items.Items.map(async (item) => {
54+
await dynamodb
55+
.deleteItem({
56+
Key: {
57+
[hashKeyAttribute]: item[hashKeyAttribute]
58+
},
59+
TableName: tableName
60+
})
61+
.promise()
62+
})
63+
)
64+
}
65+
}
66+
4267
async function getS3Object(bucket, key) {
4368
const resp = await s3
4469
.getObject({
@@ -92,5 +117,7 @@ module.exports = {
92117
deployWithRandomStage,
93118
getS3Object,
94119
deleteS3Object,
95-
getDynamodbItem
120+
getDynamodbItem,
121+
putDynamodbItem,
122+
cleanUpDynamodbItems
96123
}

lib/package/dynamodb/compileMethodsToDynamodb.js

Lines changed: 7 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -293,13 +293,13 @@ module.exports = {
293293

294294
requestTemplate += '}'
295295
requestTemplate += `
296-
#set ($body = $util.parseJson($input.body))
297-
,"UpdateExpression":"$body.get('UpdateExpression')"
298-
,"ExpressionAttributeValues":$input.json('$.ExpressionAttributeValues')
299-
#if ($body.ExpressionAttributeNames != "")
300-
,"ExpressionAttributeNames":$input.json('$.ExpressionAttributeNames')
301-
#end
302-
`
296+
#set ($body = $input.path('$'))
297+
,"UpdateExpression":"$body.UpdateExpression"
298+
,"ExpressionAttributeValues":$input.json('$.ExpressionAttributeValues')
299+
#if ($body.ExpressionAttributeNames != "")
300+
,"ExpressionAttributeNames":$input.json('$.ExpressionAttributeNames')
301+
#end
302+
`
303303
requestTemplate += '}'
304304
return {
305305
'Fn::Sub': [`${requestTemplate}`, fuSubValues]

lib/package/dynamodb/compileMethodsToDynamodb.test.js

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -615,7 +615,7 @@ describe('#compileMethodsToDynamodb()', () => {
615615
it('should create corresponding resources when hashkey is given with a path parameter', () => {
616616
const intRequestTemplate = {
617617
'Fn::Sub': [
618-
'{"TableName": "${TableName}","Key":{"${HashKey}": {"${HashAttributeType}": "${HashAttributeValue}"}}\n #set ($body = $util.parseJson($input.body))\n ,"UpdateExpression":"$body.get(\'UpdateExpression\')"\n ,"ExpressionAttributeValues":$input.json(\'$.ExpressionAttributeValues\')\n #if ($body.ExpressionAttributeNames != "")\n ,"ExpressionAttributeNames":$input.json(\'$.ExpressionAttributeNames\')\n #end\n }',
618+
'{"TableName": "${TableName}","Key":{"${HashKey}": {"${HashAttributeType}": "${HashAttributeValue}"}}\n #set ($body = $input.path(\'$\'))\n ,"UpdateExpression":"$body.UpdateExpression"\n ,"ExpressionAttributeValues":$input.json(\'$.ExpressionAttributeValues\')\n #if ($body.ExpressionAttributeNames != "")\n ,"ExpressionAttributeNames":$input.json(\'$.ExpressionAttributeNames\')\n #end\n }',
619619
{
620620
TableName: {
621621
Ref: 'MyTable'
@@ -640,7 +640,7 @@ describe('#compileMethodsToDynamodb()', () => {
640640
it('should create corresponding resources when hashkey is given with a querystring', () => {
641641
const intRequestTemplate = {
642642
'Fn::Sub': [
643-
'{"TableName": "${TableName}","Key":{"${HashKey}": {"${HashAttributeType}": "${HashAttributeValue}"}}\n #set ($body = $util.parseJson($input.body))\n ,"UpdateExpression":"$body.get(\'UpdateExpression\')"\n ,"ExpressionAttributeValues":$input.json(\'$.ExpressionAttributeValues\')\n #if ($body.ExpressionAttributeNames != "")\n ,"ExpressionAttributeNames":$input.json(\'$.ExpressionAttributeNames\')\n #end\n }',
643+
'{"TableName": "${TableName}","Key":{"${HashKey}": {"${HashAttributeType}": "${HashAttributeValue}"}}\n #set ($body = $input.path(\'$\'))\n ,"UpdateExpression":"$body.UpdateExpression"\n ,"ExpressionAttributeValues":$input.json(\'$.ExpressionAttributeValues\')\n #if ($body.ExpressionAttributeNames != "")\n ,"ExpressionAttributeNames":$input.json(\'$.ExpressionAttributeNames\')\n #end\n }',
644644
{
645645
TableName: {
646646
Ref: 'MyTable'
@@ -665,7 +665,7 @@ describe('#compileMethodsToDynamodb()', () => {
665665
it('should create corresponding resources when rangekey is given with a path parameter', () => {
666666
const intRequestTemplate = {
667667
'Fn::Sub': [
668-
'{"TableName": "${TableName}","Key":{"${HashKey}": {"${HashAttributeType}": "${HashAttributeValue}"},"${RangeKey}": {"${RangeAttributeType}": "${RangeAttributeValue}"}}\n #set ($body = $util.parseJson($input.body))\n ,"UpdateExpression":"$body.get(\'UpdateExpression\')"\n ,"ExpressionAttributeValues":$input.json(\'$.ExpressionAttributeValues\')\n #if ($body.ExpressionAttributeNames != "")\n ,"ExpressionAttributeNames":$input.json(\'$.ExpressionAttributeNames\')\n #end\n }',
668+
'{"TableName": "${TableName}","Key":{"${HashKey}": {"${HashAttributeType}": "${HashAttributeValue}"},"${RangeKey}": {"${RangeAttributeType}": "${RangeAttributeValue}"}}\n #set ($body = $input.path(\'$\'))\n ,"UpdateExpression":"$body.UpdateExpression"\n ,"ExpressionAttributeValues":$input.json(\'$.ExpressionAttributeValues\')\n #if ($body.ExpressionAttributeNames != "")\n ,"ExpressionAttributeNames":$input.json(\'$.ExpressionAttributeNames\')\n #end\n }',
669669
{
670670
TableName: {
671671
Ref: 'MyTable'
@@ -697,7 +697,7 @@ describe('#compileMethodsToDynamodb()', () => {
697697
it('should create corresponding resources when rangekey is given with a querystring', () => {
698698
const intRequestTemplate = {
699699
'Fn::Sub': [
700-
'{"TableName": "${TableName}","Key":{"${HashKey}": {"${HashAttributeType}": "${HashAttributeValue}"},"${RangeKey}": {"${RangeAttributeType}": "${RangeAttributeValue}"}}\n #set ($body = $util.parseJson($input.body))\n ,"UpdateExpression":"$body.get(\'UpdateExpression\')"\n ,"ExpressionAttributeValues":$input.json(\'$.ExpressionAttributeValues\')\n #if ($body.ExpressionAttributeNames != "")\n ,"ExpressionAttributeNames":$input.json(\'$.ExpressionAttributeNames\')\n #end\n }',
700+
'{"TableName": "${TableName}","Key":{"${HashKey}": {"${HashAttributeType}": "${HashAttributeValue}"},"${RangeKey}": {"${RangeAttributeType}": "${RangeAttributeValue}"}}\n #set ($body = $input.path(\'$\'))\n ,"UpdateExpression":"$body.UpdateExpression"\n ,"ExpressionAttributeValues":$input.json(\'$.ExpressionAttributeValues\')\n #if ($body.ExpressionAttributeNames != "")\n ,"ExpressionAttributeNames":$input.json(\'$.ExpressionAttributeNames\')\n #end\n }',
701701
{
702702
TableName: {
703703
Ref: 'MyTable'
@@ -951,7 +951,7 @@ describe('#compileMethodsToDynamodb()', () => {
951951
it('should create corresponding resources when UpdateItem is given', () => {
952952
const intRequestTemplate = {
953953
'Fn::Sub': [
954-
'{"TableName": "${TableName}","Key":{"${HashKey}": {"${HashAttributeType}": "${HashAttributeValue}"},"${RangeKey}": {"${RangeAttributeType}": "${RangeAttributeValue}"}}\n #set ($body = $util.parseJson($input.body))\n ,"UpdateExpression":"$body.get(\'UpdateExpression\')"\n ,"ExpressionAttributeValues":$input.json(\'$.ExpressionAttributeValues\')\n #if ($body.ExpressionAttributeNames != "")\n ,"ExpressionAttributeNames":$input.json(\'$.ExpressionAttributeNames\')\n #end\n }',
954+
'{"TableName": "${TableName}","Key":{"${HashKey}": {"${HashAttributeType}": "${HashAttributeValue}"},"${RangeKey}": {"${RangeAttributeType}": "${RangeAttributeValue}"}}\n #set ($body = $input.path(\'$\'))\n ,"UpdateExpression":"$body.UpdateExpression"\n ,"ExpressionAttributeValues":$input.json(\'$.ExpressionAttributeValues\')\n #if ($body.ExpressionAttributeNames != "")\n ,"ExpressionAttributeNames":$input.json(\'$.ExpressionAttributeNames\')\n #end\n }',
955955
{
956956
TableName: {
957957
Ref: 'MyTable'

0 commit comments

Comments
 (0)