@@ -37,7 +37,11 @@ import {
3737 AppCheckInternalComponentName
3838} from '@firebase/app-check-interop-types' ;
3939import { makeFakeApp , createTestService } from '../test/utils' ;
40- import { FunctionsService , httpsCallable } from './service' ;
40+ import {
41+ FunctionsService ,
42+ httpsCallable ,
43+ httpsCallableFromURL
44+ } from './service' ;
4145import { FUNCTIONS_TYPE } from './constants' ;
4246import { FunctionsError } from './error' ;
4347
@@ -523,9 +527,136 @@ describe('Firebase Functions > Stream', () => {
523527 const [ _ , options ] = mockFetch . firstCall . args ;
524528 expect ( options . headers [ 'Authorization' ] ) . to . equal ( 'Bearer auth-token' ) ;
525529 expect ( options . headers [ 'Content-Type' ] ) . to . equal ( 'application/json' ) ;
530+ expect ( options . credentials ) . to . equal ( undefined ) ;
526531 expect ( options . headers [ 'Accept' ] ) . to . equal ( 'text/event-stream' ) ;
527532 } ) ;
528533
534+ it ( 'calls cloud workstations with credentials' , async ( ) => {
535+ const authMock : FirebaseAuthInternal = {
536+ getToken : async ( ) => ( { accessToken : 'auth-token' } )
537+ } as unknown as FirebaseAuthInternal ;
538+ const authProvider = new Provider < FirebaseAuthInternalName > (
539+ 'auth-internal' ,
540+ new ComponentContainer ( 'test' )
541+ ) ;
542+ authProvider . setComponent (
543+ new Component ( 'auth-internal' , ( ) => authMock , ComponentType . PRIVATE )
544+ ) ;
545+ const appCheckMock : FirebaseAppCheckInternal = {
546+ getToken : async ( ) => ( { token : 'app-check-token' } )
547+ } as unknown as FirebaseAppCheckInternal ;
548+ const appCheckProvider = new Provider < AppCheckInternalComponentName > (
549+ 'app-check-internal' ,
550+ new ComponentContainer ( 'test' )
551+ ) ;
552+ appCheckProvider . setComponent (
553+ new Component (
554+ 'app-check-internal' ,
555+ ( ) => appCheckMock ,
556+ ComponentType . PRIVATE
557+ )
558+ ) ;
559+
560+ const functions = createTestService (
561+ app ,
562+ region ,
563+ authProvider ,
564+ undefined ,
565+ appCheckProvider
566+ ) ;
567+ functions . emulatorOrigin = 'test.cloudworkstations.dev' ;
568+ const mockFetch = sinon . stub ( functions , 'fetchImpl' as any ) ;
569+
570+ const mockResponse = new ReadableStream ( {
571+ start ( controller ) {
572+ controller . enqueue (
573+ new TextEncoder ( ) . encode ( 'data: {"result":"Success"}\n' )
574+ ) ;
575+ controller . close ( ) ;
576+ }
577+ } ) ;
578+
579+ mockFetch . resolves ( {
580+ body : mockResponse ,
581+ headers : new Headers ( { 'Content-Type' : 'text/event-stream' } ) ,
582+ status : 200 ,
583+ statusText : 'OK'
584+ } as Response ) ;
585+
586+ const func = httpsCallable < Record < string , any > , string , string > (
587+ functions ,
588+ 'stream'
589+ ) ;
590+ await func . stream ( { } ) ;
591+
592+ expect ( mockFetch . calledOnce ) . to . be . true ;
593+ const [ _ , options ] = mockFetch . firstCall . args ;
594+ expect ( options . credentials ) . to . equal ( 'include' ) ;
595+ } ) ;
596+
597+ it ( 'calls streamFromURL cloud workstations with credentials' , async ( ) => {
598+ const authMock : FirebaseAuthInternal = {
599+ getToken : async ( ) => ( { accessToken : 'auth-token' } )
600+ } as unknown as FirebaseAuthInternal ;
601+ const authProvider = new Provider < FirebaseAuthInternalName > (
602+ 'auth-internal' ,
603+ new ComponentContainer ( 'test' )
604+ ) ;
605+ authProvider . setComponent (
606+ new Component ( 'auth-internal' , ( ) => authMock , ComponentType . PRIVATE )
607+ ) ;
608+ const appCheckMock : FirebaseAppCheckInternal = {
609+ getToken : async ( ) => ( { token : 'app-check-token' } )
610+ } as unknown as FirebaseAppCheckInternal ;
611+ const appCheckProvider = new Provider < AppCheckInternalComponentName > (
612+ 'app-check-internal' ,
613+ new ComponentContainer ( 'test' )
614+ ) ;
615+ appCheckProvider . setComponent (
616+ new Component (
617+ 'app-check-internal' ,
618+ ( ) => appCheckMock ,
619+ ComponentType . PRIVATE
620+ )
621+ ) ;
622+
623+ const functions = createTestService (
624+ app ,
625+ region ,
626+ authProvider ,
627+ undefined ,
628+ appCheckProvider
629+ ) ;
630+ functions . emulatorOrigin = 'test.cloudworkstations.dev' ;
631+ const mockFetch = sinon . stub ( functions , 'fetchImpl' as any ) ;
632+
633+ const mockResponse = new ReadableStream ( {
634+ start ( controller ) {
635+ controller . enqueue (
636+ new TextEncoder ( ) . encode ( 'data: {"result":"Success"}\n' )
637+ ) ;
638+ controller . close ( ) ;
639+ }
640+ } ) ;
641+
642+ mockFetch . resolves ( {
643+ body : mockResponse ,
644+ headers : new Headers ( { 'Content-Type' : 'text/event-stream' } ) ,
645+ status : 200 ,
646+ statusText : 'OK'
647+ } as Response ) ;
648+
649+ const func = httpsCallableFromURL < Record < string , any > , string , string > (
650+ functions ,
651+ 'stream'
652+ ) ;
653+ await func . stream ( { } ) ;
654+
655+ expect ( mockFetch . calledOnce ) . to . be . true ;
656+ const [ _ , options ] = mockFetch . firstCall . args ;
657+ expect ( options . credentials ) . to . equal ( 'include' ) ;
658+ } ) ;
659+
529660 it ( 'aborts during initial fetch' , async ( ) => {
530661 const controller = new AbortController ( ) ;
531662
0 commit comments