1919
2020import * as chai from 'chai' ;
2121import * as sinonChai from 'sinon-chai' ;
22+ import { createSandbox , SinonSandbox } from 'sinon' ;
2223import * as chaiAsPromised from 'chai-as-promised' ;
2324
2425import * as mocks from '../../resources/mocks' ;
2526import { App } from '../../../src/app/index' ;
26- import { getStorage , Storage } from '../../../src/storage/index' ;
27+ import * as StorageUtils from '../../../src/storage/utils' ;
28+ import { getStorage , Storage , getDownloadUrl } from '../../../src/storage/index' ;
2729
2830chai . should ( ) ;
2931chai . use ( sinonChai ) ;
@@ -35,13 +37,19 @@ describe('Storage', () => {
3537 let mockApp : App ;
3638 let mockCredentialApp : App ;
3739
38- const noProjectIdError = 'Failed to initialize Google Cloud Storage client with the '
39- + 'available credential. Must initialize the SDK with a certificate credential or '
40- + 'application default credentials to use Cloud Storage API.' ;
40+ const noProjectIdError =
41+ 'Failed to initialize Google Cloud Storage client with the ' +
42+ 'available credential. Must initialize the SDK with a certificate credential or ' +
43+ 'application default credentials to use Cloud Storage API.' ;
4144
45+ let sandbox : SinonSandbox ;
4246 beforeEach ( ( ) => {
4347 mockApp = mocks . app ( ) ;
4448 mockCredentialApp = mocks . mockCredentialApp ( ) ;
49+ sandbox = createSandbox ( ) ;
50+ } ) ;
51+ afterEach ( ( ) => {
52+ sandbox . restore ( ) ;
4553 } ) ;
4654
4755 describe ( 'getStorage()' , ( ) => {
@@ -69,5 +77,72 @@ describe('Storage', () => {
6977 const storage2 : Storage = getStorage ( mockApp ) ;
7078 expect ( storage1 ) . to . equal ( storage2 ) ;
7179 } ) ;
80+
81+ it ( 'should return an error when no metadata is available' , async ( ) => {
82+ sandbox
83+ . stub ( StorageUtils , 'getFirebaseMetadata' )
84+ . returns ( Promise . resolve ( { } as StorageUtils . FirebaseMetadata ) ) ;
85+ const storage1 = getStorage ( mockApp ) ;
86+ const fileRef = storage1 . bucket ( 'gs://mock' ) . file ( 'abc' ) ;
87+ await expect ( getDownloadUrl ( fileRef ) ) . to . be . rejectedWith (
88+ 'No download token available. Please create one in the Firebase Console.'
89+ ) ;
90+ } ) ;
91+
92+ it ( 'should return an error when unable to fetch metadata' , async ( ) => {
93+ const error = new Error ( 'Could not get metadata' ) ;
94+ sandbox
95+ . stub ( StorageUtils , 'getFirebaseMetadata' )
96+ . returns ( Promise . reject ( error ) ) ;
97+ const storage1 = getStorage ( mockApp ) ;
98+ const fileRef = storage1 . bucket ( 'gs://mock' ) . file ( 'abc' ) ;
99+ await expect ( getDownloadUrl ( fileRef ) ) . to . be . rejectedWith (
100+ error
101+ ) ;
102+ } ) ;
103+ it ( 'should return the proper download url when metadata is available' , async ( ) => {
104+ const downloadTokens = [ 'abc' , 'def' ] ;
105+ sandbox
106+ . stub ( StorageUtils , 'getFirebaseMetadata' )
107+ . returns (
108+ Promise . resolve ( {
109+ downloadTokens : downloadTokens . join ( ',' ) ,
110+ } as StorageUtils . FirebaseMetadata )
111+ ) ;
112+ const storage1 = getStorage ( mockApp ) ;
113+ const fileRef = storage1 . bucket ( 'gs://mock' ) . file ( 'abc' ) ;
114+ await expect ( getDownloadUrl ( fileRef ) ) . to . eventually . eq (
115+ `https://firebasestorage.googleapis.com/v0/b/${ fileRef . bucket . name } /o/${ encodeURIComponent ( fileRef . name ) } ?alt=media&token=${ downloadTokens [ 0 ] } `
116+ ) ;
117+ } ) ;
118+ it ( 'should use the emulator host name when either envs are set' , async ( ) => {
119+ const HOST = 'localhost:9091' ;
120+ const envsToCheck = [
121+ { envName : 'FIREBASE_STORAGE_EMULATOR_HOST' , value : HOST } ,
122+ { envName : 'STORAGE_EMULATOR_HOST' , value : `http://${ HOST } ` } ,
123+ ] ;
124+ const downloadTokens = [ 'abc' , 'def' ] ;
125+ sandbox . stub ( StorageUtils , 'getFirebaseMetadata' ) . returns (
126+ Promise . resolve ( {
127+ downloadTokens : downloadTokens . join ( ',' ) ,
128+ } as StorageUtils . FirebaseMetadata )
129+ ) ;
130+ for ( const { envName, value } of envsToCheck ) {
131+
132+ delete process . env . STORAGE_EMULATOR_HOST ;
133+ delete process . env [ envName ] ;
134+ process . env [ envName ] = value ;
135+
136+ // Need to create a new mock app to force `getStorage`'s checking of env vars.
137+ const storage1 = getStorage ( mocks . app ( envName ) ) ;
138+ const fileRef = storage1 . bucket ( 'gs://mock' ) . file ( 'abc' ) ;
139+ await expect ( getDownloadUrl ( fileRef ) ) . to . eventually . eq (
140+ `http://${ HOST } /v0/b/${ fileRef . bucket . name } /o/${ encodeURIComponent (
141+ fileRef . name
142+ ) } ?alt=media&token=${ downloadTokens [ 0 ] } `
143+ ) ;
144+ delete process . env [ envName ] ;
145+ }
146+ } ) ;
72147 } ) ;
73148} ) ;
0 commit comments