1+ // tslint:disable:no-non-null-assertion
12import * as DynamoDB from 'aws-sdk/clients/dynamodb'
23import { of } from 'rxjs'
34import { 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'
77import { DynamoRx } from '../dynamo-rx'
88import { BatchGetRequest } from './batch-get.request'
99
1010describe ( 'batch get' , ( ) => {
1111 let request : BatchGetRequest
1212
13-
1413 describe ( 'params' , ( ) => {
1514
1615 beforeEach ( ( ) => request = new BatchGetRequest ( ) )
@@ -21,39 +20,150 @@ describe('batch get', () => {
2120 } )
2221
2322 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 ] )
2528 const params = request . params
2629 expect ( params . RequestItems ) . toBeDefined ( )
2730 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+ } ] )
2936 } )
3037 } )
3138
32-
3339 describe ( 'forModel' , ( ) => {
3440 beforeEach ( ( ) => request = new BatchGetRequest ( ) )
3541
3642 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 ( )
3955 } )
4056
4157 it ( 'should throw when providing null value ' , ( ) => {
4258 expect ( ( ) => request . forModel ( SimpleWithPartitionKeyModel , [ < any > null ] ) ) . toThrow ( )
4359 } )
4460
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 ( )
4768 } )
4869
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 ( )
5384 } )
5485
5586 } )
5687
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+ } )
57167
58168 describe ( 'should map the result items' , ( ) => {
59169 let batchGetItemsSpy : jasmine . Spy
@@ -74,7 +184,7 @@ describe('batch get', () => {
74184 const dynamoRx : DynamoRx = < any > { batchGetItems : batchGetItemsSpy }
75185 request = new BatchGetRequest ( )
76186 Object . assign ( request , { dynamoRx } )
77- request . forModel ( SimpleWithPartitionKeyModel , [ 'idVal' ] )
187+ request . forModel ( SimpleWithPartitionKeyModel , [ { id : 'idVal' } ] )
78188 } )
79189
80190 it ( 'exec' , async ( ) => {
@@ -93,5 +203,4 @@ describe('batch get', () => {
93203 } )
94204
95205 } )
96-
97206} )
0 commit comments