From 0149480df3ec267c8b317d9034ff2a297bf2ce23 Mon Sep 17 00:00:00 2001 From: Nabeel Parkar Date: Tue, 5 Sep 2023 06:49:26 +0530 Subject: [PATCH] feat(in-app-messaging): Firebase V9 modular APIs (#7306) --------- Co-authored-by: Mike Hardy --- packages/in-app-messaging/e2e/fiam.e2e.js | 213 +++++++++++++----- packages/in-app-messaging/lib/index.js | 2 + .../in-app-messaging/lib/modular/index.d.ts | 89 ++++++++ .../in-app-messaging/lib/modular/index.js | 57 +++++ tests/app.js | 2 + tests/e2e/globals.js | 6 + 6 files changed, 314 insertions(+), 55 deletions(-) create mode 100644 packages/in-app-messaging/lib/modular/index.d.ts create mode 100644 packages/in-app-messaging/lib/modular/index.js diff --git a/packages/in-app-messaging/e2e/fiam.e2e.js b/packages/in-app-messaging/e2e/fiam.e2e.js index f87f0a63d5..bb68013fbb 100644 --- a/packages/in-app-messaging/e2e/fiam.e2e.js +++ b/packages/in-app-messaging/e2e/fiam.e2e.js @@ -16,76 +16,179 @@ */ describe('inAppMessaging()', function () { - describe('namespace', function () { - it('accessible from firebase.app()', function () { - const app = firebase.app(); - should.exist(app.inAppMessaging); - app.inAppMessaging().app.should.equal(app); + describe('v8 compatibility', function () { + describe('namespace', function () { + it('accessible from firebase.app()', function () { + const app = firebase.app(); + should.exist(app.inAppMessaging); + app.inAppMessaging().app.should.equal(app); + }); }); - }); - describe('setAutomaticDataCollectionEnabled()', function () { - // These depend on `tests/firebase.json` having `in_app_messaging_auto_collection_enabled` set to false the first time - // The setting is persisted across restarts, reset to false after for local runs where prefs are sticky - afterEach(async function () { - await firebase.inAppMessaging().setAutomaticDataCollectionEnabled(false); - }); + describe('setAutomaticDataCollectionEnabled()', function () { + // These depend on `tests/firebase.json` having `in_app_messaging_auto_collection_enabled` set to false the first time + // The setting is persisted across restarts, reset to false after for local runs where prefs are sticky + afterEach(async function () { + await firebase.inAppMessaging().setAutomaticDataCollectionEnabled(false); + }); + + it('true', async function () { + should.equal(firebase.inAppMessaging().isAutomaticDataCollectionEnabled, false); + await firebase.inAppMessaging().setAutomaticDataCollectionEnabled(true); + should.equal(firebase.inAppMessaging().isAutomaticDataCollectionEnabled, true); + }); - it('true', async function () { - should.equal(firebase.inAppMessaging().isAutomaticDataCollectionEnabled, false); - await firebase.inAppMessaging().setAutomaticDataCollectionEnabled(true); - should.equal(firebase.inAppMessaging().isAutomaticDataCollectionEnabled, true); + it('false', async function () { + await firebase.inAppMessaging().setAutomaticDataCollectionEnabled(false); + should.equal(firebase.inAppMessaging().isAutomaticDataCollectionEnabled, false); + }); + + it('errors if not boolean', async function () { + try { + firebase.inAppMessaging().setAutomaticDataCollectionEnabled(); + return Promise.reject(new Error('Did not throw')); + } catch (e) { + e.message.should.containEql('must be a boolean'); + return Promise.resolve(); + } + }); }); - it('false', async function () { - await firebase.inAppMessaging().setAutomaticDataCollectionEnabled(false); - should.equal(firebase.inAppMessaging().isAutomaticDataCollectionEnabled, false); + xdescribe('setMessagesDisplaySuppressed()', function () { + it('false', async function () { + should.equal(firebase.inAppMessaging().isMessagesDisplaySuppressed, false); + await firebase.inAppMessaging().setMessagesDisplaySuppressed(false); + should.equal(firebase.inAppMessaging().isMessagesDisplaySuppressed, false); + await Utils.sleep(2000); + }); + + it('true', async function () { + await device.launchApp(); + await firebase.inAppMessaging().setMessagesDisplaySuppressed(true); + should.equal(firebase.inAppMessaging().isMessagesDisplaySuppressed, true); + await Utils.sleep(1500); + await firebase.inAppMessaging().setMessagesDisplaySuppressed(false); + should.equal(firebase.inAppMessaging().isMessagesDisplaySuppressed, false); + await Utils.sleep(1500); + }); + + it('errors if not boolean', async function () { + try { + firebase.inAppMessaging().setMessagesDisplaySuppressed(); + return Promise.reject(new Error('Did not throw')); + } catch (e) { + e.message.should.containEql('must be a boolean'); + return Promise.resolve(); + } + }); }); - it('errors if not boolean', async function () { - try { - firebase.inAppMessaging().setAutomaticDataCollectionEnabled(); - return Promise.reject(new Error('Did not throw')); - } catch (e) { - e.message.should.containEql('must be a boolean'); - return Promise.resolve(); - } + xdescribe('triggerEvent()', function () { + it('no exceptions thrown', async function () { + await device.launchApp(); + await firebase.inAppMessaging().triggerEvent('eventName'); + }); }); }); - xdescribe('setMessagesDisplaySuppressed()', function () { - it('false', async function () { - should.equal(firebase.inAppMessaging().isMessagesDisplaySuppressed, false); - await firebase.inAppMessaging().setMessagesDisplaySuppressed(false); - should.equal(firebase.inAppMessaging().isMessagesDisplaySuppressed, false); - await Utils.sleep(2000); - }); + describe('modular', function () { + describe('setAutomaticDataCollectionEnabled()', function () { + // These depend on `tests/firebase.json` having `in_app_messaging_auto_collection_enabled` set to false the first time + // The setting is persisted across restarts, reset to false after for local runs where prefs are sticky + afterEach(async function () { + await firebase.inAppMessaging().setAutomaticDataCollectionEnabled(false); + }); + // afterEach(async function () { + // const { getInAppMessaging, setAutomaticDataCollectionEnabled } = inAppMessagingModular; + // const inAppMessaging = getInAppMessaging(); + // await setAutomaticDataCollectionEnabled(inAppMessaging, false); + // }); + + it('true', async function () { + const { + getInAppMessaging, + setAutomaticDataCollectionEnabled, + isAutomaticDataCollectionEnabled, + } = inAppMessagingModular; + const inAppMessaging = getInAppMessaging(); + + should.equal(isAutomaticDataCollectionEnabled(inAppMessaging), false); + await setAutomaticDataCollectionEnabled(inAppMessaging, true); + should.equal(isAutomaticDataCollectionEnabled(inAppMessaging), true); + }); + + it('false', async function () { + const { + getInAppMessaging, + setAutomaticDataCollectionEnabled, + isAutomaticDataCollectionEnabled, + } = inAppMessagingModular; + const inAppMessaging = getInAppMessaging(); - it('true', async function () { - await device.launchApp(); - await firebase.inAppMessaging().setMessagesDisplaySuppressed(true); - should.equal(firebase.inAppMessaging().isMessagesDisplaySuppressed, true); - await Utils.sleep(1500); - await firebase.inAppMessaging().setMessagesDisplaySuppressed(false); - should.equal(firebase.inAppMessaging().isMessagesDisplaySuppressed, false); - await Utils.sleep(1500); + await setAutomaticDataCollectionEnabled(inAppMessaging, false); + should.equal(isAutomaticDataCollectionEnabled(inAppMessaging), false); + }); + + it('errors if not boolean', async function () { + const { getInAppMessaging, setAutomaticDataCollectionEnabled } = inAppMessagingModular; + + try { + await setAutomaticDataCollectionEnabled(getInAppMessaging()); + return Promise.reject(new Error('Did not throw')); + } catch (e) { + e.message.should.containEql('must be a boolean'); + return Promise.resolve(); + } + }); }); - it('errors if not boolean', async function () { - try { - firebase.inAppMessaging().setMessagesDisplaySuppressed(); - return Promise.reject(new Error('Did not throw')); - } catch (e) { - e.message.should.containEql('must be a boolean'); - return Promise.resolve(); - } + xdescribe('setMessagesDisplaySuppressed()', function () { + it('false', async function () { + const { getInAppMessaging, setMessagesDisplaySuppressed, isMessagesDisplaySuppressed } = + inAppMessagingModular; + const inAppMessaging = getInAppMessaging(); + + should.equal(isMessagesDisplaySuppressed(inAppMessaging), false); + await setMessagesDisplaySuppressed(inAppMessaging, false); + should.equal(isMessagesDisplaySuppressed(inAppMessaging), false); + await Utils.sleep(2000); + }); + + it('true', async function () { + const { getInAppMessaging, setMessagesDisplaySuppressed, isMessagesDisplaySuppressed } = + inAppMessagingModular; + const inAppMessaging = getInAppMessaging(); + + await device.launchApp(); + await setMessagesDisplaySuppressed(inAppMessaging, true); + should.equal(isMessagesDisplaySuppressed(inAppMessaging), true); + await Utils.sleep(1500); + await setMessagesDisplaySuppressed(inAppMessaging, false); + should.equal(isMessagesDisplaySuppressed(inAppMessaging), false); + await Utils.sleep(1500); + }); + + it('errors if not boolean', async function () { + const { setMessagesDisplaySuppressed } = inAppMessagingModular; + + try { + setMessagesDisplaySuppressed(); + return Promise.reject(new Error('Did not throw')); + } catch (e) { + e.message.should.containEql('must be a boolean'); + return Promise.resolve(); + } + }); }); - }); - xdescribe('triggerEvent()', function () { - it('no exceptions thrown', async function () { - await device.launchApp(); - await firebase.inAppMessaging().triggerEvent('eventName'); + xdescribe('triggerEvent()', function () { + it('no exceptions thrown', async function () { + const { getInAppMessaging, triggerEvent } = inAppMessagingModular; + const inAppMessaging = getInAppMessaging(); + + await device.launchApp(); + await triggerEvent(inAppMessaging, 'eventName'); + }); }); }); }); diff --git a/packages/in-app-messaging/lib/index.js b/packages/in-app-messaging/lib/index.js index 366c76dcb4..b9cd41847d 100644 --- a/packages/in-app-messaging/lib/index.js +++ b/packages/in-app-messaging/lib/index.js @@ -74,6 +74,8 @@ class FirebaseFiamModule extends FirebaseModule { } } +export * from './modular'; + // import { SDK_VERSION } from '@react-native-firebase/in-app-messaging'; export const SDK_VERSION = version; diff --git a/packages/in-app-messaging/lib/modular/index.d.ts b/packages/in-app-messaging/lib/modular/index.d.ts new file mode 100644 index 0000000000..296036c2d2 --- /dev/null +++ b/packages/in-app-messaging/lib/modular/index.d.ts @@ -0,0 +1,89 @@ +import { FirebaseInAppMessagingTypes } from '..'; + +type FirebaseInAppMessaging = FirebaseInAppMessagingTypes.Module; + +export declare function getInAppMessaging(): FirebaseInAppMessaging; + +/** + * Determines whether messages are suppressed or not. + * + * #### Example + * + * ```js + * const inAppMessaging = getInAppMessaging(); + * const isSuppressed = isMessagesDisplaySuppressed(inAppMessaging); + * ``` + */ +export declare function isMessagesDisplaySuppressed( + inAppMessaging: FirebaseInAppMessaging, +): boolean; + +/** + * Enable or disable suppression of Firebase In App Messaging messages. + * + * When enabled, no in app messages will be rendered until either you disable suppression, or the app restarts. + * This state is not persisted between app restarts. + * + * #### Example + * + * ```js + * // Suppress messages + * const inAppMessaging = getInAppMessaging(); + * await setMessagesDisplaySuppressed(inAppMessaging, true); + * ``` + */ +export declare function setMessagesDisplaySuppressed( + inAppMessaging: FirebaseInAppMessaging, + enabled: boolean, +): Promise; + +/** + * Determines whether automatic data collection is enabled or not. + * + * #### Example + * + * ```js + * const inAppMessaging = getInAppMessaging(); + * const isDataCollectionEnabled = isAutomaticDataCollectionEnabled(inAppMessaging); + * ``` + */ +export declare function isAutomaticDataCollectionEnabled( + inAppMessaging: FirebaseInAppMessaging, +): boolean; + +/** + * Enable or disable automatic data collection for Firebase In-App Messaging. + * + * When enabled, generates a registration token on app startup if there is no valid one and generates a new token + * when it is deleted (which prevents `deleteInstanceId()` from stopping the periodic sending of data). + * + * This setting is persisted across app restarts and overrides the setting specified in your manifest/plist file. + * + * #### Example + * + * ```js + * // Disable data collection + * const inAppMessaging = getInAppMessaging(); + * setAutomaticDataCollectionEnabled(inAppMessaging, false); + * ``` + */ +export declare function setAutomaticDataCollectionEnabled( + inAppMessaging: FirebaseInAppMessaging, + enabled: boolean, +): Promise; + +/** + * Trigger in-app messages programmatically + * + * #### Example + * + * ```js + * // Suppress messages + * const inAppMessaging = getInAppMessaging(); + * await triggerEvent(inAppMessaging, "exampleTrigger"); + * ``` + */ +export declare function triggerEvent( + inAppMessaging: FirebaseInAppMessaging, + eventId: string, +): Promise; diff --git a/packages/in-app-messaging/lib/modular/index.js b/packages/in-app-messaging/lib/modular/index.js new file mode 100644 index 0000000000..bff7137506 --- /dev/null +++ b/packages/in-app-messaging/lib/modular/index.js @@ -0,0 +1,57 @@ +import { firebase } from '..'; + +/** + * @typedef {import("..").FirebaseApp} FirebaseApp + * @typedef {import("..").FirebaseInAppMessagingTypes.Module} FirebaseInAppMessaging + */ + +/** + * @returns {FirebaseInAppMessaging} + */ +export function getInAppMessaging() { + return firebase.inAppMessaging(); +} + +/** + * @param {FirebaseInAppMessaging} inAppMessaging + * @returns {boolean} + */ +export function isMessagesDisplaySuppressed(inAppMessaging) { + return inAppMessaging.isMessagesDisplaySuppressed; +} + +/** + * + * @param {FirebaseInAppMessaging} inAppMessaging + * @param {boolean} enabled + * @returns {Promise} + */ +export function setMessagesDisplaySuppressed(inAppMessaging, enabled) { + return inAppMessaging.setMessagesDisplaySuppressed(enabled); +} + +/** + * @param {FirebaseInAppMessaging} inAppMessaging + * @returns {boolean} + */ +export function isAutomaticDataCollectionEnabled(inAppMessaging) { + return inAppMessaging.isAutomaticDataCollectionEnabled; +} + +/** + * @param {FirebaseInAppMessaging} inAppMessaging + * @param {boolean} enabled + * @returns {Promise} + */ +export function setAutomaticDataCollectionEnabled(inAppMessaging, enabled) { + return inAppMessaging.setAutomaticDataCollectionEnabled(enabled); +} + +/** + * @param {FirebaseInAppMessaging} inAppMessaging + * @param {string} eventId + * @returns {Promise} + */ +export function triggerEvent(inAppMessaging, eventId) { + return inAppMessaging.triggerEvent(eventId); +} diff --git a/tests/app.js b/tests/app.js index 91e2a1f584..0de77e72e6 100644 --- a/tests/app.js +++ b/tests/app.js @@ -43,6 +43,7 @@ import jet from 'jet/platform/react-native'; import React from 'react'; import { AppRegistry, Button, NativeModules, Text, View } from 'react-native'; import DeviceInfo from 'react-native-device-info'; +import * as inAppMessagingModular from '@react-native-firebase/in-app-messaging'; import * as installationsModular from '@react-native-firebase/installations'; import * as crashlyticsModular from '@react-native-firebase/crashlytics'; @@ -58,6 +59,7 @@ jet.exposeContextProperty('perfModular', perfModular); jet.exposeContextProperty('appCheckModular', appCheckModular); jet.exposeContextProperty('messagingModular', messagingModular); jet.exposeContextProperty('storageModular', storageModular); +jet.exposeContextProperty('inAppMessagingModular', inAppMessagingModular); jet.exposeContextProperty('installationsModular', installationsModular); jet.exposeContextProperty('crashlyticsModular', crashlyticsModular); diff --git a/tests/e2e/globals.js b/tests/e2e/globals.js index 3186f29bd8..e556484a4a 100644 --- a/tests/e2e/globals.js +++ b/tests/e2e/globals.js @@ -113,6 +113,12 @@ Object.defineProperty(global, 'storageModular', { }, }); +Object.defineProperty(global, 'inAppMessagingModular', { + get() { + return jet.inAppMessagingModular; + }, +}); + Object.defineProperty(global, 'installationsModular', { get() { return jet.installationsModular;