@@ -3,10 +3,10 @@ import { fromIni } from "@aws-sdk/credential-provider-ini";
3
3
import { fromProcess } from "@aws-sdk/credential-provider-process" ;
4
4
import { fromSSO } from "@aws-sdk/credential-provider-sso" ;
5
5
import { fromTokenFile } from "@aws-sdk/credential-provider-web-identity" ;
6
- import { CredentialsProviderError } from "@smithy/property-provider" ;
6
+ import { chain , CredentialsProviderError , memoize } from "@smithy/property-provider" ;
7
7
import { ENV_PROFILE , loadSharedConfigFiles } from "@smithy/shared-ini-file-loader" ;
8
8
9
- import { credentialsTreatedAsExpired , credentialsWillNeedRefresh , defaultProvider } from "./defaultProvider" ;
9
+ import { defaultProvider } from "./defaultProvider" ;
10
10
import { remoteProvider } from "./remoteProvider" ;
11
11
12
12
jest . mock ( "@aws-sdk/credential-provider-env" ) ;
@@ -15,6 +15,7 @@ jest.mock("@aws-sdk/credential-provider-ini");
15
15
jest . mock ( "@aws-sdk/credential-provider-process" ) ;
16
16
jest . mock ( "@aws-sdk/credential-provider-sso" ) ;
17
17
jest . mock ( "@aws-sdk/credential-provider-web-identity" ) ;
18
+ jest . mock ( "@smithy/property-provider" ) ;
18
19
jest . mock ( "@smithy/shared-ini-file-loader" ) ;
19
20
jest . mock ( "./remoteProvider" ) ;
20
21
@@ -24,24 +25,19 @@ describe(defaultProvider.name, () => {
24
25
secretAccessKey : "mockSecretAccessKey" ,
25
26
} ;
26
27
27
- const credentials = ( ) => {
28
- throw new CredentialsProviderError ( "test" , true ) ;
29
- } ;
30
-
31
- const finalCredentials = ( ) => {
32
- return mockCreds ;
33
- } ;
34
-
35
28
const mockInit = {
36
29
profile : "mockProfile" ,
37
30
} ;
38
31
39
- const mockEnvFn = jest . fn ( ) . mockImplementation ( ( ) => credentials ( ) ) ;
40
- const mockSsoFn = jest . fn ( ) . mockImplementation ( ( ) => credentials ( ) ) ;
41
- const mockIniFn = jest . fn ( ) . mockImplementation ( ( ) => credentials ( ) ) ;
42
- const mockProcessFn = jest . fn ( ) . mockImplementation ( ( ) => credentials ( ) ) ;
43
- const mockTokenFileFn = jest . fn ( ) . mockImplementation ( ( ) => credentials ( ) ) ;
44
- const mockRemoteProviderFn = jest . fn ( ) . mockImplementation ( ( ) => finalCredentials ( ) ) ;
32
+ const mockEnvFn = jest . fn ( ) ;
33
+ const mockSsoFn = jest . fn ( ) ;
34
+ const mockIniFn = jest . fn ( ) ;
35
+ const mockProcessFn = jest . fn ( ) ;
36
+ const mockTokenFileFn = jest . fn ( ) ;
37
+ const mockRemoteProviderFn = jest . fn ( ) ;
38
+
39
+ const mockChainFn = jest . fn ( ) ;
40
+ const mockMemoizeFn = jest . fn ( ) . mockResolvedValue ( mockCreds ) ;
45
41
46
42
beforeEach ( ( ) => {
47
43
[
@@ -51,48 +47,51 @@ describe(defaultProvider.name, () => {
51
47
[ fromProcess , mockProcessFn ] ,
52
48
[ fromTokenFile , mockTokenFileFn ] ,
53
49
[ remoteProvider , mockRemoteProviderFn ] ,
50
+ [ chain , mockChainFn ] ,
51
+ [ memoize , mockMemoizeFn ] ,
54
52
] . forEach ( ( [ fromFn , mockFn ] ) => {
55
53
( fromFn as jest . Mock ) . mockReturnValue ( mockFn ) ;
56
54
} ) ;
57
55
} ) ;
58
56
59
57
afterEach ( async ( ) => {
58
+ const errorFnIndex = ( chain as jest . Mock ) . mock . calls [ 0 ] . length ;
59
+ const errorFn = ( chain as jest . Mock ) . mock . calls [ 0 ] [ errorFnIndex - 1 ] ;
60
+ const expectedError = new CredentialsProviderError ( "Could not load credentials from any providers" , false ) ;
61
+ try {
62
+ await errorFn ( ) ;
63
+ fail ( `expected ${ expectedError } ` ) ;
64
+ } catch ( error ) {
65
+ expect ( error . toString ( ) ) . toStrictEqual ( expectedError . toString ( ) ) ;
66
+ }
67
+
68
+ expect ( memoize ) . toHaveBeenCalledWith ( mockChainFn , expect . any ( Function ) , expect . any ( Function ) ) ;
69
+
60
70
jest . clearAllMocks ( ) ;
61
71
} ) ;
62
72
63
73
describe ( "without fromEnv" , ( ) => {
64
- it ( "creates provider chain and memoizes it" , async ( ) => {
65
- const provider = defaultProvider ( mockInit ) ;
66
-
67
- // initial call proceeds through the chain.
68
- {
69
- const receivedCreds = await provider ( ) ;
70
- expect ( receivedCreds ) . toEqual ( mockCreds ) ;
74
+ afterEach ( ( ) => {
75
+ expect ( chain ) . toHaveBeenCalledWith (
76
+ mockSsoFn ,
77
+ mockIniFn ,
78
+ mockProcessFn ,
79
+ mockTokenFileFn ,
80
+ mockRemoteProviderFn ,
81
+ expect . any ( Function )
82
+ ) ;
83
+ } ) ;
71
84
72
- expect ( fromEnv ) . not . toHaveBeenCalled ( ) ;
73
- expect ( fromSSO ) . toHaveBeenCalledWith ( mockInit ) ;
74
- expect ( fromIni ) . toHaveBeenCalledWith ( mockInit ) ;
75
- expect ( fromProcess ) . toHaveBeenCalledWith ( mockInit ) ;
76
- expect ( fromTokenFile ) . toHaveBeenCalledWith ( mockInit ) ;
77
- expect ( remoteProvider ) . toHaveBeenCalledWith ( mockInit ) ;
85
+ it ( "creates provider chain and memoizes it" , async ( ) => {
86
+ const receivedCreds = await defaultProvider ( mockInit ) ( ) ;
87
+ expect ( receivedCreds ) . toStrictEqual ( mockCreds ) ;
78
88
79
- expect ( loadSharedConfigFiles ) . not . toHaveBeenCalled ( ) ;
89
+ expect ( fromEnv ) . not . toHaveBeenCalled ( ) ;
90
+ for ( const fromFn of [ fromSSO , fromIni , fromProcess , fromTokenFile , remoteProvider ] ) {
91
+ expect ( fromFn ) . toHaveBeenCalledWith ( mockInit ) ;
80
92
}
81
93
82
- jest . clearAllMocks ( ) ;
83
-
84
- // subsequent call does not enter the chain.
85
- {
86
- const receivedCreds = await provider ( ) ;
87
- expect ( receivedCreds ) . toEqual ( mockCreds ) ;
88
-
89
- expect ( fromEnv ) . not . toHaveBeenCalled ( ) ;
90
- expect ( fromSSO ) . not . toHaveBeenCalledWith ( mockInit ) ;
91
- expect ( fromIni ) . not . toHaveBeenCalledWith ( mockInit ) ;
92
- expect ( fromProcess ) . not . toHaveBeenCalledWith ( mockInit ) ;
93
- expect ( fromTokenFile ) . not . toHaveBeenCalledWith ( mockInit ) ;
94
- expect ( remoteProvider ) . not . toHaveBeenCalledWith ( mockInit ) ;
95
- }
94
+ expect ( loadSharedConfigFiles ) . not . toHaveBeenCalled ( ) ;
96
95
} ) ;
97
96
98
97
it ( `if env['${ ENV_PROFILE } '] is set` , async ( ) => {
@@ -124,42 +123,63 @@ describe(defaultProvider.name, () => {
124
123
for ( const fromFn of [ fromSSO , fromIni , fromProcess , fromTokenFile , remoteProvider ] ) {
125
124
expect ( fromFn ) . toHaveBeenCalledWith ( mockInitWithoutProfile ) ;
126
125
}
126
+
127
+ expect ( chain ) . toHaveBeenCalledWith (
128
+ mockEnvFn ,
129
+ mockSsoFn ,
130
+ mockIniFn ,
131
+ mockProcessFn ,
132
+ mockTokenFileFn ,
133
+ mockRemoteProviderFn ,
134
+ expect . any ( Function )
135
+ ) ;
127
136
} ) ;
128
137
129
- describe ( credentialsTreatedAsExpired . name , ( ) => {
138
+ describe ( "memoize isExpired" , ( ) => {
130
139
const mockDateNow = Date . now ( ) ;
131
140
beforeEach ( async ( ) => {
132
141
jest . spyOn ( Date , "now" ) . mockReturnValueOnce ( mockDateNow ) ;
142
+ await defaultProvider ( mockInit ) ( ) ;
133
143
} ) ;
134
144
135
145
it ( "returns true if expiration is defined, and creds have expired" , ( ) => {
146
+ const memoizeExpiredFn = ( memoize as jest . Mock ) . mock . calls [ 0 ] [ 1 ] ;
136
147
const expiration = new Date ( mockDateNow - 24 * 60 * 60 * 1000 ) ;
137
- expect ( credentialsTreatedAsExpired ( { ... mockCreds , expiration } ) ) . toEqual ( true ) ;
148
+ expect ( memoizeExpiredFn ( { expiration } ) ) . toEqual ( true ) ;
138
149
} ) ;
139
150
140
151
it ( "returns true if expiration is defined, and creds expire in <5 mins" , ( ) => {
152
+ const memoizeExpiredFn = ( memoize as jest . Mock ) . mock . calls [ 0 ] [ 1 ] ;
141
153
const expiration = new Date ( mockDateNow + 299 * 1000 ) ;
142
- expect ( credentialsTreatedAsExpired ( { ... mockCreds , expiration } ) ) . toEqual ( true ) ;
154
+ expect ( memoizeExpiredFn ( { expiration } ) ) . toEqual ( true ) ;
143
155
} ) ;
144
156
145
157
it ( "returns false if expiration is defined, but creds expire in >5 mins" , ( ) => {
158
+ const memoizeExpiredFn = ( memoize as jest . Mock ) . mock . calls [ 0 ] [ 1 ] ;
146
159
const expiration = new Date ( mockDateNow + 301 * 1000 ) ;
147
- expect ( credentialsTreatedAsExpired ( { ... mockCreds , expiration } ) ) . toEqual ( false ) ;
160
+ expect ( memoizeExpiredFn ( { expiration } ) ) . toEqual ( false ) ;
148
161
} ) ;
149
162
150
163
it ( "returns false if expiration is not defined" , ( ) => {
151
- expect ( credentialsTreatedAsExpired ( { ...mockCreds } ) ) . toEqual ( false ) ;
164
+ const memoizeExpiredFn = ( memoize as jest . Mock ) . mock . calls [ 0 ] [ 1 ] ;
165
+ expect ( memoizeExpiredFn ( { } ) ) . toEqual ( false ) ;
152
166
} ) ;
153
167
} ) ;
154
168
155
- describe ( credentialsWillNeedRefresh . name , ( ) => {
169
+ describe ( "memoize requiresRefresh" , ( ) => {
170
+ beforeEach ( async ( ) => {
171
+ await defaultProvider ( mockInit ) ( ) ;
172
+ } ) ;
173
+
156
174
it ( "returns true if expiration is not defined" , ( ) => {
157
- const expiration = new Date ( ) ;
158
- expect ( credentialsWillNeedRefresh ( { ...mockCreds , expiration } ) ) . toEqual ( true ) ;
175
+ const memoizeRefreshFn = ( memoize as jest . Mock ) . mock . calls [ 0 ] [ 2 ] ;
176
+ const expiration = Date . now ( ) ;
177
+ expect ( memoizeRefreshFn ( { expiration } ) ) . toEqual ( true ) ;
159
178
} ) ;
160
179
161
180
it ( "returns false if expiration is not defined" , ( ) => {
162
- expect ( credentialsWillNeedRefresh ( { ...mockCreds } ) ) . toEqual ( false ) ;
181
+ const memoizeRefreshFn = ( memoize as jest . Mock ) . mock . calls [ 0 ] [ 2 ] ;
182
+ expect ( memoizeRefreshFn ( { } ) ) . toEqual ( false ) ;
163
183
} ) ;
164
184
} ) ;
165
185
} ) ;
0 commit comments