@@ -41,6 +41,7 @@ import {
4141import { HttpClient } from '../../../src/utils/api-request' ;
4242import { Agent } from 'https' ;
4343import { FirebaseAppError } from '../../../src/utils/error' ;
44+ import { deepCopy } from '../../../src/utils/deep-copy' ;
4445
4546chai . should ( ) ;
4647chai . use ( sinonChai ) ;
@@ -420,6 +421,75 @@ describe('Credential', () => {
420421 } ) ;
421422 } ) ;
422423
424+ describe ( 'ImpersonatedServiceAccountCredential' , ( ) => {
425+ it ( 'should throw if called with the path to an invalid file' , ( ) => {
426+ const invalidPath = path . resolve ( __dirname , '../../resources/unparsable.key.json' ) ;
427+ expect ( ( ) => new ImpersonatedServiceAccountCredential ( invalidPath ) )
428+ . to . throw ( 'Failed to parse impersonated service account file' ) ;
429+ } ) ;
430+
431+ it ( 'should throw given an object without a "clientId" property' , ( ) => {
432+ const invalidCredential = deepCopy ( MOCK_IMPERSONATED_TOKEN_CONFIG ) ;
433+ invalidCredential . source_credentials . client_id = '' ;
434+ expect ( ( ) => new ImpersonatedServiceAccountCredential ( invalidCredential as any ) )
435+ . to . throw ( 'Impersonated Service Account must contain a "source_credentials.client_id" property.' ) ;
436+ } ) ;
437+
438+ it ( 'should throw given an object without a "clientSecret" property' , ( ) => {
439+ const invalidCredential = deepCopy ( MOCK_IMPERSONATED_TOKEN_CONFIG ) ;
440+ invalidCredential . source_credentials . client_secret = '' ;
441+ expect ( ( ) => new ImpersonatedServiceAccountCredential ( invalidCredential as any ) )
442+ . to . throw ( 'Impersonated Service Account must contain a "source_credentials.client_secret" property.' ) ;
443+ } ) ;
444+
445+ it ( 'should throw given an object without a "refreshToken" property' , ( ) => {
446+ const invalidCredential = deepCopy ( MOCK_IMPERSONATED_TOKEN_CONFIG ) ;
447+ invalidCredential . source_credentials . refresh_token = '' ;
448+ expect ( ( ) => new ImpersonatedServiceAccountCredential ( invalidCredential as any ) )
449+ . to . throw ( 'Impersonated Service Account must contain a "source_credentials.refresh_token" property.' ) ;
450+ } ) ;
451+
452+ it ( 'should throw given an object without a "type" property' , ( ) => {
453+ const invalidCredential = deepCopy ( MOCK_IMPERSONATED_TOKEN_CONFIG ) ;
454+ invalidCredential . source_credentials . type = '' ;
455+ expect ( ( ) => new ImpersonatedServiceAccountCredential ( invalidCredential as any ) )
456+ . to . throw ( 'Impersonated Service Account must contain a "source_credentials.type" property.' ) ;
457+ } ) ;
458+
459+ it ( 'should return a Credential' , ( ) => {
460+ const c = new ImpersonatedServiceAccountCredential ( MOCK_IMPERSONATED_TOKEN_CONFIG ) ;
461+ expect ( c ) . to . deep . include ( {
462+ implicit : false ,
463+ } ) ;
464+ } ) ;
465+
466+ it ( 'should return an implicit Credential' , ( ) => {
467+ const c = new ImpersonatedServiceAccountCredential ( MOCK_IMPERSONATED_TOKEN_CONFIG , undefined , true ) ;
468+ expect ( c ) . to . deep . include ( {
469+ implicit : true ,
470+ } ) ;
471+ } ) ;
472+
473+ it ( 'should create access tokens' , ( ) => {
474+ const scope = nock ( 'https://www.googleapis.com' )
475+ . post ( '/oauth2/v4/token' )
476+ . reply ( 200 , {
477+ access_token : 'token' ,
478+ token_type : 'Bearer' ,
479+ expires_in : 60 * 60 ,
480+ } , {
481+ 'cache-control' : 'no-cache, no-store, max-age=0, must-revalidate' ,
482+ } ) ;
483+ mockedRequests . push ( scope ) ;
484+
485+ const c = new ImpersonatedServiceAccountCredential ( MOCK_IMPERSONATED_TOKEN_CONFIG ) ;
486+ return c . getAccessToken ( ) . then ( ( token ) => {
487+ expect ( token . access_token ) . to . be . a ( 'string' ) . and . to . not . be . empty ;
488+ expect ( token . expires_in ) . to . greaterThan ( FIVE_MINUTES_IN_SECONDS ) ;
489+ } ) ;
490+ } ) ;
491+ } ) ;
492+
423493 describe ( 'getApplicationDefault()' , ( ) => {
424494 let fsStub : sinon . SinonStub ;
425495
0 commit comments