@@ -340,6 +340,115 @@ describe('DataConnectApiClient', () => {
340340 } ) ;
341341 } ) ;
342342 } ) ;
343+
344+ describe ( 'impersonateMutation' , ( ) => {
345+ const unauthenticatedOptions : GraphqlOptions < unknown > =
346+ { operationName : 'operationName' , impersonate : { unauthenticated : true } } ;
347+
348+ it ( 'should reject when no operationName is provided' , ( ) => {
349+ apiClient . impersonateMutation ( { impersonate : { unauthenticated : true } } )
350+ . should . eventually . be . rejectedWith ( '`query` must be a non-empty string.' ) ;
351+ apiClient . impersonateMutation ( { operationName : undefined , impersonate : { unauthenticated : true } } )
352+ . should . eventually . be . rejectedWith ( '`query` must be a non-empty string.' ) ;
353+ } ) ;
354+ it ( 'should reject when no impersonate object is provided' , ( ) => {
355+ apiClient . impersonateMutation ( { operationName : 'queryName' } )
356+ . should . eventually . be . rejectedWith ( 'GraphqlOptions must be a non-null object' ) ;
357+ apiClient . impersonateMutation ( { operationName : 'queryName' , impersonate : undefined } )
358+ . should . eventually . be . rejectedWith ( 'GraphqlOptions must be a non-null object' ) ;
359+ } ) ;
360+ it ( 'should reject when project id is not available' , ( ) => {
361+ clientWithoutProjectId . impersonateMutation ( unauthenticatedOptions )
362+ . should . eventually . be . rejectedWith ( noProjectId ) ;
363+ } ) ;
364+
365+ it ( 'should reject when a full platform error response is received' , ( ) => {
366+ sandbox
367+ . stub ( HttpClient . prototype , 'send' )
368+ . rejects ( utils . errorFrom ( ERROR_RESPONSE , 404 ) ) ;
369+ const expected = new FirebaseDataConnectError ( 'not-found' , 'Requested entity not found' ) ;
370+ return apiClient . impersonateMutation ( unauthenticatedOptions )
371+ . should . eventually . be . rejected . and . deep . include ( expected ) ;
372+ } ) ;
373+
374+ it ( 'should reject with unknown-error when error code is not present' , ( ) => {
375+ sandbox
376+ . stub ( HttpClient . prototype , 'send' )
377+ . rejects ( utils . errorFrom ( { } , 404 ) ) ;
378+ const expected = new FirebaseDataConnectError ( 'unknown-error' , 'Unknown server error: {}' ) ;
379+ return apiClient . impersonateMutation ( unauthenticatedOptions )
380+ . should . eventually . be . rejected . and . deep . include ( expected ) ;
381+ } ) ;
382+
383+ it ( 'should reject with unknown-error for non-json response' , ( ) => {
384+ sandbox
385+ . stub ( HttpClient . prototype , 'send' )
386+ . rejects ( utils . errorFrom ( 'not json' , 404 ) ) ;
387+ const expected = new FirebaseDataConnectError (
388+ 'unknown-error' , 'Unexpected response with status: 404 and body: not json' ) ;
389+ return apiClient . impersonateMutation ( unauthenticatedOptions )
390+ . should . eventually . be . rejected . and . deep . include ( expected ) ;
391+ } ) ;
392+
393+ it ( 'should reject when rejected with a FirebaseDataConnectError' , ( ) => {
394+ const expected = new FirebaseDataConnectError ( 'internal-error' , 'socket hang up' ) ;
395+ sandbox
396+ . stub ( HttpClient . prototype , 'send' )
397+ . rejects ( expected ) ;
398+ return apiClient . impersonateMutation ( unauthenticatedOptions )
399+ . should . eventually . be . rejected . and . deep . include ( expected ) ;
400+ } ) ;
401+
402+ it ( 'should resolve with the GraphQL response on success' , ( ) => {
403+ interface UsersResponse {
404+ users : [
405+ user : {
406+ id : string ;
407+ name : string ;
408+ address : string ;
409+ }
410+ ] ;
411+ }
412+ const stub = sandbox
413+ . stub ( HttpClient . prototype , 'send' )
414+ . resolves ( utils . responseFrom ( TEST_RESPONSE , 200 ) ) ;
415+ return apiClient . impersonateMutation < UsersResponse , unknown > ( unauthenticatedOptions )
416+ . then ( ( resp ) => {
417+ expect ( resp . data . users ) . to . be . not . empty ;
418+ expect ( resp . data . users [ 0 ] . name ) . to . be . not . undefined ;
419+ expect ( resp . data . users [ 0 ] . address ) . to . be . not . undefined ;
420+ expect ( resp . data . users ) . to . deep . equal ( TEST_RESPONSE . data . users ) ;
421+ expect ( stub ) . to . have . been . calledOnce . and . calledWith ( {
422+ method : 'POST' ,
423+ url : `https://firebasedataconnect.googleapis.com/v1alpha/projects/test-project/locations/${ connectorConfig . location } /services/${ connectorConfig . serviceId } /connectors/${ DataConnectService . getId ( connectorConfig ) } :impersonateMutation` ,
424+ headers : EXPECTED_HEADERS ,
425+ data : {
426+ operationName : unauthenticatedOptions . operationName ,
427+ extensions : { impersonate : unauthenticatedOptions . impersonate }
428+ }
429+ } ) ;
430+ } ) ;
431+ } ) ;
432+
433+ it ( 'should use DATA_CONNECT_EMULATOR_HOST if set' , ( ) => {
434+ process . env . DATA_CONNECT_EMULATOR_HOST = 'localhost:9399' ;
435+ const stub = sandbox
436+ . stub ( HttpClient . prototype , 'send' )
437+ . resolves ( utils . responseFrom ( TEST_RESPONSE , 200 ) ) ;
438+ return apiClient . impersonateMutation ( unauthenticatedOptions )
439+ . then ( ( ) => {
440+ expect ( stub ) . to . have . been . calledOnce . and . calledWith ( {
441+ method : 'POST' ,
442+ url : `http://localhost:9399/v1alpha/projects/test-project/locations/${ connectorConfig . location } /services/${ connectorConfig . serviceId } /connectors/${ DataConnectService . getId ( connectorConfig ) } :impersonateMutation` ,
443+ headers : EMULATOR_EXPECTED_HEADERS ,
444+ data : {
445+ operationName : unauthenticatedOptions . operationName ,
446+ extensions : { impersonate : unauthenticatedOptions . impersonate }
447+ }
448+ } ) ;
449+ } ) ;
450+ } ) ;
451+ } ) ;
343452} ) ;
344453
345454describe ( 'DataConnectApiClient CRUD helpers' , ( ) => {
0 commit comments