@@ -3,12 +3,26 @@ import { InvokeCommand, LambdaClient } from '@aws-sdk/client-lambda';
33import { DynamoDBClient } from '@aws-sdk/client-dynamodb' ;
44import { ScanCommand } from '@aws-sdk/lib-dynamodb' ;
55import { GetParameterCommand , SSMClient } from '@aws-sdk/client-ssm' ;
6- import { version as PT_VERSION } from '../../package.json ' ;
6+ import { PT_VERSION } from '../../src/version ' ;
77import { AppConfigDataClient } from '@aws-sdk/client-appconfigdata' ;
88import {
99 GetSecretValueCommand ,
1010 SecretsManagerClient ,
1111} from '@aws-sdk/client-secrets-manager' ;
12+ import { RelativeMiddlewareOptions } from '@aws-sdk/types/dist-types/middleware' ;
13+
14+ type SupportedSdkClients =
15+ | LambdaClient
16+ | DynamoDBClient
17+ | SSMClient
18+ | SecretsManagerClient
19+ | AppConfigDataClient ;
20+
21+ type SupportedSdkCommands =
22+ | InvokeCommand
23+ | ScanCommand
24+ | GetParameterCommand
25+ | GetSecretValueCommand ;
1226
1327const options = {
1428 region : 'us-east-1' ,
@@ -20,6 +34,57 @@ const options = {
2034 } ,
2135} ;
2236
37+ const assertMiddleware = ( feature : string ) => {
38+ // eslint-disable-next-line @typescript-eslint/ban-ts-comment
39+ // @ts -ignore
40+ return ( next ) => ( args ) => {
41+ const userAgent = args ?. request ?. headers [ 'user-agent' ] ;
42+ expect ( userAgent ) . toContain ( `PT/${ feature } /${ PT_VERSION } PTEnv/NA` ) ;
43+ // make sure it's at the end of the user agent
44+ expect (
45+ // eslint-disable-next-line @typescript-eslint/ban-ts-comment
46+ // @ts -ignore
47+ userAgent
48+ ?. split ( ' ' )
49+ . slice ( userAgent ?. split ( ' ' ) . length - 2 ) // take the last to entries of the user-agent header
50+ . join ( ' ' )
51+ ) . toEqual ( `PT/${ feature } /${ PT_VERSION } PTEnv/NA` ) ;
52+
53+ return next ( args ) ;
54+ } ;
55+ } ;
56+
57+ const assertMiddlewareOptions : RelativeMiddlewareOptions = {
58+ relation : 'after' ,
59+ toMiddleware : 'addPowertoolsToUserAgent' ,
60+ name : 'testUserAgentHeader' ,
61+ tags : [ 'TEST' ] ,
62+ } ;
63+
64+ const runCommand = async (
65+ client : SupportedSdkClients ,
66+ command : SupportedSdkCommands
67+ ) : Promise < unknown > => {
68+ try {
69+ // eslint-disable-next-line @typescript-eslint/ban-ts-comment
70+ // @ts -ignore
71+ return await client . send ( command ) ;
72+ } catch ( e ) {
73+ // throw only jest errors and swallow the SDK client errors like credentials or connection issues
74+ if (
75+ e instanceof Error &&
76+ // eslint-disable-next-line @typescript-eslint/ban-ts-comment
77+ // @ts -ignore
78+ e . matcherResult !== undefined &&
79+ // eslint-disable-next-line @typescript-eslint/ban-ts-comment
80+ // @ts -ignore
81+ e . matcherResult . pass === false
82+ ) {
83+ throw e ;
84+ }
85+ }
86+ } ;
87+
2388describe ( 'Given a client of instance: ' , ( ) => {
2489 it . each ( [
2590 {
@@ -57,44 +122,15 @@ describe('Given a client of instance: ', () => {
57122 ) ;
58123
59124 client . middlewareStack . addRelativeTo (
60- // eslint-disable-next-line @typescript-eslint/ban-ts-comment
61- // @ts -ignore
62- ( next ) => ( args ) => {
63- const userAgent = args ?. request ?. headers [ 'user-agent' ] ;
64- expect ( userAgent ) . toContain ( `PT/my-feature/${ PT_VERSION } PTEnv/NA` ) ;
65- // make sure it's at the end of the user agent
66- expect (
67- // eslint-disable-next-line @typescript-eslint/ban-ts-comment
68- // @ts -ignore
69- userAgent
70- ?. split ( ' ' )
71- . slice ( userAgent ?. split ( ' ' ) . length - 2 ) // take the last to entries of the user-agent header
72- . join ( ' ' )
73- ) . toEqual ( `PT/my-feature/${ PT_VERSION } PTEnv/NA` ) ;
74-
75- return next ( args ) ;
76- } ,
77- {
78- relation : 'after' ,
79- toMiddleware : 'addPowertoolsToUserAgent' ,
80- name : 'testUserAgentHeader' ,
81- tags : [ 'TEST' ] ,
82- }
125+ assertMiddleware ( 'my-feature' ) ,
126+ assertMiddlewareOptions
83127 ) ;
84128
85- try {
86- // eslint-disable-next-line @typescript-eslint/ban-ts-comment
87- // @ts -ignore
88- await client . send ( command ) ;
89- } catch ( e ) {
90- if ( e instanceof Error && e . name === 'JestAssertionError' ) {
91- throw e ;
92- }
93- }
129+ await runCommand ( client , command ) ;
94130 }
95131 ) ;
96132
97- it ( 'should not throw erro , when client fails to add middleware' , ( ) => {
133+ it ( 'should not throw error , when client fails to add middleware' , ( ) => {
98134 // create mock client that throws error when adding middleware
99135 const client = {
100136 middlewareStack : {
@@ -106,4 +142,21 @@ describe('Given a client of instance: ', () => {
106142
107143 expect ( ( ) => addUserAgentMiddleware ( client , 'my-feature' ) ) . not . toThrow ( ) ;
108144 } ) ;
145+
146+ it ( 'should no-op if we add the middleware twice' , async ( ) => {
147+ const client = new LambdaClient ( options ) ;
148+ const command = new InvokeCommand ( { FunctionName : 'test' , Payload : '' } ) ;
149+ addUserAgentMiddleware ( client , 'my-feature' ) ;
150+ addUserAgentMiddleware ( client , 'your-feature' ) ;
151+
152+ client . middlewareStack . addRelativeTo (
153+ assertMiddleware ( 'my-feature' ) ,
154+ assertMiddlewareOptions
155+ ) ;
156+ await runCommand ( client , command ) ;
157+
158+ expect ( client . middlewareStack . identify ( ) ) . toContain (
159+ 'addPowertoolsToUserAgent: POWERTOOLS,USER_AGENT'
160+ ) ;
161+ } ) ;
109162} ) ;
0 commit comments