1
1
import { DeleteCommand , DynamoDBDocument , GetCommand , PutCommand , UpdateCommand } from '@aws-sdk/lib-dynamodb' ;
2
2
import { mockClient } from 'aws-sdk-client-mock' ;
3
3
import 'aws-sdk-client-mock-jest' ;
4
- import { IdempotencyItemNotFoundError } from '../../../src/Exceptions' ;
4
+ import { IdempotencyItemAlreadyExistsError , IdempotencyItemNotFoundError } from '../../../src/Exceptions' ;
5
5
import { DynamoDBPersistenceLayer } from '../../../src/persistence/DynamoDbPersistenceLayer' ;
6
6
import { IdempotencyRecord } from '../../../src/persistence/IdempotencyRecord' ;
7
7
import { IdempotencyRecordStatus } from '../../../src/types/IdempotencyRecordStatus' ;
@@ -36,7 +36,7 @@ describe('Class: DynamoDbPersistenceLayer', () => {
36
36
} ) ;
37
37
38
38
describe ( 'Method: _putRecord' , ( ) => {
39
- test ( 'when called with a record that succeeds condition, it puts record in dynamo table' , ( ) => {
39
+ test ( 'when called with a record that succeeds condition, it puts record in dynamo table' , async ( ) => {
40
40
// Prepare
41
41
const tableName = 'tableName' ;
42
42
const persistenceLayer = new TestDynamoPersistenceLayer ( tableName ) ;
@@ -53,7 +53,7 @@ describe('Class: DynamoDbPersistenceLayer', () => {
53
53
const dynamoClient = mockClient ( DynamoDBDocument ) . on ( PutCommand ) . resolves ( { } ) ;
54
54
55
55
// Act
56
- persistenceLayer . _putRecord ( record ) ;
56
+ await persistenceLayer . _putRecord ( record ) ;
57
57
58
58
// Assess
59
59
expect ( dynamoClient ) . toReceiveCommandWith ( PutCommand , {
@@ -64,6 +64,76 @@ describe('Class: DynamoDbPersistenceLayer', () => {
64
64
ConditionExpression : 'attribute_not_exists(#id) OR #expiry < :now OR NOT #status = :inprogress'
65
65
} ) ;
66
66
} ) ;
67
+
68
+ test ( 'when called with a record that fails condition, it throws IdempotencyItemAlreadyExistsError' , async ( ) => {
69
+ // Prepare
70
+ const tableName = 'tableName' ;
71
+ const persistenceLayer = new TestDynamoPersistenceLayer ( tableName ) ;
72
+
73
+ const key = 'key' ;
74
+ const status = IdempotencyRecordStatus . EXPIRED ;
75
+ const expiryTimestamp = 0 ;
76
+ const inProgressExpiryTimestamp = 0 ;
77
+ const record = new IdempotencyRecord ( key , status , expiryTimestamp , inProgressExpiryTimestamp , undefined , undefined ) ;
78
+
79
+ const currentDate = 1 ;
80
+ jest . spyOn ( Date , 'now' ) . mockReturnValue ( currentDate ) ;
81
+
82
+ const dynamoClient = mockClient ( DynamoDBDocument ) . on ( PutCommand ) . rejects ( { name : 'ConditionalCheckFailedException' } ) ;
83
+
84
+ // Act
85
+ let error : unknown ;
86
+ try {
87
+ await persistenceLayer . _putRecord ( record ) ;
88
+ } catch ( e ) {
89
+ error = e ;
90
+ }
91
+
92
+ // Assess
93
+ expect ( dynamoClient ) . toReceiveCommandWith ( PutCommand , {
94
+ TableName : tableName ,
95
+ Item : { 'id' : key , 'expiration' : expiryTimestamp , status : status } ,
96
+ ExpressionAttributeNames : { '#id' : 'id' , '#expiry' : 'expiration' , '#status' : 'status' } ,
97
+ ExpressionAttributeValues : { ':now' : currentDate , ':inprogress' : IdempotencyRecordStatus . INPROGRESS } ,
98
+ ConditionExpression : 'attribute_not_exists(#id) OR #expiry < :now OR NOT #status = :inprogress'
99
+ } ) ;
100
+ expect ( error ) . toBeInstanceOf ( IdempotencyItemAlreadyExistsError ) ;
101
+ } ) ;
102
+
103
+ test ( 'when encountering an unknown error, it throws the causing error' , async ( ) => {
104
+ // Prepare
105
+ const tableName = 'tableName' ;
106
+ const persistenceLayer = new TestDynamoPersistenceLayer ( tableName ) ;
107
+
108
+ const key = 'key' ;
109
+ const status = IdempotencyRecordStatus . EXPIRED ;
110
+ const expiryTimestamp = 0 ;
111
+ const inProgressExpiryTimestamp = 0 ;
112
+ const record = new IdempotencyRecord ( key , status , expiryTimestamp , inProgressExpiryTimestamp , undefined , undefined ) ;
113
+
114
+ const currentDate = 1 ;
115
+ jest . spyOn ( Date , 'now' ) . mockReturnValue ( currentDate ) ;
116
+
117
+ const dynamoClient = mockClient ( DynamoDBDocument ) . on ( PutCommand ) . rejects ( new Error ( ) ) ;
118
+
119
+ // Act
120
+ let error : unknown ;
121
+ try {
122
+ await persistenceLayer . _putRecord ( record ) ;
123
+ } catch ( e ) {
124
+ error = e ;
125
+ }
126
+
127
+ // Assess
128
+ expect ( dynamoClient ) . toReceiveCommandWith ( PutCommand , {
129
+ TableName : tableName ,
130
+ Item : { 'id' : key , 'expiration' : expiryTimestamp , status : status } ,
131
+ ExpressionAttributeNames : { '#id' : 'id' , '#expiry' : 'expiration' , '#status' : 'status' } ,
132
+ ExpressionAttributeValues : { ':now' : currentDate , ':inprogress' : IdempotencyRecordStatus . INPROGRESS } ,
133
+ ConditionExpression : 'attribute_not_exists(#id) OR #expiry < :now OR NOT #status = :inprogress'
134
+ } ) ;
135
+ expect ( error ) . toBe ( error ) ;
136
+ } ) ;
67
137
} ) ;
68
138
69
139
describe ( 'Method: _getRecord' , ( ) => {
0 commit comments