1
+ // tslint:disable:no-non-null-assertion
1
2
import * as DynamoDB from 'aws-sdk/clients/dynamodb'
2
3
import { of } from 'rxjs'
3
4
import { getTableName } from '../../../test/helper'
4
- import { SimpleWithCompositePartitionKeyModel , SimpleWithPartitionKeyModel } from '../../../test/models'
5
- import { Organization } from '../../../test/models/organization.model'
6
- import { Attributes } from '../../mapper'
5
+ import { Organization , SimpleWithCompositePartitionKeyModel , SimpleWithPartitionKeyModel } from '../../../test/models'
6
+ import { Attributes , toDb } from '../../mapper'
7
7
import { DynamoRx } from '../dynamo-rx'
8
8
import { BatchGetRequest } from './batch-get.request'
9
9
10
10
describe ( 'batch get' , ( ) => {
11
11
let request : BatchGetRequest
12
12
13
-
14
13
describe ( 'params' , ( ) => {
15
14
16
15
beforeEach ( ( ) => request = new BatchGetRequest ( ) )
@@ -21,39 +20,150 @@ describe('batch get', () => {
21
20
} )
22
21
23
22
it ( 'key' , ( ) => {
24
- request . forModel ( Organization , [ 'idValue' ] )
23
+ const o : Partial < Organization > = {
24
+ id : 'idValue' ,
25
+ createdAtDate : new Date ( ) ,
26
+ }
27
+ request . forModel ( Organization , [ o ] )
25
28
const params = request . params
26
29
expect ( params . RequestItems ) . toBeDefined ( )
27
30
expect ( params . RequestItems . Organization ) . toBeDefined ( )
28
- expect ( params . RequestItems . Organization ) . toEqual ( { Keys : [ { id : { S : 'idValue' } } ] } )
31
+ expect ( params . RequestItems . Organization . Keys ) . toBeDefined ( )
32
+ expect ( params . RequestItems . Organization . Keys ) . toEqual ( [ {
33
+ id : { S : 'idValue' } ,
34
+ createdAtDate : { S : o . createdAtDate ! . toISOString ( ) } ,
35
+ } ] )
29
36
} )
30
37
} )
31
38
32
-
33
39
describe ( 'forModel' , ( ) => {
34
40
beforeEach ( ( ) => request = new BatchGetRequest ( ) )
35
41
36
42
it ( 'should throw when same table is used 2 times' , ( ) => {
37
- request . forModel ( SimpleWithPartitionKeyModel , [ 'idVal' ] )
38
- expect ( ( ) => request . forModel ( SimpleWithPartitionKeyModel , [ 'otherVal' ] ) ) . toThrow ( )
43
+ request . forModel ( SimpleWithPartitionKeyModel , [ { id : 'idVal' } ] )
44
+ expect ( ( ) => request . forModel ( SimpleWithPartitionKeyModel , [ { id : 'otherVal' } ] ) ) . toThrow ( )
45
+ } )
46
+
47
+ it ( 'should throw when sortKey is missing but necessary' , ( ) => {
48
+ expect ( ( ) => request . forModel ( SimpleWithCompositePartitionKeyModel , [ { id : 'idVal' } ] ) )
49
+ } )
50
+
51
+ it ( 'should throw when modelClazz is not @Model decorated' , ( ) => {
52
+ class X { id : string }
53
+
54
+ expect ( ( ) => request . forModel ( X , [ { id : 'ok' } ] ) ) . toThrow ( )
39
55
} )
40
56
41
57
it ( 'should throw when providing null value ' , ( ) => {
42
58
expect ( ( ) => request . forModel ( SimpleWithPartitionKeyModel , [ < any > null ] ) ) . toThrow ( )
43
59
} )
44
60
45
- it ( 'should throw when sortKey is missing' , ( ) => {
46
- expect ( ( ) => request . forModel ( SimpleWithCompositePartitionKeyModel , [ { partitionKey : 'idVal' } ] ) )
61
+ it ( 'should allow ConsistentRead' , ( ) => {
62
+ request . forModel ( SimpleWithPartitionKeyModel , [ { id : 'myId' } ] , true )
63
+ expect ( request . params ) . toBeDefined ( )
64
+ expect ( request . params . RequestItems ) . toBeDefined ( )
65
+ const keysOfTable = request . params . RequestItems [ getTableName ( SimpleWithPartitionKeyModel ) ]
66
+ expect ( keysOfTable ) . toBeDefined ( )
67
+ expect ( keysOfTable . ConsistentRead ) . toBeTruthy ( )
47
68
} )
48
69
49
- it ( 'should throw when partitionKey is neither string nor object' , ( ) => {
50
- expect ( ( ) => request . forModel ( SimpleWithCompositePartitionKeyModel , [ < any > 78 ] ) )
51
- expect ( ( ) => request . forModel ( SimpleWithCompositePartitionKeyModel , [ < any > true ] ) )
52
- expect ( ( ) => request . forModel ( SimpleWithCompositePartitionKeyModel , [ < any > new Date ( ) ] ) )
70
+ it ( 'should throw when more than 100 items are added' , ( ) => {
71
+ const items55 : Array < Partial < SimpleWithPartitionKeyModel > > = new Array ( 55 )
72
+ . map ( ( x , i ) => ( { id : `id-${ i } ` } ) )
73
+ const items60 : Array < Partial < Organization > > = new Array ( 60 )
74
+ . map ( ( x , i ) => ( { id : `id-${ i } ` , createdAtDate : new Date ( ) } ) )
75
+
76
+ // at once
77
+ expect ( ( ) => request . forModel ( SimpleWithPartitionKeyModel , [ ...items55 , ...items55 ] ) ) . toThrow ( )
78
+
79
+ // in two steps
80
+ expect ( ( ) => {
81
+ request . forModel ( SimpleWithPartitionKeyModel , items55 )
82
+ request . forModel ( Organization , items60 )
83
+ } ) . toThrow ( )
53
84
} )
54
85
55
86
} )
56
87
88
+ describe ( 'execNoMap, execFullResponse, exec' , ( ) => {
89
+ const jsItem1 : SimpleWithPartitionKeyModel = { id : 'id-1' , age : 21 }
90
+ const jsItem2 : SimpleWithPartitionKeyModel = { id : 'id-2' , age : 22 }
91
+
92
+ const output1 : DynamoDB . BatchGetItemOutput = {
93
+ Responses : {
94
+ [ getTableName ( SimpleWithPartitionKeyModel ) ] : [ toDb ( jsItem1 , SimpleWithPartitionKeyModel ) ] ,
95
+ } ,
96
+ UnprocessedKeys : {
97
+ [ getTableName ( SimpleWithPartitionKeyModel ) ] : {
98
+ Keys : [ toDb ( jsItem1 , SimpleWithPartitionKeyModel ) ] ,
99
+ } ,
100
+ } ,
101
+ }
102
+ const output2 : DynamoDB . BatchGetItemOutput = {
103
+ Responses : {
104
+ [ getTableName ( SimpleWithPartitionKeyModel ) ] : [ toDb ( jsItem2 , SimpleWithPartitionKeyModel ) ] ,
105
+ } ,
106
+ }
107
+
108
+ let batchGetItemsSpy : jasmine . Spy
109
+ let nextSpyFn : ( ) => { value : number }
110
+
111
+ const generatorMock = ( ) => < any > { next : nextSpyFn }
112
+
113
+ beforeEach ( ( ) => {
114
+ request = new BatchGetRequest ( )
115
+ request . forModel ( SimpleWithPartitionKeyModel , [ jsItem1 , jsItem2 ] )
116
+
117
+ batchGetItemsSpy = jasmine . createSpy ( ) . and . returnValues ( of ( output1 ) , of ( output2 ) )
118
+ const dynamoRx : DynamoRx = < any > { batchGetItems : batchGetItemsSpy }
119
+
120
+ Object . assign ( request , { dynamoRx } )
121
+
122
+ nextSpyFn = jest . fn ( ) . mockImplementation ( ( ) => ( { value : 0 } ) )
123
+ } )
124
+
125
+ it ( '[execNoMap] should backoff and retry when UnprocessedItems are returned' , async ( ) => {
126
+ const result = await request . execNoMap ( generatorMock ) . toPromise ( )
127
+ expect ( nextSpyFn ) . toHaveBeenCalledTimes ( 1 )
128
+ expect ( batchGetItemsSpy ) . toHaveBeenCalledTimes ( 2 )
129
+ expect ( result ) . toBeDefined ( )
130
+ expect ( result . Responses ) . toBeDefined ( )
131
+
132
+ const resultItems = result . Responses ! [ getTableName ( SimpleWithPartitionKeyModel ) ]
133
+ expect ( resultItems ) . toBeDefined ( )
134
+ expect ( resultItems . length ) . toBe ( 2 )
135
+ expect ( resultItems [ 0 ] ) . toEqual ( toDb ( jsItem1 , SimpleWithPartitionKeyModel ) )
136
+ expect ( resultItems [ 1 ] ) . toEqual ( toDb ( jsItem2 , SimpleWithPartitionKeyModel ) )
137
+ } )
138
+
139
+ it ( '[execFullResponse] should backoff and retry when UnprocessedItems are returned' , async ( ) => {
140
+ const result = await request . execFullResponse ( generatorMock ) . toPromise ( )
141
+ expect ( nextSpyFn ) . toHaveBeenCalledTimes ( 1 )
142
+ expect ( batchGetItemsSpy ) . toHaveBeenCalledTimes ( 2 )
143
+ expect ( result ) . toBeDefined ( )
144
+ expect ( result . Responses ) . toBeDefined ( )
145
+
146
+ const resultItems = result . Responses ! [ getTableName ( SimpleWithPartitionKeyModel ) ]
147
+ expect ( resultItems ) . toBeDefined ( )
148
+ expect ( resultItems . length ) . toBe ( 2 )
149
+ expect ( resultItems [ 0 ] ) . toEqual ( jsItem1 )
150
+ expect ( resultItems [ 1 ] ) . toEqual ( jsItem2 )
151
+ } )
152
+
153
+ it ( '[exec] should backoff and retry when UnprocessedItems are returned' , async ( ) => {
154
+ const result = await request . exec ( generatorMock ) . toPromise ( )
155
+ expect ( nextSpyFn ) . toHaveBeenCalledTimes ( 1 )
156
+ expect ( batchGetItemsSpy ) . toHaveBeenCalledTimes ( 2 )
157
+ expect ( result ) . toBeDefined ( )
158
+
159
+ const resultItems = result [ getTableName ( SimpleWithPartitionKeyModel ) ]
160
+ expect ( resultItems ) . toBeDefined ( )
161
+ expect ( resultItems . length ) . toBe ( 2 )
162
+ expect ( resultItems [ 0 ] ) . toEqual ( jsItem1 )
163
+ expect ( resultItems [ 1 ] ) . toEqual ( jsItem2 )
164
+ } )
165
+
166
+ } )
57
167
58
168
describe ( 'should map the result items' , ( ) => {
59
169
let batchGetItemsSpy : jasmine . Spy
@@ -74,7 +184,7 @@ describe('batch get', () => {
74
184
const dynamoRx : DynamoRx = < any > { batchGetItems : batchGetItemsSpy }
75
185
request = new BatchGetRequest ( )
76
186
Object . assign ( request , { dynamoRx } )
77
- request . forModel ( SimpleWithPartitionKeyModel , [ 'idVal' ] )
187
+ request . forModel ( SimpleWithPartitionKeyModel , [ { id : 'idVal' } ] )
78
188
} )
79
189
80
190
it ( 'exec' , async ( ) => {
@@ -93,5 +203,4 @@ describe('batch get', () => {
93
203
} )
94
204
95
205
} )
96
-
97
206
} )
0 commit comments