From 57f7327da4b405dace6b040e8a942d5f107f3603 Mon Sep 17 00:00:00 2001 From: Nabeel Parkar Date: Tue, 5 Sep 2023 03:34:56 +0530 Subject: [PATCH] feat(crashlytics): Firbase web modular V9 API (#7283) * feat(crashlytics): add modular API for crashlytics * fix: remove app parameter from getCrashlytics * fix(types): typedef types at top, use typedefs in jsdoc comments --------- Co-authored-by: Mike Hardy --- packages/crashlytics/e2e/crashlytics.e2e.js | 448 ++++++++++++++------ packages/crashlytics/lib/index.d.ts | 2 +- packages/crashlytics/lib/index.js | 2 + packages/crashlytics/lib/modular/index.d.ts | 207 +++++++++ packages/crashlytics/lib/modular/index.js | 118 ++++++ tests/app.js | 2 + tests/e2e/globals.js | 6 + 7 files changed, 660 insertions(+), 125 deletions(-) create mode 100644 packages/crashlytics/lib/modular/index.d.ts create mode 100644 packages/crashlytics/lib/modular/index.js diff --git a/packages/crashlytics/e2e/crashlytics.e2e.js b/packages/crashlytics/e2e/crashlytics.e2e.js index f62b0880d9..e3bb8710ef 100644 --- a/packages/crashlytics/e2e/crashlytics.e2e.js +++ b/packages/crashlytics/e2e/crashlytics.e2e.js @@ -16,171 +16,371 @@ */ describe('crashlytics()', function () { - // Run locally only - flakey on CI - xdescribe('crash()', function () { - it('crashes the app', async function () { - jet.context._BEFORE_CRASH_ = 1; - firebase.crashlytics().crash(); - await Utils.sleep(1500); - await device.launchApp({ newInstance: false }); - await Utils.sleep(1500); - should.equal(jet.context._BEFORE_CRASH_, undefined); + describe('v8 compatibility', function () { + // Run locally only - flakey on CI + xdescribe('crash()', function () { + it('crashes the app', async function () { + jet.context._BEFORE_CRASH_ = 1; + firebase.crashlytics().crash(); + await Utils.sleep(1500); + await device.launchApp({ newInstance: false }); + await Utils.sleep(1500); + should.equal(jet.context._BEFORE_CRASH_, undefined); + }); }); - }); - describe('log()', function () { - it('accepts any value', async function () { - firebase.crashlytics().log('invertase'); - firebase.crashlytics().log(1337); - firebase.crashlytics().log(null); - firebase.crashlytics().log(true); - firebase.crashlytics().log({}); - firebase.crashlytics().log([]); - firebase.crashlytics().log(() => {}); + describe('log()', function () { + it('accepts any value', async function () { + firebase.crashlytics().log('invertase'); + firebase.crashlytics().log(1337); + firebase.crashlytics().log(null); + firebase.crashlytics().log(true); + firebase.crashlytics().log({}); + firebase.crashlytics().log([]); + firebase.crashlytics().log(() => {}); + }); + }); + + describe('setUserId()', function () { + it('accepts string values', async function () { + await firebase.crashlytics().setUserId('invertase'); + }); + + it('rejects none string values', async function () { + try { + await firebase.crashlytics().setUserId(666.1337); + return Promise.reject(new Error('Did not throw.')); + } catch (e) { + e.message.should.containEql('must be a string'); + } + }); }); - }); - describe('setUserId()', function () { - it('accepts string values', async function () { - await firebase.crashlytics().setUserId('invertase'); + describe('setAttribute()', function () { + it('accepts string values', async function () { + await firebase.crashlytics().setAttribute('invertase', '1337'); + }); + + it('rejects none string values', async function () { + try { + await firebase.crashlytics().setAttribute('invertase', 33.3333); + return Promise.reject(new Error('Did not throw.')); + } catch (e) { + e.message.should.containEql('must be a string'); + } + }); + + it('errors if attribute name is not a string', async function () { + try { + await firebase.crashlytics().setAttribute(1337, 'invertase'); + return Promise.reject(new Error('Did not throw.')); + } catch (e) { + e.message.should.containEql('must be a string'); + } + }); }); - it('rejects none string values', async function () { - try { - await firebase.crashlytics().setUserId(666.1337); - return Promise.reject(new Error('Did not throw.')); - } catch (e) { - e.message.should.containEql('must be a string'); - } + describe('setAttributes()', function () { + it('errors if arg is not an object', async function () { + try { + await firebase.crashlytics().setAttributes(1337); + return Promise.reject(new Error('Did not throw.')); + } catch (e) { + e.message.should.containEql('must be an object'); + } + }); + + it('accepts string values', async function () { + await firebase.crashlytics().setAttributes({ invertase: '1337' }); + }); }); - }); - describe('setAttribute()', function () { - it('accepts string values', async function () { - await firebase.crashlytics().setAttribute('invertase', '1337'); + describe('recordError()', function () { + it('warns if not an error', async function () { + const orig = jet.context.console.warn; + let logged = false; + jet.context.console.warn = msg => { + msg.should.containEql('expects an instance of Error'); + logged = true; + jet.context.console.warn = orig; + }; + + firebase.crashlytics().recordError(1337); + should.equal(logged, true); + }); + + it('accepts Error values', async function () { + firebase.crashlytics().recordError(new Error("I'm a teapot!")); + // TODO verify stack obj + }); + + it('accepts optional jsErrorName', async function () { + firebase + .crashlytics() + .recordError( + new Error("I'm a teapot!"), + 'This message will display in crashlytics dashboard', + ); + // TODO verify stack obj + }); }); - it('rejects none string values', async function () { - try { - await firebase.crashlytics().setAttribute('invertase', 33.3333); - return Promise.reject(new Error('Did not throw.')); - } catch (e) { - e.message.should.containEql('must be a string'); - } + describe('sendUnsentReports()', function () { + it("sends unsent reports to the crashlytic's server", function () { + firebase.crashlytics().sendUnsentReports(); + }); }); - it('errors if attribute name is not a string', async function () { - try { - await firebase.crashlytics().setAttribute(1337, 'invertase'); - return Promise.reject(new Error('Did not throw.')); - } catch (e) { - e.message.should.containEql('must be a string'); - } + describe('checkForUnsentReports()', function () { + it('errors if automatic crash report collection is enabled', async function () { + await firebase.crashlytics().setCrashlyticsCollectionEnabled(true); + try { + await firebase.crashlytics().checkForUnsentReports(); + return Promise.reject('Error did not throw'); + } catch (e) { + e.message.should.containEql("has been set to 'true', all reports are automatically sent"); + } + }); + it("checks device cache for unsent crashlytic's reports", async function () { + await firebase.crashlytics().setCrashlyticsCollectionEnabled(false); + const anyUnsentReports = await firebase.crashlytics().checkForUnsentReports(); + + should(anyUnsentReports).equal(false); + }); }); - }); - describe('setAttributes()', function () { - it('errors if arg is not an object', async function () { - try { - await firebase.crashlytics().setAttributes(1337); - return Promise.reject(new Error('Did not throw.')); - } catch (e) { - e.message.should.containEql('must be an object'); - } + describe('deleteUnsentReports()', function () { + it('deletes unsent crashlytics reports', async function () { + await firebase.crashlytics().deleteUnsentReports(); + }); + }); + + describe('didCrashOnPreviousExecution()', function () { + // TODO: worked on Detox v17, fails after transition to v18. Why? + xit('checks if app crached on previous execution', async function () { + const didCrash = await firebase.crashlytics().didCrashOnPreviousExecution(); + + should(didCrash).equal(false); + }); }); - it('accepts string values', async function () { - await firebase.crashlytics().setAttributes({ invertase: '1337' }); + describe('setCrashlyticsCollectionEnabled()', function () { + it('false', async function () { + await firebase.crashlytics().setCrashlyticsCollectionEnabled(false); + should.equal(firebase.crashlytics().isCrashlyticsCollectionEnabled, false); + }); + + it('true', async function () { + await firebase.crashlytics().setCrashlyticsCollectionEnabled(true); + should.equal(firebase.crashlytics().isCrashlyticsCollectionEnabled, true); + }); + + it('errors if not boolean', async function () { + try { + await firebase.crashlytics().setCrashlyticsCollectionEnabled(1337); + return Promise.reject(new Error('Did not throw.')); + } catch (e) { + e.message.should.containEql('must be a boolean'); + } + }); }); }); - describe('recordError()', function () { - it('warns if not an error', async function () { - const orig = jet.context.console.warn; - let logged = false; - jet.context.console.warn = msg => { - msg.should.containEql('expects an instance of Error'); - logged = true; - jet.context.console.warn = orig; - }; + describe('modular', function () { + // Run locally only - flakey on CI + xdescribe('crash()', function () { + it('crashes the app', async function () { + const { getCrashlytics, crash } = crashlyticsModular; + const crashlytics = getCrashlytics(); + jet.context._BEFORE_CRASH_ = 1; + crash(crashlytics); + await Utils.sleep(1500); + await device.launchApp({ newInstance: false }); + await Utils.sleep(1500); + should.equal(jet.context._BEFORE_CRASH_, undefined); + }); + }); - firebase.crashlytics().recordError(1337); - should.equal(logged, true); + describe('log()', function () { + it('accepts any value', async function () { + const { getCrashlytics, log } = crashlyticsModular; + const crashlytics = getCrashlytics(); + log(crashlytics, 'invertase'); + log(crashlytics, 1337); + log(crashlytics, null); + log(crashlytics, true); + log(crashlytics, {}); + log(crashlytics, []); + log(crashlytics, () => {}); + }); }); - it('accepts Error values', async function () { - firebase.crashlytics().recordError(new Error("I'm a teapot!")); - // TODO verify stack obj + describe('setUserId()', function () { + it('accepts string values', async function () { + const { getCrashlytics, setUserId } = crashlyticsModular; + await setUserId(getCrashlytics(), 'invertase'); + }); + + it('rejects none string values', async function () { + const { getCrashlytics, setUserId } = crashlyticsModular; + try { + await setUserId(getCrashlytics(), 666.1337); + return Promise.reject(new Error('Did not throw.')); + } catch (e) { + e.message.should.containEql('must be a string'); + } + }); + }); + + describe('setAttribute()', function () { + it('accepts string values', async function () { + const { getCrashlytics, setAttribute } = crashlyticsModular; + await setAttribute(getCrashlytics(), 'invertase', '1337'); + }); + + it('rejects none string values', async function () { + const { getCrashlytics, setAttribute } = crashlyticsModular; + try { + await setAttribute(getCrashlytics(), 'invertase', 33.3333); + return Promise.reject(new Error('Did not throw.')); + } catch (e) { + e.message.should.containEql('must be a string'); + } + }); + + it('errors if attribute name is not a string', async function () { + const { getCrashlytics, setAttribute } = crashlyticsModular; + try { + await setAttribute(getCrashlytics(), 1337, 'invertase'); + return Promise.reject(new Error('Did not throw.')); + } catch (e) { + e.message.should.containEql('must be a string'); + } + }); }); - it('accepts optional jsErrorName', async function () { - firebase - .crashlytics() - .recordError( + describe('setAttributes()', function () { + it('errors if arg is not an object', async function () { + const { getCrashlytics, setAttributes } = crashlyticsModular; + try { + await setAttributes(getCrashlytics(), 1337); + return Promise.reject(new Error('Did not throw.')); + } catch (e) { + e.message.should.containEql('must be an object'); + } + }); + + it('accepts string values', async function () { + await firebase.crashlytics().setAttributes({ invertase: '1337' }); + }); + }); + + describe('recordError()', function () { + it('warns if not an error', async function () { + const { getCrashlytics, recordError } = crashlyticsModular; + const orig = jet.context.console.warn; + let logged = false; + jet.context.console.warn = msg => { + msg.should.containEql('expects an instance of Error'); + logged = true; + jet.context.console.warn = orig; + }; + + recordError(getCrashlytics(), 1337); + should.equal(logged, true); + }); + + it('accepts Error values', async function () { + const { getCrashlytics, recordError } = crashlyticsModular; + recordError(getCrashlytics(), new Error("I'm a teapot!")); + // TODO verify stack obj + }); + + it('accepts optional jsErrorName', async function () { + const { getCrashlytics, recordError } = crashlyticsModular; + recordError( + getCrashlytics(), new Error("I'm a teapot!"), 'This message will display in crashlytics dashboard', ); - // TODO verify stack obj + // TODO verify stack obj + }); }); - }); - describe('sendUnsentReports()', function () { - it("sends unsent reports to the crashlytic's server", function () { - firebase.crashlytics().sendUnsentReports(); + describe('sendUnsentReports()', function () { + it("sends unsent reports to the crashlytic's server", function () { + const { getCrashlytics, sendUnsentReports } = crashlyticsModular; + sendUnsentReports(getCrashlytics()); + }); }); - }); - describe('checkForUnsentReports()', function () { - it('errors if automatic crash report collection is enabled', async function () { - await firebase.crashlytics().setCrashlyticsCollectionEnabled(true); - try { - await firebase.crashlytics().checkForUnsentReports(); - return Promise.reject('Error did not throw'); - } catch (e) { - e.message.should.containEql("has been set to 'true', all reports are automatically sent"); - } - }); - it("checks device cache for unsent crashlytic's reports", async function () { - await firebase.crashlytics().setCrashlyticsCollectionEnabled(false); - const anyUnsentReports = await firebase.crashlytics().checkForUnsentReports(); + describe('checkForUnsentReports()', function () { + it('errors if automatic crash report collection is enabled', async function () { + const { getCrashlytics, setCrashlyticsCollectionEnabled, checkForUnsentReports } = + crashlyticsModular; + const crashlytics = getCrashlytics(); + await setCrashlyticsCollectionEnabled(crashlytics, true); + try { + await checkForUnsentReports(crashlytics); + return Promise.reject('Error did not throw'); + } catch (e) { + e.message.should.containEql("has been set to 'true', all reports are automatically sent"); + } + }); + it("checks device cache for unsent crashlytic's reports", async function () { + const { getCrashlytics, setCrashlyticsCollectionEnabled, checkForUnsentReports } = + crashlyticsModular; + const crashlytics = getCrashlytics(); + await setCrashlyticsCollectionEnabled(crashlytics, false); + const anyUnsentReports = await checkForUnsentReports(crashlytics); - should(anyUnsentReports).equal(false); + should(anyUnsentReports).equal(false); + }); }); - }); - describe('deleteUnsentReports()', function () { - it('deletes unsent crashlytics reports', async function () { - await firebase.crashlytics().deleteUnsentReports(); + describe('deleteUnsentReports()', function () { + it('deletes unsent crashlytics reports', async function () { + const { getCrashlytics, deleteUnsentReports } = crashlyticsModular; + await deleteUnsentReports(getCrashlytics()); + }); }); - }); - describe('didCrashOnPreviousExecution()', function () { - // TODO: worked on Detox v17, fails after transition to v18. Why? - xit('checks if app crached on previous execution', async function () { - const didCrash = await firebase.crashlytics().didCrashOnPreviousExecution(); + describe('didCrashOnPreviousExecution()', function () { + // TODO: worked on Detox v17, fails after transition to v18. Why? + xit('checks if app crached on previous execution', async function () { + const { getCrashlytics, didCrashOnPreviousExecution } = crashlyticsModular; + const didCrash = await didCrashOnPreviousExecution(getCrashlytics()); - should(didCrash).equal(false); + should(didCrash).equal(false); + }); }); - }); - describe('setCrashlyticsCollectionEnabled()', function () { - it('false', async function () { - await firebase.crashlytics().setCrashlyticsCollectionEnabled(false); - should.equal(firebase.crashlytics().isCrashlyticsCollectionEnabled, false); - }); + describe('setCrashlyticsCollectionEnabled()', function () { + it('false', async function () { + const { getCrashlytics, setCrashlyticsCollectionEnabled, isCrashlyticsCollectionEnabled } = + crashlyticsModular; + const crashlytics = getCrashlytics(); + await setCrashlyticsCollectionEnabled(crashlytics, false); + should.equal(isCrashlyticsCollectionEnabled(crashlytics), false); + }); - it('true', async function () { - await firebase.crashlytics().setCrashlyticsCollectionEnabled(true); - should.equal(firebase.crashlytics().isCrashlyticsCollectionEnabled, true); - }); + it('true', async function () { + const { getCrashlytics, setCrashlyticsCollectionEnabled, isCrashlyticsCollectionEnabled } = + crashlyticsModular; + const crashlytics = getCrashlytics(); + await setCrashlyticsCollectionEnabled(crashlytics, true); + should.equal(isCrashlyticsCollectionEnabled(crashlytics), true); + }); - it('errors if not boolean', async function () { - try { - await firebase.crashlytics().setCrashlyticsCollectionEnabled(1337); - return Promise.reject(new Error('Did not throw.')); - } catch (e) { - e.message.should.containEql('must be a boolean'); - } + it('errors if not boolean', async function () { + const { getCrashlytics, setCrashlyticsCollectionEnabled } = crashlyticsModular; + try { + await setCrashlyticsCollectionEnabled(getCrashlytics(), 1337); + return Promise.reject(new Error('Did not throw.')); + } catch (e) { + e.message.should.containEql('must be a boolean'); + } + }); }); }); }); diff --git a/packages/crashlytics/lib/index.d.ts b/packages/crashlytics/lib/index.d.ts index 022ca382c9..254cbc6061 100644 --- a/packages/crashlytics/lib/index.d.ts +++ b/packages/crashlytics/lib/index.d.ts @@ -77,7 +77,7 @@ export namespace FirebaseCrashlyticsTypes { * ``` * */ - isCrashlyticsCollectionEnabled: true; + isCrashlyticsCollectionEnabled: boolean; /** * Determines whether there are any unsent crash reports cached on the device. The callback only executes * if automatic data collection is disabled. diff --git a/packages/crashlytics/lib/index.js b/packages/crashlytics/lib/index.js index 58c2960369..67751bc331 100644 --- a/packages/crashlytics/lib/index.js +++ b/packages/crashlytics/lib/index.js @@ -139,6 +139,8 @@ class FirebaseCrashlyticsModule extends FirebaseModule { } } +export * from './modular'; + // import { SDK_VERSION } from '@react-native-firebase/crashlytics'; export const SDK_VERSION = version; diff --git a/packages/crashlytics/lib/modular/index.d.ts b/packages/crashlytics/lib/modular/index.d.ts new file mode 100644 index 0000000000..e580bc319f --- /dev/null +++ b/packages/crashlytics/lib/modular/index.d.ts @@ -0,0 +1,207 @@ +import { FirebaseCrashlyticsTypes } from '..'; + +type FirebaseCrashlytics = FirebaseCrashlyticsTypes.Module; + +/** + * Returns Crashlytics instance. + * #### Example + * ```js + * const crashlytics = getCrashlytics(); + * ``` + */ +export declare function getCrashlytics(): FirebaseCrashlytics; + +/** + * Whether Crashlytics reporting is enabled. + * + * #### Example + * + * ```js + * const crashlytics = getCrashlytics(); + * const isEnabled = isCrashlyticsCollectionEnabled(crashlytics); + * ``` + */ +export declare function isCrashlyticsCollectionEnabled(crashlytics: FirebaseCrashlytics): boolean; +/** + * Determines whether there are any unsent crash reports cached on the device. The callback only executes + * if automatic data collection is disabled. + * + * #### Example + * + * ```js + * async checkReports() { + * // returns boolean value + * const crashlytics = getCrashlytics(); + * const unsentReports = await checkForUnsentReports(crashlytics); + * } + * + * checkReports(); + * ``` + */ +export declare function checkForUnsentReports(crashlytics: FirebaseCrashlytics): Promise; +/** + * Deletes any unsent reports on the device. This method only applies if automatic data collection is + * disabled. + * + * #### Example + * + * ```js + * const crashlytics = getCrashlytics(); + * deleteUnsentReports(crashlytics); + * ``` + */ +export declare function deleteUnsentReports(crashlytics: FirebaseCrashlytics): Promise; +/** + * Returns a boolean value indicating whether the app crashed during the previous execution. + * + * #### Example + * + * ```js + * async didCrashPreviously() { + * // returns boolean value + * const crashlytics = getCrashlytics(); + * const didCrash = await didCrashOnPreviousExecution(crashlytics); + * } + * + * didCrashPreviously(); + * ``` + */ +export declare function didCrashOnPreviousExecution( + crashlytics: FirebaseCrashlytics, +): Promise; + +/** + * Cause your app to crash for testing purposes. This is a native crash and will not contain a javascript stack trace. + * Note that crashes are intercepted by debuggers on iOS so no report will be seen under those conditions. Additionally + * if it is a debug build you will need to ensure your firebase.json is configured to enable crashlytics even in debug mode. + * + * #### Example + * + * ```js + * const crashlytics = getCrashlytics(); + * crash(crashlytics); + * ``` + */ +export declare function crash(crashlytics: FirebaseCrashlytics): void; + +/** + * Log a message that will appear in any subsequent Crash or Non-fatal error reports. + * + * #### Example + * + * ```js + * const crashlytics = getCrashlytics(); + * log(crashlytics, 'Testing a crash'); + * crash(crashlytics); + * ``` + */ +export declare function log(crashlytics: FirebaseCrashlytics, message: string): void; + +/** + * Record a JavaScript Error. + * + * The JavaScript stack trace is converted into a mock native iOS or Android exception before submission. + * The line numbers in the stack trace (if available) will be relative to the javascript bundle built by your packager, + * after whatever transpilation or minimization steps happen. You will need to maintain sourcemaps to decode them if desired. + * + * #### Example + * + * ```js + * const crashlytics = getCrashlytics(); + * recordError( + * crashlytics, + * new Error('An error was caught') + * ); + * ``` + */ +export declare function recordError( + crashlytics: FirebaseCrashlytics, + error: Error, + jsErrorName?: string, +): void; +/** + * Enqueues any unsent reports on the device to upload to Crashlytics. This method only applies if + * automatic data collection is disabled. + * + * #### Example + * + * ```js + * const crashlytics = getCrashlytics(); + * sendUnsentReports(crashlytics); + * ``` + */ +export declare function sendUnsentReports(crashlytics: FirebaseCrashlytics): void; + +/** + * Specify a user identifier which will be visible in the Firebase Crashlytics console. + * + * It is recommended for privacy purposes that this value be a value that's meaningless to a third-party + * observer; such as an arbitrary string that ties an end-user to a record in your system e.g. a database record id. + * + * #### Example + * + * ```js + * const auth = getAuth(); + * const crashlytics = getCrashlytics(); + * // Custom user id + * await setUserId(crashlytics, '123456789'); + * // Firebase auth uid + * await setUserId( + * crashlytics, + * auth.currentUser.uid + * ); + * ``` + */ +export declare function setUserId(crashlytics: FirebaseCrashlytics, userId: string): Promise; + +/** + * Sets a string value to be associated with the given attribute name which will be visible in the Firebase Crashlytics console. + * + * #### Example + * + * ```js + * const crashlytics = getCrashlytics(); + * await setAttribute(crashlytics, 'role', 'admin'); + * ``` + */ +export declare function setAttribute( + crashlytics: FirebaseCrashlytics, + name: string, + value: string, +): Promise; + +/** + * Like `setAttribute` but for multiple attributes. + * + * #### Example + * + * ```js + * const crashlytics = getCrashlytics(); + * await setAttributes(crashlytics, { + * role: 'admin', + * followers: '13', + * }); + * ``` + */ +export declare function setAttributes( + crashlytics: FirebaseCrashlytics, + attributes: { [key: string]: string }, +): Promise; + +/** + * Enable/disable Crashlytics reporting. + * + * Use this for opt-in first user data collection flows combined with `firebase.json` settings to disable auto collection. + * + * #### Example + * + * ```js + * const crashlytics = getCrashlytics(); + * // Disable crash reporting + * await setCrashlyticsCollectionEnabled(crashlytics, false); + * ``` + */ +export declare function setCrashlyticsCollectionEnabled( + crashlytics: FirebaseCrashlytics, + enabled: boolean, +): Promise; diff --git a/packages/crashlytics/lib/modular/index.js b/packages/crashlytics/lib/modular/index.js new file mode 100644 index 0000000000..42a4f684c0 --- /dev/null +++ b/packages/crashlytics/lib/modular/index.js @@ -0,0 +1,118 @@ +import { firebase } from '..'; + +/** + * @typedef {import("..").FirebaseApp} FirebaseApp + * @typedef {import("..").FirebaseCrashlyticsTypes.Module} FirebaseCrashlytics + */ + +/** + * @param {FirebaseApp} app + * @returns {FirebaseCrashlytics} + */ +export function getCrashlytics() { + return firebase.crashlytics(); +} + +/** + * @param {FirebaseCrashlytics} crashlytics + * @returns {boolean} + */ +export function isCrashlyticsCollectionEnabled(crashlytics) { + return crashlytics.isCrashlyticsCollectionEnabled; +} + +/** + * @param {FirebaseCrashlytics} crashlytics + * @returns {Promise} + */ +export function checkForUnsentReports(crashlytics) { + return crashlytics.checkForUnsentReports(); +} + +/** + * @param {FirebaseCrashlytics} crashlytics + * @returns {Promise} + */ +export function deleteUnsentReports(crashlytics) { + return crashlytics.deleteUnsentReports(); +} + +/** + * @param {FirebaseCrashlytics} crashlytics + * @returns {Promise} + */ +export function didCrashOnPreviousExecution(crashlytics) { + return crashlytics.didCrashOnPreviousExecution(); +} + +/** + * @param {FirebaseCrashlytics} crashlytics + * @returns {void} + */ +export function crash(crashlytics) { + return crashlytics.crash(); +} + +/** + * @param {FirebaseCrashlytics} crashlytics + * @param {string} message + * @returns {void} + */ +export function log(crashlytics, message) { + return crashlytics.log(message); +} + +/** + * @param {FirebaseCrashlytics} crashlytics + * @param {Error} error + * @param {string | undefined} jsErrorName + * @returns {void} + */ +export function recordError(crashlytics, error, jsErrorName) { + return crashlytics.recordError(error, jsErrorName); +} + +/** + * @param {FirebaseCrashlytics} crashlytics + * @returns {void} + */ +export function sendUnsentReports(crashlytics) { + return crashlytics.sendUnsentReports(); +} + +/** + * @param {FirebaseCrashlytics} crashlytics + * @param {string} userId + * @returns {Promise} + */ +export function setUserId(crashlytics, userId) { + return crashlytics.setUserId(userId); +} + +/** + * @param {FirebaseCrashlytics} crashlytics + * @param {string} name + * @param {string} value + * @returns {Promise} + */ +export function setAttribute(crashlytics, name, value) { + return crashlytics.setAttribute(name, value); +} + +/** + * @param {FirebaseCrashlytics} crashlytics + * @param {{ [key: string]: string }} attributes + * @returns {Promise} + */ +export function setAttributes(crashlytics, attributes) { + return crashlytics.setAttributes(attributes); +} + +/** + * @param {FirebaseCrashlytics} crashlytics + * @param {boolean} enabled + * @returns {Promise} + */ +export function setCrashlyticsCollectionEnabled(crashlytics, enabled) { + return crashlytics.setCrashlyticsCollectionEnabled(enabled); +} diff --git a/tests/app.js b/tests/app.js index 1012057c25..91e2a1f584 100644 --- a/tests/app.js +++ b/tests/app.js @@ -44,6 +44,7 @@ import React from 'react'; import { AppRegistry, Button, NativeModules, Text, View } from 'react-native'; import DeviceInfo from 'react-native-device-info'; import * as installationsModular from '@react-native-firebase/installations'; +import * as crashlyticsModular from '@react-native-firebase/crashlytics'; jet.exposeContextProperty('NativeModules', NativeModules); jet.exposeContextProperty('NativeEventEmitter', NativeEventEmitter); @@ -58,6 +59,7 @@ jet.exposeContextProperty('appCheckModular', appCheckModular); jet.exposeContextProperty('messagingModular', messagingModular); jet.exposeContextProperty('storageModular', storageModular); jet.exposeContextProperty('installationsModular', installationsModular); +jet.exposeContextProperty('crashlyticsModular', crashlyticsModular); firebase.database().useEmulator('localhost', 9000); firebase.auth().useEmulator('http://localhost:9099'); diff --git a/tests/e2e/globals.js b/tests/e2e/globals.js index f70774c0cc..3186f29bd8 100644 --- a/tests/e2e/globals.js +++ b/tests/e2e/globals.js @@ -119,4 +119,10 @@ Object.defineProperty(global, 'installationsModular', { }, }); +Object.defineProperty(global, 'crashlyticsModular', { + get() { + return jet.crashlyticsModular; + }, +}); + global.isCI = !!process.env.CI;