diff --git a/CHANGELOG.md b/CHANGELOG.md index 1b7c0a43e3..f0d65d9fcf 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -8,6 +8,10 @@ - (react-native) Update bugsnag-cocoa from v6.25.2 to [v6.26.2](https://github.com/bugsnag/bugsnag-cocoa/blob/master/CHANGELOG.md#6262-2023-04-20) - (delivery-xml-http-request) Ensure delivery errors are passed to the post report callback [#1938](https://github.com/bugsnag/bugsnag-js/pull/1938) +### Fixed + +- (electron) Fix `onSendError` callbacks not being called [#1999](https://github.com/bugsnag/bugsnag-js/pull/1999) + ## 7.20.1 (2023-02-08) ### Changes diff --git a/packages/plugin-electron-deliver-minidumps/deliver-minidumps.js b/packages/plugin-electron-deliver-minidumps/deliver-minidumps.js index 62cfe1b554..d58d224408 100644 --- a/packages/plugin-electron-deliver-minidumps/deliver-minidumps.js +++ b/packages/plugin-electron-deliver-minidumps/deliver-minidumps.js @@ -46,7 +46,7 @@ module.exports = (app, net, filestore, NativeClient) => ({ const { sendMinidump } = sendMinidumpFactory(net, client) const queue = new MinidumpQueue(filestore) - const loop = new MinidumpDeliveryLoop(sendMinidump, client._config.onSend, queue, client._logger) + const loop = new MinidumpDeliveryLoop(sendMinidump, client._config.onSendError, queue, client._logger) app.whenReady().then(() => { const stateManagerPlugin = client.getPlugin('clientStateManager') diff --git a/packages/plugin-electron-deliver-minidumps/event-serialisation.js b/packages/plugin-electron-deliver-minidumps/event-serialisation.js new file mode 100644 index 0000000000..15c997a867 --- /dev/null +++ b/packages/plugin-electron-deliver-minidumps/event-serialisation.js @@ -0,0 +1,138 @@ +const Event = require('@bugsnag/core/event') +const Session = require('@bugsnag/core/session') +const Breadcrumb = require('@bugsnag/core/breadcrumb') + +const supportedProperties = [ + 'app', + 'breadcrumbs', + 'context', + 'device', + 'featureFlags', + 'groupingHash', + 'metaData', + 'request', + 'session', + 'severity', + 'unhandled', + 'user' +] + +function hasValueForProperty (object, name) { + if (!Object.prototype.hasOwnProperty.call(object, name)) { + return false + } + + const value = object[name] + + if (typeof value === 'undefined' || value === null) { + return false + } + + if (Array.isArray(value) && value.length === 0) { + return false + } + + if (typeof value === 'object' && Object.keys(value).length === 0) { + return false + } + + return true +} + +function serialiseEvent (event) { + const json = event.toJSON() + const serialisedEvent = {} + + for (let i = 0; i < supportedProperties.length; ++i) { + const property = supportedProperties[i] + + if (!hasValueForProperty(json, property)) { + continue + } + + // breadcrumbs and session information need to be encoded further + if (property === 'breadcrumbs') { + serialisedEvent.breadcrumbs = json.breadcrumbs.map(breadcrumb => breadcrumb.toJSON()) + } else if (property === 'session') { + serialisedEvent.session = json.session.toJSON() + } else if (property === 'metaData') { + serialisedEvent.metadata = json[property] + } else { + serialisedEvent[property] = json[property] + } + } + + // set the severityReason if the severity was changed + // 'severity' is not set by default so if it's present then the user must have + // set it in a callback + if (serialisedEvent.severity) { + serialisedEvent.severityReason = { type: 'userCallbackSetSeverity' } + } + + return serialisedEvent +} + +function deserialiseEvent (json, minidumpPath) { + if (!json || typeof json !== 'object') { + return + } + + const event = new Event('Native Crash', 'Event created for a native crash', [], {}) + + if (hasValueForProperty(json, 'app')) { + event.app = json.app + } + + if (hasValueForProperty(json, 'breadcrumbs')) { + event.breadcrumbs = json.breadcrumbs.map( + breadcrumb => new Breadcrumb( + breadcrumb.name, + breadcrumb.metaData, + breadcrumb.type, + new Date(breadcrumb.timestamp) + ) + ) + } + + if (hasValueForProperty(json, 'context')) { + event.context = json.context + } + + if (hasValueForProperty(json, 'device')) { + event.device = json.device + } + + if (hasValueForProperty(json, 'featureFlags')) { + for (let i = 0; i < json.featureFlags.length; ++i) { + const flag = json.featureFlags[i] + + event.addFeatureFlag(flag.featureFlag, flag.variant) + } + } + + if (hasValueForProperty(json, 'metadata')) { + event._metadata = json.metadata + } + + if (hasValueForProperty(json, 'session')) { + const session = new Session() + session.id = json.session.id + session.startedAt = new Date(json.session.startedAt) + session._handled = json.session.events.handled + session._unhandled = json.session.events.unhandled + + event._session = session + } + + if (hasValueForProperty(json, 'user')) { + event._user = json.user + } + + // this doesn't exist on the Event class, but could be helpful in onSendError + // callbacks as it allows the user to find the related minidump + event.minidumpPath = minidumpPath + + return event +} + +module.exports = { serialiseEvent, deserialiseEvent } diff --git a/packages/plugin-electron-deliver-minidumps/minidump-loop.js b/packages/plugin-electron-deliver-minidumps/minidump-loop.js index 38ff7c4a4a..739c49359b 100644 --- a/packages/plugin-electron-deliver-minidumps/minidump-loop.js +++ b/packages/plugin-electron-deliver-minidumps/minidump-loop.js @@ -1,12 +1,18 @@ const { readFile } = require('fs').promises +const runSyncCallbacks = require('@bugsnag/core/lib/sync-callback-runner') +const { serialiseEvent, deserialiseEvent } = require('./event-serialisation') module.exports = class MinidumpDeliveryLoop { - constructor (sendMinidump, onSend = () => true, minidumpQueue, logger) { + constructor (sendMinidump, onSendError, minidumpQueue, logger) { this._sendMinidump = sendMinidump - this._onSend = onSend this._minidumpQueue = minidumpQueue this._logger = logger this._running = false + + // onSendError can be a function or an array of functions + this._onSendError = typeof onSendError === 'function' + ? [onSendError] + : onSendError } _onerror (err, minidump) { @@ -31,24 +37,34 @@ module.exports = class MinidumpDeliveryLoop { } async _deliverMinidump (minidump) { - const event = await this._readEvent(minidump.eventPath) - const shouldSendMinidump = event && await this._onSend(event) + let shouldSendMinidump = true + let eventJson = await this._readEvent(minidump.eventPath) - if (shouldSendMinidump === false) { - this._minidumpQueue.remove(minidump) - this._scheduleSelf() - } else { + if (eventJson && this._onSendError.length > 0) { + const event = deserialiseEvent(eventJson, minidump.minidumpPath) + const ignore = runSyncCallbacks(this._onSendError, event, 'onSendError', this._logger) + + // i.e. we SHOULD send the minidump if we SHOULD NOT ignore the event + shouldSendMinidump = !ignore + + // reserialise the event for sending in the form payload + eventJson = serialiseEvent(event) + } + + if (shouldSendMinidump) { try { - await this._sendMinidump(minidump.minidumpPath, event) + await this._sendMinidump(minidump.minidumpPath, eventJson) - // if we had a successful delivery - remove the minidump from the queue, and schedule the next + // if we had a successful delivery - remove the minidump from the queue this._minidumpQueue.remove(minidump) } catch (e) { this._onerror(e, minidump) - } finally { - this._scheduleSelf() } + } else { + this._minidumpQueue.remove(minidump) } + + this._scheduleSelf() } async _deliverNextMinidump () { diff --git a/packages/plugin-electron-deliver-minidumps/package.json b/packages/plugin-electron-deliver-minidumps/package.json index 9347161800..ce050b10d1 100644 --- a/packages/plugin-electron-deliver-minidumps/package.json +++ b/packages/plugin-electron-deliver-minidumps/package.json @@ -13,6 +13,7 @@ }, "files": [ "deliver-minidumps.js", + "event-serialisation.js", "minidump-loop.js", "minidump-queue.js", "send-minidump.js" diff --git a/packages/plugin-electron-deliver-minidumps/test/minidump-loop.test.ts b/packages/plugin-electron-deliver-minidumps/test/minidump-loop.test.ts index 40c4cdc911..680beed554 100644 --- a/packages/plugin-electron-deliver-minidumps/test/minidump-loop.test.ts +++ b/packages/plugin-electron-deliver-minidumps/test/minidump-loop.test.ts @@ -1,4 +1,6 @@ import EventEmitter from 'events' +import Session from '@bugsnag/core/session' +import Breadcrumb from '@bugsnag/core/breadcrumb' import NetworkStatus from '@bugsnag/electron-network-status' import MinidumpDeliveryLoop from '../minidump-loop' @@ -27,7 +29,7 @@ const runDeliveryLoop = async (times: number = 1) => { } describe('electron-minidump-delivery: minidump-loop', () => { - const onSend = () => true + const onSendCallbacks = [] const logger = { error: () => {} } @@ -40,7 +42,7 @@ describe('electron-minidump-delivery: minidump-loop', () => { { minidumpPath: 'minidump-path2', eventPath: 'event-path2' } ) - const loop = new MinidumpDeliveryLoop(sendMinidump, onSend, minidumpQueue, logger) + const loop = new MinidumpDeliveryLoop(sendMinidump, onSendCallbacks, minidumpQueue, logger) loop.start() await runDeliveryLoop() @@ -56,7 +58,7 @@ describe('electron-minidump-delivery: minidump-loop', () => { { minidumpPath: 'minidump-path2' } ) - const loop = new MinidumpDeliveryLoop(sendMinidump, onSend, minidumpQueue, logger) + const loop = new MinidumpDeliveryLoop(sendMinidump, onSendCallbacks, minidumpQueue, logger) loop.start() await runDeliveryLoop() @@ -66,7 +68,7 @@ describe('electron-minidump-delivery: minidump-loop', () => { }) }) - it('skips events blocked by onSend', async () => { + it('skips events blocked by an on send callback', async () => { const sendMinidump = createSendMinidump() const minidumpQueue = createQueue( { minidumpPath: 'minidump-path1', eventPath: 'event-path1' }, @@ -82,6 +84,148 @@ describe('electron-minidump-delivery: minidump-loop', () => { expect(minidumpQueue.remove).toBeCalledTimes(2) }) + it('allows on send callback to mutate the event', async () => { + const sendMinidump = createSendMinidump() + const minidumpQueue = createQueue( + { minidumpPath: 'minidump-path', eventPath: 'event-path' } + ) + + let eventMinidumpPath + const onSendError = event => { + event.addMetadata('abc', { x: 1, y: 2 }) + event.addMetadata('abc', 'z', 3) + event.addMetadata('minidump', { path: event.minidumpPath }) + + event.addFeatureFlag('a', 1) + event.context = 'contextual' + event.setUser('a', 'b', 'c') + event.breadcrumbs.push(new Breadcrumb('crumby', { a: 1 }, 'manual', new Date('2020-01-01T00:00:00Z'))) + + const session = new Session() + session.id = 'an session ID' + session.startedAt = new Date('2020-01-02T00:00:00Z') + session._handled = 0 + session._unhandled = 1 + + event._session = session + + event.groupingHash = 'grouper' + event.request = { food: 'please' } + event.severity = 'info' + event.unhandled = false + + eventMinidumpPath = event.minidumpPath + } + + const loop = new MinidumpDeliveryLoop(sendMinidump, onSendError, minidumpQueue, logger) + loop.start() + + await runDeliveryLoop(1) + + expect(sendMinidump).toBeCalledWith('minidump-path', { + breadcrumbs: [ + { + name: 'crumby', + metaData: { a: 1 }, + type: 'manual', + timestamp: new Date('2020-01-01T00:00:00Z') + } + ], + context: 'contextual', + featureFlags: [ + { featureFlag: 'a', variant: '1' } + ], + groupingHash: 'grouper', + metadata: { + abc: { x: 1, y: 2, z: 3 }, + minidump: { path: 'minidump-path' } + }, + request: { food: 'please' }, + session: { + events: { handled: 0, unhandled: 1 }, + id: 'an session ID', + startedAt: new Date('2020-01-02T00:00:00Z') + }, + severity: 'info', + severityReason: { type: 'userCallbackSetSeverity' }, + user: { + email: 'b', + id: 'a', + name: 'c' + } + }) + + expect(eventMinidumpPath).toBe('minidump-path') + + expect(minidumpQueue.remove).toBeCalledWith({ + minidumpPath: 'minidump-path', + eventPath: 'event-path' + }) + }) + + it('stops calling callbacks when an event is blocked by an earlier callback', async () => { + const sendMinidump = createSendMinidump() + const minidumpQueue = createQueue( + { minidumpPath: 'minidump-path1', eventPath: 'event-path1' }, + { minidumpPath: 'minidump-path2', eventPath: 'event-path2' } + ) + + const callbacks = [jest.fn(() => true), jest.fn(() => false), jest.fn(() => true)] + + const loop = new MinidumpDeliveryLoop(sendMinidump, callbacks, minidumpQueue, logger) + loop.start() + + await runDeliveryLoop(2) + + expect(sendMinidump).toBeCalledTimes(0) + expect(minidumpQueue.remove).toBeCalledTimes(2) + + // the callbacks are called twice as there are two minidumps and are called + // in order of most recently added -> least recently added + expect(callbacks[2]).toHaveBeenCalledTimes(2) + expect(callbacks[1]).toHaveBeenCalledTimes(2) + expect(callbacks[0]).not.toHaveBeenCalled() + }) + + it('handles callbacks that throw errors', async () => { + const sendMinidump = createSendMinidump() + const minidumpQueue = createQueue( + { minidumpPath: 'minidump-path1', eventPath: 'event-path1' }, + { minidumpPath: 'minidump-path2', eventPath: 'event-path2' } + ) + const error = new Error('oh no!') + + const callbacks = [ + jest.fn(() => true), + jest.fn(() => true), + jest.fn(() => { throw error }), + jest.fn(() => true) + ] + + const logError = jest.fn() + + const loop = new MinidumpDeliveryLoop(sendMinidump, callbacks, minidumpQueue, { error: logError }) + loop.start() + + await runDeliveryLoop(2) + + expect(sendMinidump).toBeCalledTimes(2) + expect(minidumpQueue.remove).toBeCalledTimes(2) + + expect(callbacks[3]).toHaveBeenCalledTimes(2) + expect(callbacks[2]).toHaveBeenCalledTimes(2) + expect(callbacks[1]).toHaveBeenCalledTimes(2) + expect(callbacks[0]).toHaveBeenCalledTimes(2) + + // there are two minidumps so the error should be thrown & logged twice + // each thrown error results in two logs - one for an 'error occurred...' + // message and one for the error object itself + expect(logError).toHaveBeenNthCalledWith(1, 'Error occurred in onSendError callback, continuing anyway…') + expect(logError).toHaveBeenNthCalledWith(2, error) + expect(logError).toHaveBeenNthCalledWith(3, 'Error occurred in onSendError callback, continuing anyway…') + expect(logError).toHaveBeenNthCalledWith(4, error) + }) + it('stops when the queue is exhausted', async () => { const sendMinidump = createSendMinidump() const minidumpQueue = createQueue( @@ -89,7 +233,7 @@ describe('electron-minidump-delivery: minidump-loop', () => { { minidumpPath: 'minidump-path2', eventPath: 'event-path2' } ) - const loop = new MinidumpDeliveryLoop(sendMinidump, onSend, minidumpQueue, logger) + const loop = new MinidumpDeliveryLoop(sendMinidump, onSendCallbacks, minidumpQueue, logger) loop.start() await runDeliveryLoop(3) @@ -100,7 +244,7 @@ describe('electron-minidump-delivery: minidump-loop', () => { expect(jest.getTimerCount()).toBe(0) }) - it('attempts redlivery', async () => { + it('attempts redelivery', async () => { const retryError: any = new Error() retryError.isRetryable = true const sendMinidump = jest.fn() @@ -112,7 +256,7 @@ describe('electron-minidump-delivery: minidump-loop', () => { { minidumpPath: 'minidump-path2', eventPath: 'event-path2' } ) - const loop = new MinidumpDeliveryLoop(sendMinidump, onSend, minidumpQueue, logger) + const loop = new MinidumpDeliveryLoop(sendMinidump, onSendCallbacks, minidumpQueue, logger) loop.start() await runDeliveryLoop(2) @@ -134,7 +278,7 @@ describe('electron-minidump-delivery: minidump-loop', () => { { minidumpPath: 'minidump-path2', eventPath: 'event-path2' } ) - const loop = new MinidumpDeliveryLoop(sendMinidump, onSend, minidumpQueue, logger) + const loop = new MinidumpDeliveryLoop(sendMinidump, onSendCallbacks, minidumpQueue, logger) loop.watchNetworkStatus(statusWatcher) // ensure that nothing is delivered while disconnected @@ -158,7 +302,7 @@ describe('electron-minidump-delivery: minidump-loop', () => { { minidumpPath: 'minidump-path2', eventPath: 'event-path2' } ) - const loop = new MinidumpDeliveryLoop(sendMinidump, onSend, minidumpQueue, logger) + const loop = new MinidumpDeliveryLoop(sendMinidump, onSendCallbacks, minidumpQueue, logger) loop.watchNetworkStatus(statusWatcher) // ensure that the first minidump is delivered diff --git a/test/electron/features/feature-flags.feature b/test/electron/features/feature-flags.feature index 1e7a14198f..d118e61128 100644 --- a/test/electron/features/feature-flags.feature +++ b/test/electron/features/feature-flags.feature @@ -224,7 +224,8 @@ Scenario: feature flags are attached to native crashes from the main process | minidumps | 0 | | sessions | 1 | When I click "main-process-crash" - And I launch an app + And I launch an app with configuration: + | bugsnag | on-send-error | Then the total requests received by the server matches: | events | 0 | | minidumps | 1 | @@ -250,7 +251,8 @@ Scenario: feature flags can be cleared entirely in the main process with a nativ | sessions | 1 | When I click "main-process-clear-feature-flags-now" And I click "main-process-crash" - And I launch an app + And I launch an app with configuration: + | bugsnag | on-send-error | Then the total requests received by the server matches: | events | 0 | | minidumps | 1 | @@ -265,7 +267,7 @@ Scenario: feature flags can be cleared entirely in the main process with a nativ Scenario: feature flags are attached to native crashes from a renderer process Given I launch an app with configuration: - | bugsnag | feature-flags | + | bugsnag | feature-flags-on-send-error | | renderer_config | { "featureFlags": [{ "name": "from renderer config" }] } | Then the total requests received by the server matches: | events | 0 | @@ -289,7 +291,7 @@ Scenario: feature flags are attached to native crashes from a renderer process Scenario: feature flags can be cleared entirely in a renderer process with a native crash Given I launch an app with configuration: - | bugsnag | feature-flags | + | bugsnag | feature-flags-on-send-error | | renderer_config | { "featureFlags": [{ "name": "from renderer config" }] } | Then the total requests received by the server matches: | events | 0 | diff --git a/test/electron/features/native-crash.feature b/test/electron/features/native-crash.feature index 359d0c9548..5ff9efcdbd 100644 --- a/test/electron/features/native-crash.feature +++ b/test/electron/features/native-crash.feature @@ -1,14 +1,14 @@ Feature: Native Errors Scenario: A minidump is uploaded on native error - When I launch an app + Given I launch an app Then the total requests received by the server matches: | events | 0 | | minidumps | 0 | | sessions | 1 | - When I click "main-process-crash" - And I launch an app + And I launch an app with configuration: + | bugsnag | on-send-error | Then the total requests received by the server matches: | events | 0 | | minidumps | 1 | @@ -17,16 +17,16 @@ Feature: Native Errors And minidump request 0 contains a form field named "event" matching "minidump-event.json" Scenario: A native error occurs after a handled event - When I launch an app - And I click "custom-breadcrumb" + Given I launch an app + When I click "custom-breadcrumb" And I click "main-notify" Then the total requests received by the server matches: | events | 1 | | minidumps | 0 | | sessions | 1 | - When I click "main-process-crash" - And I launch an app + And I launch an app with configuration: + | bugsnag | on-send-error | Then the total requests received by the server matches: | events | 1 | | minidumps | 1 | @@ -41,14 +41,12 @@ Feature: Native Errors | minidumps | 0 | | events | 0 | | sessions | 1 | - When I click "main-process-crash" And I launch an app with no network Then the total requests received by the server matches: | minidumps | 0 | | events | 0 | | sessions | 1 | - When the app gains network connectivity Then the total requests received by the server matches: | events | 0 | @@ -62,14 +60,12 @@ Feature: Native Errors | minidumps | 0 | | events | 0 | | sessions | 0 | - When I click "main-process-crash" And I launch an app Then the total requests received by the server matches: | minidumps | 0 | | events | 0 | | sessions | 0 | - When I click "main-process-crash" And the server becomes reachable And I launch an app @@ -86,14 +82,12 @@ Feature: Native Errors | minidumps | 0 | | events | 0 | | sessions | 0 | - When I click "main-process-crash" And I launch an app with no network Then the total requests received by the server matches: | minidumps | 0 | | events | 0 | | sessions | 0 | - When I click "main-process-crash" And I launch an app Then the total requests received by the server matches: @@ -102,12 +96,12 @@ Feature: Native Errors | sessions | 4 | Scenario: Crash in the renderer process - When I launch an app + Given I launch an app with configuration: + | bugsnag | on-send-error | Then the total requests received by the server matches: | events | 0 | | minidumps | 0 | | sessions | 1 | - When I click "renderer-process-crash" Then the total requests received by the server matches: | events | 0 | @@ -117,15 +111,16 @@ Feature: Native Errors And minidump request 0 contains a form field named "event" matching "minidump-event.json" Scenario: Crash in the renderer and main processes - When I launch an app + Given I launch an app with configuration: + | bugsnag | on-send-error | Then the total requests received by the server matches: | events | 0 | | minidumps | 0 | | sessions | 1 | - When I click "renderer-and-main-process-crashes" And I wait for 2 seconds - And I launch an app + When I launch an app with configuration: + | bugsnag | on-send-error | Then the total requests received by the server matches: | events | 0 | | minidumps | 2 | diff --git a/test/electron/features/support/steps/request-steps.js b/test/electron/features/support/steps/request-steps.js index ec8322af7f..5058a2fdb5 100644 --- a/test/electron/features/support/steps/request-steps.js +++ b/test/electron/features/support/steps/request-steps.js @@ -138,7 +138,7 @@ Then('minidump request {int} has no feature flags', async (index) => { expect(actual).toHaveProperty('events') expect(actual.events).toHaveLength(1) - expect(actual.events[0]).toHaveProperty('featureFlags', []) + expect(actual.events[0]).not.toHaveProperty('featureFlags') }) Then('the total requests received by the server matches:', async (data) => { diff --git a/test/electron/fixtures/app/configs/feature-flags-on-send-error.js b/test/electron/fixtures/app/configs/feature-flags-on-send-error.js new file mode 100644 index 0000000000..c0d8850553 --- /dev/null +++ b/test/electron/fixtures/app/configs/feature-flags-on-send-error.js @@ -0,0 +1,4 @@ +const featureFlagsConfig = require('./feature-flags') +const onSendErrorConfig = require('./on-send-error') + +module.exports = () => Object.assign({}, featureFlagsConfig(), onSendErrorConfig()) diff --git a/test/electron/fixtures/app/configs/on-send-error.js b/test/electron/fixtures/app/configs/on-send-error.js new file mode 100644 index 0000000000..3fcd616922 --- /dev/null +++ b/test/electron/fixtures/app/configs/on-send-error.js @@ -0,0 +1,9 @@ +module.exports = () => { + return { + onSendError (event) { + event.context = 'checkout page' + event.addMetadata('account', { type: 'VIP', verified: true }) + event.addMetadata('account', 'status', "it's complicated") + } + } +} diff --git a/test/electron/fixtures/events/minidump-event.json b/test/electron/fixtures/events/minidump-event.json index 2cb6dc5e49..bb4ba5b595 100644 --- a/test/electron/fixtures/events/minidump-event.json +++ b/test/electron/fixtures/events/minidump-event.json @@ -31,6 +31,7 @@ } } ], + "context": "checkout page", "device": { "runtimeVersions": { "node": "{TYPE:string}", @@ -42,6 +43,11 @@ "osVersion": "{REGEX:\\d+\\.\\d+}" }, "metadata": { + "account": { + "type": "VIP", + "verified": true, + "status": "it's complicated" + }, "app": { "name": "Runner", "CFBundleVersion": "{PLATFORM_MACOS:1.0.2}" diff --git a/test/electron/fixtures/events/minidump-plus-handled-event.json b/test/electron/fixtures/events/minidump-plus-handled-event.json index e52f89e32b..59045afec6 100644 --- a/test/electron/fixtures/events/minidump-plus-handled-event.json +++ b/test/electron/fixtures/events/minidump-plus-handled-event.json @@ -31,6 +31,7 @@ } } ], + "context": "checkout page", "device": { "runtimeVersions": { "node": "{TYPE:string}", @@ -42,6 +43,11 @@ "osVersion": "{REGEX:\\d+\\.\\d+}" }, "metadata": { + "account": { + "type": "VIP", + "verified": true, + "status": "it's complicated" + }, "app": { "name": "Runner", "CFBundleVersion": "{PLATFORM_MACOS:1.0.2}" diff --git a/test/electron/fixtures/events/second-minidump-event.json b/test/electron/fixtures/events/second-minidump-event.json index 8b07b51507..d31e14f86c 100644 --- a/test/electron/fixtures/events/second-minidump-event.json +++ b/test/electron/fixtures/events/second-minidump-event.json @@ -42,6 +42,11 @@ "osVersion": "{REGEX:\\d+\\.\\d+}" }, "metadata": { + "account": { + "type": "VIP", + "verified": true, + "status": "it's complicated" + }, "app": { "name": "Runner", "CFBundleVersion": "{PLATFORM_MACOS:1.0.2}"