11import {
22 GetParameterCommand ,
33 GetParameterCommandOutput ,
4+ GetParametersCommand ,
45 PutParameterCommand ,
56 PutParameterCommandOutput ,
67 SSMClient ,
@@ -9,7 +10,7 @@ import 'aws-sdk-client-mock-jest/vitest';
910import { mockClient } from 'aws-sdk-client-mock' ;
1011import nock from 'nock' ;
1112
12- import { getParameter , putParameter , SSM_ADVANCED_TIER_THRESHOLD } from '.' ;
13+ import { getParameter , getParameters , putParameter , SSM_ADVANCED_TIER_THRESHOLD } from '.' ;
1314import { describe , it , expect , beforeEach , vi } from 'vitest' ;
1415
1516const mockSSMClient = mockClient ( SSMClient ) ;
@@ -166,3 +167,90 @@ describe('Test getParameter and putParameter', () => {
166167 } ) ;
167168 } ) ;
168169} ) ;
170+
171+ describe ( 'Test getParameters (batch)' , ( ) => {
172+ beforeEach ( ( ) => {
173+ mockSSMClient . reset ( ) ;
174+ } ) ;
175+
176+ it ( 'returns multiple parameters in a single call' , async ( ) => {
177+ mockSSMClient . on ( GetParametersCommand ) . resolves ( {
178+ Parameters : [
179+ { Name : '/app/param1' , Value : 'value1' } ,
180+ { Name : '/app/param2' , Value : 'value2' } ,
181+ ] ,
182+ } ) ;
183+
184+ const result = await getParameters ( [ '/app/param1' , '/app/param2' ] ) ;
185+
186+ expect ( result ) . toEqual (
187+ new Map ( [
188+ [ '/app/param1' , 'value1' ] ,
189+ [ '/app/param2' , 'value2' ] ,
190+ ] ) ,
191+ ) ;
192+ expect ( mockSSMClient ) . toHaveReceivedCommandWith ( GetParametersCommand , {
193+ Names : [ '/app/param1' , '/app/param2' ] ,
194+ WithDecryption : true ,
195+ } ) ;
196+ } ) ;
197+
198+ it ( 'returns empty map for empty input' , async ( ) => {
199+ const result = await getParameters ( [ ] ) ;
200+
201+ expect ( result ) . toEqual ( new Map ( ) ) ;
202+ expect ( mockSSMClient ) . not . toHaveReceivedCommand ( GetParametersCommand ) ;
203+ } ) ;
204+
205+ it ( 'chunks requests when more than 10 parameters' , async ( ) => {
206+ const names = Array . from ( { length : 12 } , ( _ , i ) => `/app/param${ i } ` ) ;
207+
208+ mockSSMClient
209+ . on ( GetParametersCommand , { Names : names . slice ( 0 , 10 ) , WithDecryption : true } )
210+ . resolves ( {
211+ Parameters : names . slice ( 0 , 10 ) . map ( ( name ) => ( { Name : name , Value : `val-${ name } ` } ) ) ,
212+ } )
213+ . on ( GetParametersCommand , { Names : names . slice ( 10 ) , WithDecryption : true } )
214+ . resolves ( {
215+ Parameters : names . slice ( 10 ) . map ( ( name ) => ( { Name : name , Value : `val-${ name } ` } ) ) ,
216+ } ) ;
217+
218+ const result = await getParameters ( names ) ;
219+
220+ expect ( result . size ) . toBe ( 12 ) ;
221+ expect ( mockSSMClient ) . toHaveReceivedCommandTimes ( GetParametersCommand , 2 ) ;
222+ for ( const name of names ) {
223+ expect ( result . get ( name ) ) . toBe ( `val-${ name } ` ) ;
224+ }
225+ } ) ;
226+
227+ it ( 'omits parameters with missing Name or Value' , async ( ) => {
228+ mockSSMClient . on ( GetParametersCommand ) . resolves ( {
229+ Parameters : [
230+ { Name : '/app/good' , Value : 'value' } ,
231+ { Name : '/app/no-value' , Value : undefined } ,
232+ { Name : undefined , Value : 'orphan' } ,
233+ ] ,
234+ } ) ;
235+
236+ const result = await getParameters ( [ '/app/good' , '/app/no-value' ] ) ;
237+
238+ expect ( result ) . toEqual ( new Map ( [ [ '/app/good' , 'value' ] ] ) ) ;
239+ } ) ;
240+
241+ it ( 'propagates errors from SSM API' , async ( ) => {
242+ mockSSMClient . on ( GetParametersCommand ) . rejects ( new Error ( 'AccessDenied' ) ) ;
243+
244+ await expect ( getParameters ( [ '/app/param1' ] ) ) . rejects . toThrow ( 'AccessDenied' ) ;
245+ } ) ;
246+
247+ it ( 'handles response with empty Parameters array' , async ( ) => {
248+ mockSSMClient . on ( GetParametersCommand ) . resolves ( {
249+ Parameters : [ ] ,
250+ } ) ;
251+
252+ const result = await getParameters ( [ '/app/missing' ] ) ;
253+
254+ expect ( result ) . toEqual ( new Map ( ) ) ;
255+ } ) ;
256+ } ) ;
0 commit comments