From 1a7f6b93b1097869f14238bef4234b75c971b146 Mon Sep 17 00:00:00 2001 From: MichaelVerdon Date: Wed, 11 Jun 2025 08:25:48 +0100 Subject: [PATCH] chore(storage): deprecation warnings for v8 API ahead of future major release --- packages/app/lib/common/index.js | 41 +++ packages/storage/__tests__/storage.test.ts | 253 ++++++++++++++++++- packages/storage/e2e/StorageReference.e2e.js | 13 +- packages/storage/e2e/StorageTask.e2e.js | 174 +++++++------ packages/storage/e2e/helpers.js | 16 +- packages/storage/lib/index.js | 11 +- packages/storage/lib/modular/index.js | 37 +-- 7 files changed, 420 insertions(+), 125 deletions(-) diff --git a/packages/app/lib/common/index.js b/packages/app/lib/common/index.js index ab7e1e64aa..69d6b9efed 100644 --- a/packages/app/lib/common/index.js +++ b/packages/app/lib/common/index.js @@ -269,6 +269,35 @@ const mapOfDeprecationReplacements = { nanoseconds: NO_REPLACEMENT, }, }, + storage: { + default: { + useEmulator: 'connectStorageEmulator()', + ref: 'ref()', + refFromURL: 'refFromURL()', + setMaxOperationRetryTime: 'setMaxOperationRetryTime()', + setMaxUploadRetryTime: 'setMaxUploadRetryTime()', + setMaxDownloadRetryTime: 'setMaxDownloadRetryTime()', + }, + StorageReference: { + delete: 'deleteObject()', + getDownloadURL: 'getDownloadURL()', + getMetadata: 'getMetadata()', + list: 'list()', + listAll: 'listAll()', + updateMetadata: 'updateMetadata()', + put: 'uploadBytesResumable()', + putString: 'uploadString()', + putFile: 'putFile()', + writeToFile: 'writeToFile()', + toString: 'toString()', + child: 'child()', + }, + statics: { + StringFormat: 'StringFormat', + TaskEvent: 'TaskEvent', + TaskState: 'TaskState', + }, + }, }; const modularDeprecationMessage = @@ -332,6 +361,10 @@ function getNamespace(target) { if (target._config && target._config.namespace) { return target._config.namespace; } + if (target.constructor.name === 'StorageReference') { + return 'storage'; + } + const className = target.name ? target.name : target.constructor.name; return Object.keys(mapOfDeprecationReplacements).find(key => { if (mapOfDeprecationReplacements[key][className]) { @@ -349,6 +382,11 @@ function getInstanceName(target) { // module class instance, we use default to store map of deprecated methods return 'default'; } + + if (target.constructor.name === 'StorageReference') { + // if path passed into ref(), it will pass in the arg as target.name + return target.constructor.name; + } if (target.name) { // It's a function which has a name property unlike classes return target.name; @@ -390,6 +428,9 @@ export function createDeprecationProxy(instance) { if (prop === 'CustomProvider') { deprecationConsoleWarning('appCheck', prop, 'statics', false); } + if (prop === 'StringFormat' || prop === 'TaskEvent' || prop === 'TaskState') { + deprecationConsoleWarning('storage', prop, 'statics', false); + } if (prop !== 'setLogLevel') { // we want to capture setLogLevel function call which we do below diff --git a/packages/storage/__tests__/storage.test.ts b/packages/storage/__tests__/storage.test.ts index 74f9e85fc5..58faf37928 100644 --- a/packages/storage/__tests__/storage.test.ts +++ b/packages/storage/__tests__/storage.test.ts @@ -1,4 +1,4 @@ -import { afterAll, beforeAll, describe, expect, it } from '@jest/globals'; +import { afterAll, beforeAll, beforeEach, describe, expect, it, jest } from '@jest/globals'; import storage, { firebase, @@ -30,6 +30,14 @@ import storage, { TaskState, } from '../lib'; +import { + createCheckV9Deprecation, + CheckV9DeprecationFunction, +} from '../../app/lib/common/unitTestUtils'; + +// @ts-ignore test +import FirebaseModule from '../../app/lib/internal/FirebaseModule'; + describe('Storage', function () { describe('namespace', function () { beforeAll(async function () { @@ -196,4 +204,247 @@ describe('Storage', function () { expect(TaskState.SUCCESS).toBeDefined(); }); }); + + describe('test `console.warn` is called for RNFB v8 API & not called for v9 API', function () { + let storageV9Deprecation: CheckV9DeprecationFunction; + let storageRefV9Deprecation: CheckV9DeprecationFunction; + let staticsV9Deprecation: CheckV9DeprecationFunction; + + beforeEach(function () { + storageV9Deprecation = createCheckV9Deprecation(['storage']); + + storageRefV9Deprecation = createCheckV9Deprecation(['storage', 'StorageReference']); + + staticsV9Deprecation = createCheckV9Deprecation(['storage', 'statics']); + + // @ts-ignore test + jest.spyOn(FirebaseModule.prototype, 'native', 'get').mockImplementation(() => { + return new Proxy( + {}, + { + get: (_target, prop) => { + // Handle list operations specially + if (prop === 'list' || prop === 'listAll') { + return jest.fn().mockResolvedValue({ + items: [], + prefixes: [], + nextPageToken: null, + } as never); + } + // Default mock for other operations + return jest.fn().mockResolvedValue({ + source: 'cache', + changes: [], + documents: [], + metadata: {}, + path: 'foo', + } as never); + }, + }, + ); + }); + }); + + describe('Storage', function () { + it('useStorageEmulator()', function () { + const storage = getStorage(); + storageV9Deprecation( + () => connectStorageEmulator(storage, 'localhost', 8080), + () => storage.useEmulator('localhost', 8080), + 'useEmulator', + ); + }); + + it('ref()', function () { + const storage = getStorage(); + storageV9Deprecation( + () => ref(storage, 'foo'), + () => storage.ref('foo'), + 'ref', + ); + }); + + it('refFromURL()', function () { + const storage = firebase.app().storage(); + storageV9Deprecation( + () => refFromURL(storage, 'gs://flutterfire-e2e-tests.appspot.com/flutter-tsts'), + () => storage.refFromURL('gs://flutterfire-e2e-tests.appspot.com/flutter-tsts'), + 'refFromURL', + ); + }); + + it('setMaxOperationRetryTime()', function () { + const storage = firebase.app().storage(); + storageV9Deprecation( + () => setMaxOperationRetryTime(storage, 1000), + () => storage.setMaxOperationRetryTime(1000), + 'setMaxOperationRetryTime', + ); + }); + + it('setMaxUploadRetryTime()', function () { + const storage = firebase.app().storage(); + storageV9Deprecation( + () => setMaxUploadRetryTime(storage, 1000), + () => storage.setMaxUploadRetryTime(1000), + 'setMaxUploadRetryTime', + ); + }); + + it('setMaxDownloadRetryTime()', function () { + const storage = firebase.app().storage(); + storageV9Deprecation( + () => setMaxDownloadRetryTime(storage, 1000), + () => storage.setMaxDownloadRetryTime(1000), + 'setMaxDownloadRetryTime', + ); + }); + + it('delete()', function () { + const storage = firebase.app().storage(); + const storageRef = storage.ref('foo'); + storageRefV9Deprecation( + () => deleteObject(storageRef), + () => storageRef.delete(), + 'delete', + ); + }); + + it('getDownloadURL()', function () { + const storage = firebase.app().storage(); + const storageRef = storage.ref('foo'); + storageRefV9Deprecation( + () => getDownloadURL(storageRef), + () => storageRef.getDownloadURL(), + 'getDownloadURL', + ); + }); + + it('getMetadata()', function () { + const storage = firebase.app().storage(); + const storageRef = storage.ref('foo'); + storageRefV9Deprecation( + () => getMetadata(storageRef), + () => storageRef.getMetadata(), + 'getMetadata', + ); + }); + + it('list()', function () { + const storage = firebase.app().storage(); + const storageRef = storage.ref('foo'); + storageRefV9Deprecation( + () => list(storageRef), + () => storageRef.list(), + 'list', + ); + }); + + it('listAll()', function () { + const storage = firebase.app().storage(); + const storageRef = storage.ref('foo'); + storageRefV9Deprecation( + () => listAll(storageRef), + () => storageRef.listAll(), + 'listAll', + ); + }); + + it('updateMetadata()', function () { + const storage = firebase.app().storage(); + const storageRef = storage.ref('foo'); + storageRefV9Deprecation( + () => updateMetadata(storageRef, {}), + () => storageRef.updateMetadata({}), + 'updateMetadata', + ); + }); + + it('put()', function () { + const storage = firebase.app().storage(); + const storageRef = storage.ref('foo'); + storageRefV9Deprecation( + () => uploadBytesResumable(storageRef, new Blob(['foo']), {}), + () => storageRef.put(new Blob(['foo']), {}), + 'put', + ); + }); + + it('putString()', function () { + const storage = firebase.app().storage(); + const storageRef = storage.ref('foo'); + storageRefV9Deprecation( + () => uploadString(storageRef, 'foo', StringFormat.RAW), + () => storageRef.putString('foo', StringFormat.RAW), + 'putString', + ); + }); + + it('putFile()', function () { + const storage = firebase.app().storage(); + const storageRef = storage.ref('foo'); + storageRefV9Deprecation( + () => putFile(storageRef, 'foo', {}), + () => storageRef.putFile('foo', {}), + 'putFile', + ); + }); + + it('writeToFile()', function () { + const storage = firebase.app().storage(); + const storageRef = storage.ref('foo'); + storageRefV9Deprecation( + () => writeToFile(storageRef, 'foo'), + () => storageRef.writeToFile('foo'), + 'writeToFile', + ); + }); + + it('toString()', function () { + const storage = firebase.app().storage(); + const storageRef = storage.ref('foo'); + storageRefV9Deprecation( + () => toString(storageRef), + () => storageRef.toString(), + 'toString', + ); + }); + + it('child()', function () { + const storage = firebase.app().storage(); + const storageRef = storage.ref('foo'); + storageRefV9Deprecation( + () => child(storageRef, 'bar'), + () => storageRef.child('bar'), + 'child', + ); + }); + }); + + describe('statics', function () { + it('StringFormat static', function () { + staticsV9Deprecation( + () => StringFormat.RAW, + () => firebase.storage.StringFormat.RAW, + 'StringFormat', + ); + }); + + it('TaskEvent static', function () { + staticsV9Deprecation( + () => TaskEvent.STATE_CHANGED, + () => firebase.storage.TaskEvent.STATE_CHANGED, + 'TaskEvent', + ); + }); + + it('TaskState static', function () { + staticsV9Deprecation( + () => TaskState.SUCCESS, + () => firebase.storage.TaskState.SUCCESS, + 'TaskState', + ); + }); + }); + }); }); diff --git a/packages/storage/e2e/StorageReference.e2e.js b/packages/storage/e2e/StorageReference.e2e.js index a561087dab..2a8a8fe01e 100644 --- a/packages/storage/e2e/StorageReference.e2e.js +++ b/packages/storage/e2e/StorageReference.e2e.js @@ -110,7 +110,6 @@ describe('storage() -> StorageReference', function () { const storageReference = firebase.storage().ref(`${PATH}/deleteMe.txt`); await storageReference.putString('Delete File'); await storageReference.delete(); - try { await storageReference.getMetadata(); return Promise.reject(new Error('Did not throw')); @@ -717,16 +716,16 @@ describe('storage() -> StorageReference', function () { // Same bucket defined in app.js when setting up emulator it('should write a file to the second storage bucket', async function () { - const { ref } = storageModular; + const { ref, uploadString } = storageModular; // "only-second-bucket" is not an allowable path on live project for either bucket const storageReference = ref(secondStorage, 'only-second-bucket/ok.txt'); - await storageReference.putString('Hello World'); + await uploadString(storageReference, 'Hello World'); }); it('should throw exception on path not allowed on second bucket security rules', async function () { - const { ref } = storageModular; + const { ref, uploadString } = storageModular; // "react-native-firebase-testing" is not an allowed on second bucket, only "ony-second-bucket" const storageReference = ref( @@ -735,7 +734,7 @@ describe('storage() -> StorageReference', function () { ); try { - await storageReference.putString('Hello World'); + await uploadString(storageReference, 'Hello World'); return Promise.reject(new Error('Did not throw')); } catch (error) { error.code.should.equal('storage/unauthorized'); @@ -974,10 +973,10 @@ describe('storage() -> StorageReference', function () { describe('list', function () { it('should return list results', async function () { - const { getStorage, ref } = storageModular; + const { getStorage, ref, list } = storageModular; const storageReference = ref(getStorage(), `${PATH}/list`); - const result = await storageReference.list(); + const result = await list(storageReference); result.constructor.name.should.eql('StorageListResult'); result.should.have.property('nextPageToken'); diff --git a/packages/storage/e2e/StorageTask.e2e.js b/packages/storage/e2e/StorageTask.e2e.js index 781a1b1652..97a99e4b80 100644 --- a/packages/storage/e2e/StorageTask.e2e.js +++ b/packages/storage/e2e/StorageTask.e2e.js @@ -348,14 +348,15 @@ describe('storage() -> StorageTask', function () { }); it('should have access to the snapshot values outside of the event subscriber', async function () { - const uploadTaskSnapshot = firebase - .storage() - .ref(`${PATH}/putStringBlob.json`) - .putString('Just a string to put in a file for upload'); + const { getStorage, ref, uploadString, TaskState } = storageModular; + const uploadTaskSnapshot = uploadString( + ref(getStorage(), `${PATH}/putStringBlob.json`), + 'Just a string to put in a file for upload', + ); const { resolve, promise } = Promise.defer(); uploadTaskSnapshot.on('state_changed', { next: snapshot => { - if (snapshot.state === firebase.storage.TaskState.SUCCESS) { + if (snapshot.state === TaskState.SUCCESS) { snapshotProperties(snapshot); resolve(); } @@ -802,77 +803,78 @@ describe('storage() -> StorageTask', function () { it('downloads a file', async function () { if (Platform.other) return; - const { getStorage, ref } = storageModular; + const { getStorage, ref, writeToFile, TaskState } = storageModular; - const meta = await ref(getStorage(), `${PATH}/list/file1.txt`).writeToFile( + const meta = await writeToFile( + ref(getStorage(), `${PATH}/list/file1.txt`), `${firebase.utils.FilePath.DOCUMENT_DIRECTORY}/file1.txt`, ); - meta.state.should.eql(firebase.storage.TaskState.SUCCESS); + meta.state.should.eql(TaskState.SUCCESS); meta.bytesTransferred.should.eql(meta.totalBytes); }); }); describe('putString()', function () { it('uploads a raw string', async function () { - const { getStorage, ref, uploadString } = storageModular; + const { getStorage, ref, uploadString, StringFormat, TaskState } = storageModular; const jsonDerulo = JSON.stringify({ foo: 'bar' }); const uploadTaskSnapshot = await uploadString( ref(getStorage(), `${PATH}/putString.json`), jsonDerulo, - firebase.storage.StringFormat.RAW, + StringFormat.RAW, { contentType: 'application/json', }, ); - uploadTaskSnapshot.state.should.eql(firebase.storage.TaskState.SUCCESS); + uploadTaskSnapshot.state.should.eql(TaskState.SUCCESS); uploadTaskSnapshot.bytesTransferred.should.eql(uploadTaskSnapshot.totalBytes); uploadTaskSnapshot.metadata.should.be.an.Object(); }); it('uploads a data_url formatted string', async function () { - const { getStorage, ref, uploadString } = storageModular; + const { getStorage, ref, uploadString, StringFormat, TaskState } = storageModular; const dataUrl = 'data:application/json;base64,eyJmb28iOiJiYXNlNjQifQ=='; const uploadTaskSnapshot = await uploadString( ref(getStorage(), `${PATH}/putStringDataURL.json`), dataUrl, - firebase.storage.StringFormat.DATA_URL, + StringFormat.DATA_URL, ); - uploadTaskSnapshot.state.should.eql(firebase.storage.TaskState.SUCCESS); + uploadTaskSnapshot.state.should.eql(TaskState.SUCCESS); uploadTaskSnapshot.bytesTransferred.should.eql(uploadTaskSnapshot.totalBytes); uploadTaskSnapshot.metadata.should.be.an.Object(); }); it('uploads a url encoded data_url formatted string', async function () { - const { getStorage, ref, uploadString } = storageModular; + const { getStorage, ref, uploadString, StringFormat, TaskState } = storageModular; const dataUrl = 'data:text/html,%3Ch1%3EHello%2C%20World!%3C%2Fh1%3E'; const uploadTaskSnapshot = await uploadString( ref(getStorage(), `${PATH}/helloWorld.html`), dataUrl, - firebase.storage.StringFormat.DATA_URL, + StringFormat.DATA_URL, ); - uploadTaskSnapshot.state.should.eql(firebase.storage.TaskState.SUCCESS); + uploadTaskSnapshot.state.should.eql(TaskState.SUCCESS); uploadTaskSnapshot.bytesTransferred.should.eql(uploadTaskSnapshot.totalBytes); uploadTaskSnapshot.metadata.should.be.an.Object(); }); it('when using data_url it still sets the content type if metadata is provided', async function () { - const { getStorage, ref, uploadString } = storageModular; + const { getStorage, ref, uploadString, StringFormat, TaskState } = storageModular; const dataUrl = 'data:text/html,%3Ch1%3EHello%2C%20World!%3C%2Fh1%3E'; const uploadTaskSnapshot = await uploadString( ref(getStorage(), `${PATH}/helloWorld.html`), dataUrl, - firebase.storage.StringFormat.DATA_URL, + StringFormat.DATA_URL, { // TODO(salakar) automate test metadata is preserved when auto setting mediatype customMetadata: { @@ -881,56 +883,52 @@ describe('storage() -> StorageTask', function () { }, ); - uploadTaskSnapshot.state.should.eql(firebase.storage.TaskState.SUCCESS); + uploadTaskSnapshot.state.should.eql(TaskState.SUCCESS); uploadTaskSnapshot.bytesTransferred.should.eql(uploadTaskSnapshot.totalBytes); uploadTaskSnapshot.metadata.should.be.an.Object(); }); it('uploads a base64 string', async function () { - const { getStorage, ref, uploadString } = storageModular; + const { getStorage, ref, uploadString, StringFormat, TaskState } = storageModular; const base64String = 'eyJmb28iOiJiYXNlNjQifQ=='; const uploadTaskSnapshot = await uploadString( ref(getStorage(), `${PATH}/putStringBase64.json`), base64String, - firebase.storage.StringFormat.BASE64, + StringFormat.BASE64, { contentType: 'application/json', }, ); - uploadTaskSnapshot.state.should.eql(firebase.storage.TaskState.SUCCESS); + uploadTaskSnapshot.state.should.eql(TaskState.SUCCESS); uploadTaskSnapshot.bytesTransferred.should.eql(uploadTaskSnapshot.totalBytes); uploadTaskSnapshot.metadata.should.be.an.Object(); }); it('uploads a base64url string', async function () { - const { getStorage, ref, uploadString } = storageModular; + const { getStorage, ref, uploadString, StringFormat, TaskState } = storageModular; const base64UrlString = 'eyJmb28iOiJiYXNlNjQifQ'; const uploadTaskSnapshot = await uploadString( ref(getStorage(), `${PATH}/putStringBase64Url.json`), base64UrlString, - firebase.storage.StringFormat.BASE64URL, + StringFormat.BASE64URL, { contentType: 'application/json', }, ); - uploadTaskSnapshot.state.should.eql(firebase.storage.TaskState.SUCCESS); + uploadTaskSnapshot.state.should.eql(TaskState.SUCCESS); uploadTaskSnapshot.bytesTransferred.should.eql(uploadTaskSnapshot.totalBytes); uploadTaskSnapshot.metadata.should.be.an.Object(); }); it('throws an error on invalid data_url', async function () { - const { getStorage, ref, uploadString } = storageModular; + const { getStorage, ref, uploadString, StringFormat } = storageModular; const dataUrl = ''; try { - await uploadString( - ref(getStorage(), '/a.b'), - dataUrl, - firebase.storage.StringFormat.DATA_URL, - ); + await uploadString(ref(getStorage(), '/a.b'), dataUrl, StringFormat.DATA_URL); return Promise.reject(new Error('Did not throw!')); } catch (error) { @@ -940,9 +938,9 @@ describe('storage() -> StorageTask', function () { }); it('throws if string arg is not a valid string', async function () { - const { getStorage, ref, uploadString } = storageModular; + const { getStorage, ref, uploadString, StringFormat } = storageModular; try { - await uploadString(ref(getStorage(), '/a.b'), 1, 'base64'); + await uploadString(ref(getStorage(), '/a.b'), 1, StringFormat.BASE64); return Promise.reject(new Error('Did not throw!')); } catch (error) { error.message.should.containEql("'string' expects a string value"); @@ -962,9 +960,9 @@ describe('storage() -> StorageTask', function () { }); it('throws an error if metadata is not an object', async function () { - const { getStorage, ref, uploadString } = storageModular; + const { getStorage, ref, uploadString, StringFormat } = storageModular; try { - await uploadString(ref(getStorage(), '/a.b'), 'fooby', 'raw', 1234); + await uploadString(ref(getStorage(), '/a.b'), 'fooby', StringFormat.RAW, 1234); return Promise.reject(new Error('Did not throw!')); } catch (error) { error.message.should.containEql('must be an object value if provided'); @@ -976,7 +974,7 @@ describe('storage() -> StorageTask', function () { describe('put()', function () { // TODO flakey test, RN JSTimer exception sometimes xit('uploads a Blob', async function () { - const { getStorage, ref, uploadBytesResumable } = storageModular; + const { getStorage, ref, uploadBytesResumable, TaskState } = storageModular; const jsonDerulo = JSON.stringify({ foo: 'bar' }); const bob = new Blob([jsonDerulo], { @@ -988,13 +986,13 @@ describe('storage() -> StorageTask', function () { bob, ); - uploadTaskSnapshot.state.should.eql(firebase.storage.TaskState.SUCCESS); + uploadTaskSnapshot.state.should.eql(TaskState.SUCCESS); uploadTaskSnapshot.bytesTransferred.should.eql(uploadTaskSnapshot.totalBytes); uploadTaskSnapshot.metadata.should.be.an.Object(); }); it('uploads an ArrayBuffer', async function () { - const { getStorage, ref, uploadBytesResumable } = storageModular; + const { getStorage, ref, uploadBytesResumable, TaskState } = storageModular; const jsonDerulo = JSON.stringify({ foo: 'bar' }); const arrayBuffer = new ArrayBuffer(jsonDerulo.length); @@ -1011,13 +1009,13 @@ describe('storage() -> StorageTask', function () { }, ); - uploadTaskSnapshot.state.should.eql(firebase.storage.TaskState.SUCCESS); + uploadTaskSnapshot.state.should.eql(TaskState.SUCCESS); uploadTaskSnapshot.bytesTransferred.should.eql(uploadTaskSnapshot.totalBytes); uploadTaskSnapshot.metadata.should.be.an.Object(); }); it('uploads an Uint8Array', async function () { - const { getStorage, ref, uploadBytesResumable } = storageModular; + const { getStorage, ref, uploadBytesResumable, TaskState } = storageModular; const jsonDerulo = JSON.stringify({ foo: 'bar' }); const arrayBuffer = new ArrayBuffer(jsonDerulo.length); @@ -1035,7 +1033,7 @@ describe('storage() -> StorageTask', function () { }, ); - uploadTaskSnapshot.state.should.eql(firebase.storage.TaskState.SUCCESS); + uploadTaskSnapshot.state.should.eql(TaskState.SUCCESS); uploadTaskSnapshot.bytesTransferred.should.eql(uploadTaskSnapshot.totalBytes); uploadTaskSnapshot.metadata.should.be.an.Object(); }); @@ -1143,13 +1141,13 @@ describe('storage() -> StorageTask', function () { }); it('uploads a file without read permission', async function () { - const { getStorage, ref, uploadString } = storageModular; + const { getStorage, ref, uploadString, TaskState } = storageModular; const uploadTaskSnapshot = await uploadString( ref(getStorage(), WRITE_ONLY_NAME), 'Just a string to put in a file for upload', ); - uploadTaskSnapshot.state.should.eql(firebase.storage.TaskState.SUCCESS); + uploadTaskSnapshot.state.should.eql(TaskState.SUCCESS); uploadTaskSnapshot.bytesTransferred.should.eql(uploadTaskSnapshot.totalBytes); uploadTaskSnapshot.metadata.should.be.an.Object(); }); @@ -1168,7 +1166,7 @@ describe('storage() -> StorageTask', function () { }); it('should have access to the snapshot values outside of the event subscriber', async function () { - const { getStorage, ref, uploadString } = storageModular; + const { getStorage, ref, uploadString, TaskState } = storageModular; const uploadTaskSnapshot = uploadString( ref(getStorage(), `${PATH}/putStringBlob.json`), @@ -1178,7 +1176,7 @@ describe('storage() -> StorageTask', function () { const { resolve, promise } = Promise.defer(); uploadTaskSnapshot.on('state_changed', { next: snapshot => { - if (snapshot.state === firebase.storage.TaskState.SUCCESS) { + if (snapshot.state === TaskState.SUCCESS) { snapshotProperties(snapshot); resolve(); } @@ -1199,7 +1197,7 @@ describe('storage() -> StorageTask', function () { }); it('throws an Error if event is invalid', async function () { - const { getStorage, ref, putFile } = storageModular; + const { getStorage, ref, putFile, TaskEvent } = storageModular; const storageReference = ref(getStorage(), `${PATH}/ok.jpeg`); try { @@ -1209,18 +1207,18 @@ describe('storage() -> StorageTask', function () { return Promise.reject(new Error('Did not error!')); } catch (error) { error.message.should.containEql( - "event argument must be a string with a value of 'state_changed'", + `event argument must be a string with a value of '${TaskEvent.STATE_CHANGED}'`, ); return Promise.resolve(); } }); it('throws an Error if nextOrObserver is invalid', async function () { - const { getStorage, ref, putFile } = storageModular; + const { getStorage, ref, putFile, TaskEvent } = storageModular; const storageReference = ref(getStorage(), `${PATH}/ok.jpeg`); try { const task = putFile(storageReference, 'abc'); - task.on('state_changed', 'not a fn'); + task.on(TaskEvent.STATE_CHANGED, 'not a fn'); return Promise.reject(new Error('Did not error!')); } catch (error) { error.message.should.containEql("'nextOrObserver' must be a Function, an Object or Null"); @@ -1230,13 +1228,13 @@ describe('storage() -> StorageTask', function () { it('observer calls error callback', async function () { if (Platform.other) return; // TODO refactor to use putString instead of writeToFile/putFile - const { getStorage, ref, putFile } = storageModular; + const { getStorage, ref, putFile, TaskEvent } = storageModular; const storageRef = ref(getStorage(), `${PATH}/uploadOk.jpeg`); const { resolve, promise } = Promise.defer(); const path = `${firebase.utils.FilePath.DOCUMENT_DIRECTORY}/notFoundFooFile.bar`; const task = putFile(storageRef, path); - task.on('state_changed', { + task.on(TaskEvent.STATE_CHANGED, { error: error => { error.code.should.containEql('storage/file-not-found'); resolve(); @@ -1254,7 +1252,7 @@ describe('storage() -> StorageTask', function () { it('observer: calls next callback', async function () { if (Platform.other) return; // TODO refactor to use putString instead of writeToFile - const { getStorage, ref, writeToFile } = storageModular; + const { getStorage, ref, writeToFile, TaskState } = storageModular; const storageRef = ref(getStorage(), `${PATH}/ok.jpeg`); const { resolve, promise } = Promise.defer(); @@ -1262,7 +1260,7 @@ describe('storage() -> StorageTask', function () { const task = writeToFile(storageRef, path); task.on('state_changed', { next: snapshot => { - if (snapshot.state === firebase.storage.TaskState.SUCCESS) { + if (snapshot.state === TaskState.SUCCESS) { resolve(); } }, @@ -1273,7 +1271,7 @@ describe('storage() -> StorageTask', function () { it('observer: calls completion callback', async function () { if (Platform.other) return; // TODO refactor to use putString instead of writeToFile - const { getStorage, ref, writeToFile } = storageModular; + const { getStorage, ref, writeToFile, TaskState } = storageModular; const storageRef = ref(getStorage(), `${PATH}/ok.jpeg`); const { resolve, promise } = Promise.defer(); @@ -1282,7 +1280,7 @@ describe('storage() -> StorageTask', function () { task.on('state_changed', { complete: snapshot => { - snapshot.state.should.equal(firebase.storage.TaskState.SUCCESS); + snapshot.state.should.equal(TaskState.SUCCESS); resolve(); }, }); @@ -1320,7 +1318,7 @@ describe('storage() -> StorageTask', function () { it('calls next callback', async function () { if (Platform.other) return; // TODO refactor to use putString instead of writeToFile - const { getStorage, ref, writeToFile } = storageModular; + const { getStorage, ref, writeToFile, TaskState } = storageModular; const storageRef = ref(getStorage(), `${PATH}/ok.jpeg`); const { resolve, promise } = Promise.defer(); @@ -1328,7 +1326,7 @@ describe('storage() -> StorageTask', function () { const task = writeToFile(storageRef, path); task.on('state_changed', snapshot => { - if (snapshot.state === firebase.storage.TaskState.SUCCESS) { + if (snapshot.state === TaskState.SUCCESS) { resolve(); } }); @@ -1339,14 +1337,14 @@ describe('storage() -> StorageTask', function () { it('calls completion callback', async function () { if (Platform.other) return; // TODO refactor to use putString instead of writeToFile - const { getStorage, ref, writeToFile } = storageModular; + const { getStorage, ref, writeToFile, TaskState } = storageModular; const storageRef = ref(getStorage(), `${PATH}/ok.jpeg`); const { resolve, promise } = Promise.defer(); const path = `${firebase.utils.FilePath.DOCUMENT_DIRECTORY}/onDownload.jpeg`; const task = writeToFile(storageRef, path); task.on('state_changed', null, null, snapshot => { - snapshot.state.should.equal(firebase.storage.TaskState.SUCCESS); + snapshot.state.should.equal(TaskState.SUCCESS); resolve(); }); @@ -1356,7 +1354,7 @@ describe('storage() -> StorageTask', function () { it('returns a subscribe fn', async function () { if (Platform.other) return; // TODO refactor to use putString instead of writeToFile - const { getStorage, ref, writeToFile } = storageModular; + const { getStorage, ref, writeToFile, TaskState } = storageModular; const storageRef = ref(getStorage(), `${PATH}/ok.jpeg`); const { resolve, promise } = Promise.defer(); const path = `${firebase.utils.FilePath.DOCUMENT_DIRECTORY}/onDownload.jpeg`; @@ -1365,7 +1363,7 @@ describe('storage() -> StorageTask', function () { const subscribe = task.on('state_changed'); subscribe(null, null, snapshot => { - if (snapshot.state === firebase.storage.TaskState.SUCCESS) { + if (snapshot.state === TaskState.SUCCESS) { resolve(); } }); @@ -1376,7 +1374,7 @@ describe('storage() -> StorageTask', function () { it('returns a subscribe fn supporting observer usage syntax', async function () { if (Platform.other) return; // TODO refactor to use putString instead of writeToFile - const { getStorage, ref, writeToFile } = storageModular; + const { getStorage, ref, writeToFile, TaskState } = storageModular; const storageRef = ref(getStorage(), `${PATH}/ok.jpeg`); const { resolve, promise } = Promise.defer(); const path = `${firebase.utils.FilePath.DOCUMENT_DIRECTORY}/onDownload.jpeg`; @@ -1386,7 +1384,7 @@ describe('storage() -> StorageTask', function () { subscribe({ complete: snapshot => { - if (snapshot.state === firebase.storage.TaskState.SUCCESS) { + if (snapshot.state === TaskState.SUCCESS) { resolve(); } }, @@ -1398,7 +1396,7 @@ describe('storage() -> StorageTask', function () { it('listens to download state', async function () { if (Platform.other) return; // TODO refactor to use putString instead of writeToFile - const { getStorage, ref, writeToFile } = storageModular; + const { getStorage, ref, writeToFile, TaskState } = storageModular; const storageRef = ref(getStorage(), `${PATH}/ok.jpeg`); const { resolve, reject, promise } = Promise.defer(); const path = `${firebase.utils.FilePath.DOCUMENT_DIRECTORY}/onDownload.gif`; @@ -1406,7 +1404,7 @@ describe('storage() -> StorageTask', function () { const unsubscribe = writeToFile(storageRef, path).on( 'state_changed', snapshot => { - if (snapshot.state === firebase.storage.TaskState.SUCCESS) { + if (snapshot.state === TaskState.SUCCESS) { resolve(); } }, @@ -1421,7 +1419,7 @@ describe('storage() -> StorageTask', function () { it('listens to upload state', async function () { if (Platform.other) return; // TODO refactor to use putString instead of putFile - const { getStorage, ref, putFile } = storageModular; + const { getStorage, ref, putFile, TaskState } = storageModular; const storageRef = ref(getStorage(), `${PATH}/ok.jpeg`); const { resolve, reject, promise } = Promise.defer(); const path = `${firebase.utils.FilePath.DOCUMENT_DIRECTORY}/onDownload.gif`; @@ -1429,7 +1427,7 @@ describe('storage() -> StorageTask', function () { const unsubscribe = putFile(storageRef, path).on( 'state_changed', snapshot => { - if (snapshot.state === firebase.storage.TaskState.SUCCESS) { + if (snapshot.state === TaskState.SUCCESS) { resolve(); } }, @@ -1447,7 +1445,7 @@ describe('storage() -> StorageTask', function () { xdescribe('pause() resume()', function () { it('successfully pauses and resumes an upload', async function testRunner() { this.timeout(100 * 1000); - const { getStorage, ref, writeToFile, putFile } = storageModular; + const { getStorage, ref, writeToFile, putFile, TaskState } = storageModular; const storageRef = ref(getStorage(), Platform.ios ? '/smallFileTest.png' : '/cat.gif'); await writeToFile( @@ -1469,7 +1467,7 @@ describe('storage() -> StorageTask', function () { 'state_changed', snapshot => { // 1) pause when we receive first running event - if (snapshot.state === firebase.storage.TaskState.RUNNING && !hadRunningStatus) { + if (snapshot.state === TaskState.RUNNING && !hadRunningStatus) { hadRunningStatus = true; if (Platform.android) { uploadTask.pause(); @@ -1482,14 +1480,14 @@ describe('storage() -> StorageTask', function () { } // 2) resume when we receive first paused event - if (snapshot.state === firebase.storage.TaskState.PAUSED) { + if (snapshot.state === TaskState.PAUSED) { hadPausedStatus = true; uploadTask.resume(); } // 3) track that we resumed on 2nd running status whilst paused if ( - snapshot.state === firebase.storage.TaskState.RUNNING && + snapshot.state === TaskState.RUNNING && hadRunningStatus && hadPausedStatus && !hadResumedStatus @@ -1498,7 +1496,7 @@ describe('storage() -> StorageTask', function () { } // 4) finally confirm we received all statuses - if (snapshot.state === firebase.storage.TaskState.SUCCESS) { + if (snapshot.state === TaskState.SUCCESS) { should.equal(hadRunningStatus, true); should.equal(hadPausedStatus, true); should.equal(hadResumedStatus, true); @@ -1515,7 +1513,7 @@ describe('storage() -> StorageTask', function () { it('successfully pauses and resumes a download', async function () { if (Platform.other) return; // TODO refactor to use putString instead of writeToFile - const { getStorage, ref, writeToFile } = storageModular; + const { getStorage, ref, writeToFile, TaskState } = storageModular; const storageRef = ref(getStorage(), Platform.ios ? '/1mbTestFile.gif' : '/cat.gif'); const { resolve, reject, promise } = Promise.defer(); @@ -1535,20 +1533,20 @@ describe('storage() -> StorageTask', function () { snapshot => { // TODO(salakar) validate snapshot props // 1) pause when we receive first running event - if (snapshot.state === firebase.storage.TaskState.RUNNING && !hadRunningStatus) { + if (snapshot.state === TaskState.RUNNING && !hadRunningStatus) { hadRunningStatus = true; downloadTask.pause(); } // 2) resume when we receive first paused event - if (snapshot.state === firebase.storage.TaskState.PAUSED) { + if (snapshot.state === TaskState.PAUSED) { hadPausedStatus = true; downloadTask.resume(); } // 3) track that we resumed on 2nd running status whilst paused if ( - snapshot.state === firebase.storage.TaskState.RUNNING && + snapshot.state === TaskState.RUNNING && hadRunningStatus && hadPausedStatus && !hadResumedStatus @@ -1557,7 +1555,7 @@ describe('storage() -> StorageTask', function () { } // 4) finally confirm we received all statuses - if (snapshot.state === firebase.storage.TaskState.SUCCESS) { + if (snapshot.state === TaskState.SUCCESS) { should.equal(hadRunningStatus, true); should.equal(hadPausedStatus, true); should.equal(hadResumedStatus, true); @@ -1576,7 +1574,7 @@ describe('storage() -> StorageTask', function () { describe('cancel()', function () { // TODO stage a file big enough to test upload cancel xit('successfully cancels an upload', async function () { - const { getStorage, ref, writeToFile, putFile } = storageModular; + const { getStorage, ref, writeToFile, putFile, TaskState } = storageModular; const storageRef = ref(getStorage(), Platform.ios ? '/1mbTestFile.gif' : '/cat.gif'); await writeToFile( storageRef, @@ -1598,22 +1596,22 @@ describe('storage() -> StorageTask', function () { snapshot => { // TODO(salakar) validate snapshot props // 1) cancel it when we receive first running event - if (snapshot.state === firebase.storage.TaskState.RUNNING && !hadRunningStatus) { + if (snapshot.state === TaskState.RUNNING && !hadRunningStatus) { hadRunningStatus = true; uploadTask.cancel(); } // 2) confirm cancellation - if (snapshot.state === firebase.storage.TaskState.CANCELLED) { + if (snapshot.state === TaskState.CANCELLED) { should.equal(hadRunningStatus, true); hadCancelledStatus = true; } - if (snapshot.state === firebase.storage.TaskState.ERROR) { + if (snapshot.state === TaskState.ERROR) { throw new Error('Should not error if cancelled?'); } - if (snapshot.state === firebase.storage.TaskState.SUCCESS) { + if (snapshot.state === TaskState.SUCCESS) { reject(new Error('UploadTask did not cancel!')); } }, @@ -1632,7 +1630,7 @@ describe('storage() -> StorageTask', function () { // TODO stage a file big enough to cancel a download xit('successfully cancels a download', async function () { - const { getStorage, ref, writeToFile } = storageModular; + const { getStorage, ref, writeToFile, TaskState } = storageModular; const storageRef = ref(getStorage(), '/1mbTestFile.gif'); await Utils.sleep(10000); const { resolve, reject, promise } = Promise.defer(); @@ -1647,22 +1645,22 @@ describe('storage() -> StorageTask', function () { snapshot => { // TODO(salakar) validate snapshot props // 1) cancel it when we receive first running event - if (snapshot.state === firebase.storage.TaskState.RUNNING && !hadRunningStatus) { + if (snapshot.state === TaskState.RUNNING && !hadRunningStatus) { hadRunningStatus = true; downloadTask.cancel(); } // 2) confirm cancellation - if (snapshot.state === firebase.storage.TaskState.CANCELLED) { + if (snapshot.state === TaskState.CANCELLED) { should.equal(hadRunningStatus, true); hadCancelledStatus = true; } - if (snapshot.state === firebase.storage.TaskState.ERROR) { + if (snapshot.state === TaskState.ERROR) { throw new Error('Should not error if cancelled?'); } - if (snapshot.state === firebase.storage.TaskState.SUCCESS) { + if (snapshot.state === TaskState.SUCCESS) { reject(new Error('DownloadTask did not cancel!')); } }, diff --git a/packages/storage/e2e/helpers.js b/packages/storage/e2e/helpers.js index e0eecf7f85..96871b8ee5 100644 --- a/packages/storage/e2e/helpers.js +++ b/packages/storage/e2e/helpers.js @@ -8,20 +8,20 @@ const WRITE_ONLY_NAME = 'writeOnly.jpeg'; exports.seed = async function seed(path) { let leakDetectCurrent = globalThis.RNFBDebugInTestLeakDetection; globalThis.RNFBDebugInTestLeakDetection = false; - const { getStorage, ref } = storageModular; + const { getStorage, ref, uploadString, StringFormat } = storageModular; try { // Add a write only file - await ref(getStorage(), WRITE_ONLY_NAME).putString('Write Only'); + await uploadString(ref(getStorage(), WRITE_ONLY_NAME), 'Write Only'); - // Setup list items - Future.wait not working... - await ref(getStorage(), `${path}/list/file1.txt`).putString('File 1', 'raw', { + await uploadString(ref(getStorage(), `${path}/list/file1.txt`), 'File 1', StringFormat.RAW, { contentType: 'text/plain', }); - await ref(getStorage(), `${path}/list/file2.txt`).putString('File 2'); - await ref(getStorage(), `${path}/list/file3.txt`).putString('File 3'); - await ref(getStorage(), `${path}/list/file4.txt`).putString('File 4'); - await ref(getStorage(), `${path}/list/nested/file5.txt`).putString('File 5'); + + await uploadString(ref(getStorage(), `${path}/list/file2.txt`), 'File 2'); + await uploadString(ref(getStorage(), `${path}/list/file3.txt`), 'File 3'); + await uploadString(ref(getStorage(), `${path}/list/file4.txt`), 'File 4'); + await uploadString(ref(getStorage(), `${path}/list/nested/file5.txt`), 'File 5'); } catch (e) { // eslint-disable-next-line no-console console.error('unable to seed storage service with test fixtures'); diff --git a/packages/storage/lib/index.js b/packages/storage/lib/index.js index 2fecc42c0a..37e18b44e9 100644 --- a/packages/storage/lib/index.js +++ b/packages/storage/lib/index.js @@ -15,7 +15,13 @@ * */ -import { isAndroid, isNumber, isString } from '@react-native-firebase/app/lib/common'; +import { + isAndroid, + isNumber, + isString, + createDeprecationProxy, +} from '@react-native-firebase/app/lib/common'; + import { setReactNativeModule } from '@react-native-firebase/app/lib/internal/nativeModule'; import { createModuleNamespace, @@ -91,8 +97,7 @@ class FirebaseStorageModule extends FirebaseModule { if (!isString(path)) { throw new Error("firebase.storage().ref(*) 'path' must be a string value."); } - - return new StorageReference(this, path); + return createDeprecationProxy(new StorageReference(this, path)); } /** diff --git a/packages/storage/lib/modular/index.js b/packages/storage/lib/modular/index.js index 5b6992ec8b..99c5d0716d 100644 --- a/packages/storage/lib/modular/index.js +++ b/packages/storage/lib/modular/index.js @@ -29,6 +29,7 @@ */ import { getApp } from '@react-native-firebase/app'; +import { MODULAR_DEPRECATION_ARG } from '@react-native-firebase/app/lib/common'; /** * Returns a Storage instance for the given app. @@ -61,7 +62,7 @@ export function getStorage(app, bucketUrl) { * @returns {void} */ export function connectStorageEmulator(storage, host, port, options) { - return storage.useEmulator(host, port, options); + return storage.useEmulator.call(storage, host, port, options, MODULAR_DEPRECATION_ARG); } /** @@ -72,7 +73,7 @@ export function connectStorageEmulator(storage, host, port, options) { * @returns {Reference} */ export function ref(storage, path) { - return storage.ref(path); + return storage.ref.call(storage, path, MODULAR_DEPRECATION_ARG); } /** @@ -81,7 +82,7 @@ export function ref(storage, path) { * @returns {Promise} */ export function deleteObject(storageRef) { - return storageRef.delete(); + return storageRef.delete.call(storageRef, MODULAR_DEPRECATION_ARG); } /** @@ -111,7 +112,7 @@ export function getBytes(storageRef, maxDownloadSizeBytes) { * @returns {Promise} */ export function getDownloadURL(storageRef) { - return storageRef.getDownloadURL(); + return storageRef.getDownloadURL.call(storageRef, MODULAR_DEPRECATION_ARG); } /** @@ -120,7 +121,7 @@ export function getDownloadURL(storageRef) { * @returns {Promise} */ export function getMetadata(storageRef) { - return storageRef.getMetadata(); + return storageRef.getMetadata.call(storageRef, MODULAR_DEPRECATION_ARG); } /** @@ -141,7 +142,7 @@ export function getStream(storageRef, maxDownloadSizeBytes) { * @returns {Promise} */ export function list(storageRef, options) { - return storageRef.list(options); + return storageRef.list.call(storageRef, options, MODULAR_DEPRECATION_ARG); } /** @@ -150,7 +151,7 @@ export function list(storageRef, options) { * @returns {Promise} */ export function listAll(storageRef) { - return storageRef.listAll(); + return storageRef.listAll.call(storageRef, MODULAR_DEPRECATION_ARG); } /** @@ -160,7 +161,7 @@ export function listAll(storageRef) { * @returns {Promise} */ export function updateMetadata(storageRef, metadata) { - return storageRef.updateMetadata(metadata); + return storageRef.updateMetadata.call(storageRef, metadata, MODULAR_DEPRECATION_ARG); } /** @@ -183,7 +184,7 @@ export async function uploadBytes(storageRef, data, metadata) { * @returns {Task} */ export function uploadBytesResumable(storageRef, data, metadata) { - return storageRef.put(data, metadata); + return storageRef.put.call(storageRef, data, metadata, MODULAR_DEPRECATION_ARG); } /** @@ -195,7 +196,7 @@ export function uploadBytesResumable(storageRef, data, metadata) { * @returns {Task} */ export function uploadString(storageRef, data, format, metadata) { - return storageRef.putString(data, format, metadata); + return storageRef.putString.call(storageRef, data, format, metadata, MODULAR_DEPRECATION_ARG); } // Methods not on the Firebase JS SDK below @@ -207,7 +208,7 @@ export function uploadString(storageRef, data, format, metadata) { * @returns {Reference} */ export function refFromURL(storage, url) { - return storage.refFromURL(url); + return storage.refFromURL.call(storage, url, MODULAR_DEPRECATION_ARG); } /** @@ -217,7 +218,7 @@ export function refFromURL(storage, url) { * @returns {Promise} */ export function setMaxOperationRetryTime(storage, time) { - return storage.setMaxOperationRetryTime(time); + return storage.setMaxOperationRetryTime.call(storage, time, MODULAR_DEPRECATION_ARG); } /** @@ -227,7 +228,7 @@ export function setMaxOperationRetryTime(storage, time) { * @returns {Promise} */ export function setMaxUploadRetryTime(storage, time) { - return storage.setMaxUploadRetryTime(time); + return storage.setMaxUploadRetryTime.call(storage, time, MODULAR_DEPRECATION_ARG); } /** @@ -238,7 +239,7 @@ export function setMaxUploadRetryTime(storage, time) { * @returns {Task} */ export function putFile(storageRef, filePath, metadata) { - return storageRef.putFile(filePath, metadata); + return storageRef.putFile.call(storageRef, filePath, metadata, MODULAR_DEPRECATION_ARG); } /** @@ -248,7 +249,7 @@ export function putFile(storageRef, filePath, metadata) { * @returns {Task} */ export function writeToFile(storageRef, filePath) { - return storageRef.writeToFile(filePath); + return storageRef.writeToFile.call(storageRef, filePath, MODULAR_DEPRECATION_ARG); } /** @@ -257,7 +258,7 @@ export function writeToFile(storageRef, filePath) { * @returns {String} */ export function toString(storageRef) { - return storageRef.toString(); + return storageRef.toString.call(storageRef, MODULAR_DEPRECATION_ARG); } /** @@ -267,7 +268,7 @@ export function toString(storageRef) { * @returns {String} */ export function child(storageRef, path) { - return storageRef.child(path); + return storageRef.child.call(storageRef, path, MODULAR_DEPRECATION_ARG); } /** @@ -277,7 +278,7 @@ export function child(storageRef, path) { * @returns {Promise} */ export function setMaxDownloadRetryTime(storage, time) { - return storage.setMaxDownloadRetryTime(time); + return storage.setMaxDownloadRetryTime.call(storage, time, MODULAR_DEPRECATION_ARG); } export { StringFormat, TaskEvent, TaskState } from '../StorageStatics';