diff --git a/.changeset/config.json b/.changeset/config.json index af95312e25a..6791d5c6557 100644 --- a/.changeset/config.json +++ b/.changeset/config.json @@ -13,6 +13,7 @@ "firebase-namespace-integration-test", "firebase-firestore-integration-test", "firebase-messaging-integration-test", + "firebase-compat-interop-test", "firebase-compat-typings-test", "@firebase/app-exp", "@firebase/analytics-compat", diff --git a/.changeset/fuzzy-teachers-guess.md b/.changeset/fuzzy-teachers-guess.md new file mode 100644 index 00000000000..8c67248724c --- /dev/null +++ b/.changeset/fuzzy-teachers-guess.md @@ -0,0 +1,5 @@ +--- +"@firebase/component": patch +--- + +handle `undefined` correctly from input. diff --git a/integration/compat-interop/analytics.test.ts b/integration/compat-interop/analytics.test.ts new file mode 100644 index 00000000000..637e533286d --- /dev/null +++ b/integration/compat-interop/analytics.test.ts @@ -0,0 +1,35 @@ +/** + * @license + * Copyright 2021 Google LLC + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +import { getModularInstance } from '@firebase/util'; +import { expect } from 'chai'; +import { getAnalytics } from '@firebase/analytics-exp'; +import firebase from '@firebase/app-compat'; +import '@firebase/analytics-compat'; + +import { TEST_PROJECT_CONFIG } from './util'; + +firebase.initializeApp(TEST_PROJECT_CONFIG); + +const compatAnalytics = firebase.analytics(); +const modularAnalytics = getAnalytics(); + +describe('Analytics compat interop', () => { + it('Analytics compat instance references modular Analytics instance', () => { + expect(getModularInstance(compatAnalytics)).to.equal(modularAnalytics); + }); +}); diff --git a/integration/compat-interop/app.test.ts b/integration/compat-interop/app.test.ts new file mode 100644 index 00000000000..4a79c4b5bc3 --- /dev/null +++ b/integration/compat-interop/app.test.ts @@ -0,0 +1,50 @@ +/** + * @license + * Copyright 2021 Google LLC + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +import { getModularInstance } from '@firebase/util'; +import { expect } from 'chai'; +import { getApp, getApps } from '@firebase/app-exp'; +import firebase from '@firebase/app-compat'; + +import { TEST_PROJECT_CONFIG } from './util'; +//TODO: add Storage, Firestore and Database tests once v8 is removed. Currently it's too difficult to set them up in integration tests. +describe('App compat interop', () => { + afterEach(() => { + const deletePromises = []; + for (const app of firebase.apps) { + deletePromises.push(app.delete()); + } + + return Promise.all(deletePromises); + }); + + it('App compat instance references modular App instance', () => { + const compatApp = firebase.initializeApp(TEST_PROJECT_CONFIG); + const modularApp = getApp(); + expect(getModularInstance(compatApp)).to.equal(modularApp); + }); + + it('deleting compat app deletes modular app', async () => { + const compatApp = firebase.initializeApp(TEST_PROJECT_CONFIG); + expect(firebase.apps.length).to.equal(1); + expect(getApps().length).to.equal(1); + + await compatApp.delete(); + expect(firebase.apps.length).to.equal(0); + expect(getApps().length).to.equal(0); + }); +}); diff --git a/integration/compat-interop/auth.test.ts b/integration/compat-interop/auth.test.ts new file mode 100644 index 00000000000..b15b368ed22 --- /dev/null +++ b/integration/compat-interop/auth.test.ts @@ -0,0 +1,49 @@ +/** + * @license + * Copyright 2021 Google LLC + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +import { getModularInstance } from '@firebase/util'; +import { expect } from 'chai'; +import { getAuth, signOut } from '@firebase/auth-exp'; +import firebase from '@firebase/app-compat'; +import '@firebase/auth-compat'; + +import { TEST_PROJECT_CONFIG } from './util'; + +firebase.initializeApp(TEST_PROJECT_CONFIG); + +const compatAuth = firebase.auth(); +const modularAuth = getAuth(); + +describe('Auth compat interop', () => { + it('Auth compat instance references modular Auth instance', () => { + expect(getModularInstance(compatAuth)).to.equal(modularAuth); + }); + + it('Auth compat and modular Auth share the same user state', async () => { + expect(compatAuth.currentUser).to.equal(null); + expect(modularAuth.currentUser).to.equal(null); + const userCred = await compatAuth.signInAnonymously(); + expect(userCred.user?.uid).to.equal(modularAuth.currentUser?.uid); + expect(await userCred.user?.getIdToken()).to.equal( + await modularAuth.currentUser?.getIdToken() + ); + + await signOut(modularAuth); + expect(compatAuth.currentUser).to.equal(null); + expect(modularAuth.currentUser).to.equal(null); + }); +}); diff --git a/integration/compat-interop/functions.test.ts b/integration/compat-interop/functions.test.ts new file mode 100644 index 00000000000..327fd8bde94 --- /dev/null +++ b/integration/compat-interop/functions.test.ts @@ -0,0 +1,35 @@ +/** + * @license + * Copyright 2021 Google LLC + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +import { getModularInstance } from '@firebase/util'; +import { expect } from 'chai'; +import { getFunctions } from '@firebase/functions-exp'; +import firebase from '@firebase/app-compat'; +import '@firebase/functions-compat'; + +import { TEST_PROJECT_CONFIG } from './util'; + +firebase.initializeApp(TEST_PROJECT_CONFIG); + +const compatFunction = firebase.functions(); +const modularFunctions = getFunctions(); + +describe('Functions compat interop', () => { + it('Functions compat instance references modular Functions instance', () => { + expect(getModularInstance(compatFunction)).to.equal(modularFunctions); + }); +}); diff --git a/integration/compat-interop/karma.conf.js b/integration/compat-interop/karma.conf.js new file mode 100644 index 00000000000..6dde3b61344 --- /dev/null +++ b/integration/compat-interop/karma.conf.js @@ -0,0 +1,36 @@ +/** + * @license + * Copyright 2017 Google LLC + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +const karma = require('karma'); +const karmaBase = require('../../config/karma.base'); + +const files = ['*.test.*']; + +module.exports = function (config) { + const karmaConfig = Object.assign({}, karmaBase, { + // files to load into karma + files: files, + preprocessors: { '**/*.ts': ['webpack', 'sourcemap'] }, + // frameworks to use + // available frameworks: https://npmjs.org/browse/keyword/karma-adapter + frameworks: ['mocha'] + }); + + config.set(karmaConfig); +}; + +module.exports.files = files; diff --git a/integration/compat-interop/messaging.test.ts b/integration/compat-interop/messaging.test.ts new file mode 100644 index 00000000000..88758d2e3e3 --- /dev/null +++ b/integration/compat-interop/messaging.test.ts @@ -0,0 +1,35 @@ +/** + * @license + * Copyright 2021 Google LLC + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +import { getModularInstance } from '@firebase/util'; +import { expect } from 'chai'; +import { getMessaging } from '@firebase/messaging-exp'; +import firebase from '@firebase/app-compat'; +import '@firebase/messaging-compat'; + +import { TEST_PROJECT_CONFIG } from './util'; + +firebase.initializeApp(TEST_PROJECT_CONFIG); + +const compatMessaging = firebase.messaging(); +const modularMessaging = getMessaging(); + +describe('Messaging compat interop', () => { + it('Messaging compat instance references modular Messaging instance', () => { + expect(getModularInstance(compatMessaging)).to.equal(modularMessaging); + }); +}); diff --git a/integration/compat-interop/package.json b/integration/compat-interop/package.json new file mode 100644 index 00000000000..f47062301c4 --- /dev/null +++ b/integration/compat-interop/package.json @@ -0,0 +1,29 @@ +{ + "name": "firebase-compat-interop-test", + "private": true, + "version": "0.1.0", + "scripts": { + "test": "karma start --single-run", + "test:ci": "node ../../scripts/run_tests_in_ci.js -s test", + "test:debug": "karma start --browsers Chrome --auto-watch" + }, + "dependencies": { + "@firebase/app-exp": "0.0.900", + "@firebase/app-compat": "0.0.900", + "@firebase/analytics-exp": "0.0.900", + "@firebase/analytics-compat": "0.0.900", + "@firebase/auth-exp": "0.0.900", + "@firebase/auth-compat": "0.0.900", + "@firebase/functions-exp": "0.0.900", + "@firebase/functions-compat": "0.0.900", + "@firebase/messaging-exp": "0.0.900", + "@firebase/messaging-compat": "0.0.900", + "@firebase/performance-exp": "0.0.900", + "@firebase/performance-compat": "0.0.900", + "@firebase/remote-config-exp": "0.0.900", + "@firebase/remote-config-compat": "0.0.900" + }, + "devDependencies": { + "typescript": "4.2.2" + } + } \ No newline at end of file diff --git a/integration/compat-interop/performance.test.ts b/integration/compat-interop/performance.test.ts new file mode 100644 index 00000000000..6820b0cb368 --- /dev/null +++ b/integration/compat-interop/performance.test.ts @@ -0,0 +1,60 @@ +/** + * @license + * Copyright 2021 Google LLC + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +import { getModularInstance } from '@firebase/util'; +import { expect } from 'chai'; +import { getPerformance } from '@firebase/performance-exp'; +import firebase from '@firebase/app-compat'; +import '@firebase/performance-compat'; + +import { TEST_PROJECT_CONFIG } from './util'; + +firebase.initializeApp(TEST_PROJECT_CONFIG); + +const compatPerf = firebase.performance(); +const modularPerf = getPerformance(); + +describe('Performance compat interop', () => { + it('Performance compat instance references modular Performance instance', () => { + expect(getModularInstance(compatPerf)).to.equal(modularPerf); + }); + + it('Performance compat and modular Performance instance share the same configuration', () => { + expect(compatPerf.dataCollectionEnabled).to.equal(true); + expect(compatPerf.instrumentationEnabled).to.equal(true); + expect(modularPerf.dataCollectionEnabled).to.equal(true); + expect(modularPerf.instrumentationEnabled).to.equal(true); + + // change settings on the compat instance + compatPerf.dataCollectionEnabled = false; + compatPerf.instrumentationEnabled = false; + + expect(compatPerf.dataCollectionEnabled).to.equal(false); + expect(compatPerf.instrumentationEnabled).to.equal(false); + expect(modularPerf.dataCollectionEnabled).to.equal(false); + expect(modularPerf.instrumentationEnabled).to.equal(false); + + // change settings on the modular instance + modularPerf.dataCollectionEnabled = true; + modularPerf.instrumentationEnabled = true; + + expect(compatPerf.dataCollectionEnabled).to.equal(true); + expect(compatPerf.instrumentationEnabled).to.equal(true); + expect(modularPerf.dataCollectionEnabled).to.equal(true); + expect(modularPerf.instrumentationEnabled).to.equal(true); + }); +}); diff --git a/integration/compat-interop/remote-config.test.ts b/integration/compat-interop/remote-config.test.ts new file mode 100644 index 00000000000..580832aee12 --- /dev/null +++ b/integration/compat-interop/remote-config.test.ts @@ -0,0 +1,35 @@ +/** + * @license + * Copyright 2021 Google LLC + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +import { getModularInstance } from '@firebase/util'; +import { expect } from 'chai'; +import { getRemoteConfig } from '@firebase/remote-config-exp'; +import firebase from '@firebase/app-compat'; +import '@firebase/remote-config-compat'; + +import { TEST_PROJECT_CONFIG } from './util'; + +firebase.initializeApp(TEST_PROJECT_CONFIG); + +const compatRC = firebase.remoteConfig(); +const modularRC = getRemoteConfig(); + +describe('RC compat interop', () => { + it('RC compat instance references modular RC instance', () => { + expect(getModularInstance(compatRC)).to.equal(modularRC); + }); +}); diff --git a/integration/compat-interop/tsconfig.json b/integration/compat-interop/tsconfig.json new file mode 100644 index 00000000000..4da78214594 --- /dev/null +++ b/integration/compat-interop/tsconfig.json @@ -0,0 +1,19 @@ +{ + "extends": "../../config/tsconfig.base.json", + "compileOnSave": false, + "compilerOptions": { + "allowJs": true, + "declaration": false, + "module": "commonjs", + "moduleResolution": "node", + "noImplicitAny": true, + "outDir": "dist", + "target": "ES5", + "sourceMap": true, + "esModuleInterop": true + }, + "exclude": [ + "node_modules", + "dist" + ] +} diff --git a/integration/compat-interop/util.ts b/integration/compat-interop/util.ts new file mode 100644 index 00000000000..68734591c6e --- /dev/null +++ b/integration/compat-interop/util.ts @@ -0,0 +1,18 @@ +/** + * @license + * Copyright 2021 Google LLC + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +export const TEST_PROJECT_CONFIG = require('../../config/project.json'); diff --git a/packages-exp/functions-compat/src/index.ts b/packages-exp/functions-compat/src/index.ts index 8be24bbe6d4..ac85ad18dce 100644 --- a/packages-exp/functions-compat/src/index.ts +++ b/packages-exp/functions-compat/src/index.ts @@ -25,12 +25,12 @@ firebase.registerVersion(name, version); declare module '@firebase/app-compat' { interface FirebaseNamespace { - functions?: { + functions: { (app?: FirebaseApp): types.FirebaseFunctions; Functions: typeof types.FirebaseFunctions; }; } interface FirebaseApp { - functions?(regionOrCustomDomain?: string): types.FirebaseFunctions; + functions(regionOrCustomDomain?: string): types.FirebaseFunctions; } } diff --git a/packages-exp/performance-compat/src/index.ts b/packages-exp/performance-compat/src/index.ts index 7fed7ca8c8b..0a2109ee3f0 100644 --- a/packages-exp/performance-compat/src/index.ts +++ b/packages-exp/performance-compat/src/index.ts @@ -58,11 +58,11 @@ registerPerformanceCompat(firebase as _FirebaseNamespace); declare module '@firebase/app-compat' { interface FirebaseNamespace { - performance?: { + performance: { (app?: FirebaseApp): FirebasePerformanceCompat; }; } interface FirebaseApp { - performance?(): FirebasePerformanceCompat; + performance(): FirebasePerformanceCompat; } } diff --git a/packages-exp/remote-config-compat/src/index.ts b/packages-exp/remote-config-compat/src/index.ts index 11c472c7ead..88de17406cf 100644 --- a/packages-exp/remote-config-compat/src/index.ts +++ b/packages-exp/remote-config-compat/src/index.ts @@ -64,7 +64,7 @@ registerRemoteConfigCompat(firebase as _FirebaseNamespace); declare module '@firebase/app-compat' { interface FirebaseNamespace { - remoteConfig?: { + remoteConfig: { (app?: FirebaseApp): RemoteConfigCompat; }; } diff --git a/packages/component/src/provider.ts b/packages/component/src/provider.ts index d5a171b6c3a..de01e815691 100644 --- a/packages/component/src/provider.ts +++ b/packages/component/src/provider.ts @@ -99,11 +99,9 @@ export class Provider { identifier?: string; optional?: boolean; }): NameServiceMapping[T] | null { - const { identifier, optional } = { - identifier: DEFAULT_ENTRY_NAME, - optional: false, - ...options - }; + const identifier = options?.identifier ?? DEFAULT_ENTRY_NAME; + const optional = options?.optional ?? false; + // if multipleInstances is not supported, use the default name const normalizedIdentifier = this.normalizeInstanceIdentifier(identifier); diff --git a/yarn.lock b/yarn.lock index 174872ed50a..5c652bc7122 100644 --- a/yarn.lock +++ b/yarn.lock @@ -2557,6 +2557,13 @@ dependencies: "@types/glob" "*" +"@types/archiver@^5.1.0": + version "5.1.0" + resolved "https://registry.npmjs.org/@types/archiver/-/archiver-5.1.0.tgz#869f4ce4028e49cf9a0243cf914415f4cc3d1f3d" + integrity sha512-baFOhanb/hxmcOd1Uey2TfFg43kTSmM6py1Eo7Rjbv/ivcl7PXLhY0QgXGf50Hx/eskGCFqPfhs/7IZLb15C5g== + dependencies: + "@types/glob" "*" + "@types/argparse@1.0.38": version "1.0.38" resolved "https://registry.npmjs.org/@types/argparse/-/argparse-1.0.38.tgz#a81fd8606d481f873a3800c6ebae4f1d768a56a9" @@ -8328,6 +8335,18 @@ get-uri@3: fs-extra "^8.1.0" ftp "^0.3.10" +get-uri@3: + version "3.0.2" + resolved "https://registry.npmjs.org/get-uri/-/get-uri-3.0.2.tgz#f0ef1356faabc70e1f9404fa3b66b2ba9bfc725c" + integrity sha512-+5s0SJbGoyiJTZZ2JTpFPLMPSch72KEqGOTvQsBqg0RBWvwhWUSYZFAtz3TPW0GXJuLBJPts1E241iHg+VRfhg== + dependencies: + "@tootallnate/once" "1" + data-uri-to-buffer "3" + debug "4" + file-uri-to-path "2" + fs-extra "^8.1.0" + ftp "^0.3.10" + get-value@^2.0.3, get-value@^2.0.6: version "2.0.6" resolved "https://registry.npmjs.org/get-value/-/get-value-2.0.6.tgz#dc15ca1c672387ca76bd37ac0a395ba2042a2c28" @@ -16428,6 +16447,11 @@ tslib@^2.0.1, tslib@^2.1.0, tslib@^2.2.0: resolved "https://registry.npmjs.org/tslib/-/tslib-2.2.0.tgz#fb2c475977e35e241311ede2693cee1ec6698f5c" integrity sha512-gS9GVHRU+RGn5KQM2rllAlR3dU6m7AcpJKdtH8gFvQiC4Otgk98XnmMU+nZenHt/+VhnBPWwgrJsyrdcw6i23w== +tslib@^2.0.1: + version "2.2.0" + resolved "https://registry.npmjs.org/tslib/-/tslib-2.2.0.tgz#fb2c475977e35e241311ede2693cee1ec6698f5c" + integrity sha512-gS9GVHRU+RGn5KQM2rllAlR3dU6m7AcpJKdtH8gFvQiC4Otgk98XnmMU+nZenHt/+VhnBPWwgrJsyrdcw6i23w== + tslint@6.1.3: version "6.1.3" resolved "https://registry.npmjs.org/tslint/-/tslint-6.1.3.tgz#5c23b2eccc32487d5523bd3a470e9aa31789d904"