@@ -225,6 +225,77 @@ describe('ExecAuth', () => {
225225 strictEqual ( execCount , 2 ) ;
226226 } ) ;
227227
228+ it ( 'should cache tokens without expirationTimestamp (non-expiring tokens)' , async ( ) => {
229+ // TODO: fix this test for Windows
230+ if ( process . platform === 'win32' ) {
231+ return ;
232+ }
233+ const auth = new ExecAuth ( ) ;
234+ let execCount = 0 ;
235+ const tokenValue = 'non-expiring-token' ;
236+
237+ ( auth as any ) . execFn = (
238+ command : string ,
239+ args ?: readonly string [ ] ,
240+ options ?: child_process . SpawnOptionsWithoutStdio ,
241+ ) : child_process . ChildProcessWithoutNullStreams => {
242+ execCount ++ ;
243+ return {
244+ stdout : {
245+ setEncoding : ( ) => { } ,
246+ on : ( _data : string , f : ( data : Buffer | string ) => void ) => {
247+ // Note: No expirationTimestamp field - token should never expire
248+ f (
249+ Buffer . from (
250+ JSON . stringify ( {
251+ status : { token : tokenValue } ,
252+ } ) ,
253+ ) ,
254+ ) ;
255+ } ,
256+ } ,
257+ stderr : {
258+ setEncoding : ( ) => { } ,
259+ on : ( ) => { } ,
260+ } ,
261+ on : ( op : string , f : any ) => {
262+ if ( op === 'close' ) {
263+ f ( 0 ) ;
264+ }
265+ } ,
266+ } as unknown as child_process . ChildProcessWithoutNullStreams ;
267+ } ;
268+
269+ const user = {
270+ name : 'user' ,
271+ authProvider : {
272+ config : {
273+ exec : {
274+ command : 'echo' ,
275+ } ,
276+ } ,
277+ } ,
278+ } ;
279+
280+ const opts = { } as https . RequestOptions ;
281+ opts . headers = { } as OutgoingHttpHeaders ;
282+
283+ // First call - should execute the command
284+ await auth . applyAuthentication ( user , opts ) ;
285+ strictEqual ( opts . headers . Authorization , `Bearer ${ tokenValue } ` ) ;
286+ strictEqual ( execCount , 1 ) ;
287+
288+ // Second call - should use cached token (no expiration means never expires)
289+ await auth . applyAuthentication ( user , opts ) ;
290+ strictEqual ( opts . headers . Authorization , `Bearer ${ tokenValue } ` ) ;
291+ strictEqual ( execCount , 1 , 'exec should not be called again for non-expiring token' ) ;
292+
293+ // Third call - still should use cached token
294+ await auth . applyAuthentication ( user , opts ) ;
295+ strictEqual ( opts . headers . Authorization , `Bearer ${ tokenValue } ` ) ;
296+ strictEqual ( execCount , 1 , 'exec should still not be called again' ) ;
297+ } ) ;
298+
228299 it ( 'should return null on no exec info' , async ( ) => {
229300 const auth = new ExecAuth ( ) ;
230301 const opts = { } as https . RequestOptions ;
0 commit comments