From d37abc87314cd45b8d782594edfcb39cb21d77b1 Mon Sep 17 00:00:00 2001 From: Yousif Ahmed Date: Mon, 20 Nov 2023 13:56:00 +0000 Subject: [PATCH] (plugin-electron-client-state-persistence) Add unit tests for disabled NativeClient --- .../package.json | 3 +- .../test/client-state-persistence.test.ts | 257 +++++++++--------- 2 files changed, 129 insertions(+), 131 deletions(-) diff --git a/packages/plugin-electron-client-state-persistence/package.json b/packages/plugin-electron-client-state-persistence/package.json index 908f07fc54..2b92c476a3 100644 --- a/packages/plugin-electron-client-state-persistence/package.json +++ b/packages/plugin-electron-client-state-persistence/package.json @@ -41,7 +41,8 @@ "devDependencies": { "@bugsnag/core": "^7.19.0", "@bugsnag/plugin-electron-client-state-manager": "^7.19.0", - "@types/bindings": "^1.5.0" + "@types/bindings": "^1.5.0", + "@bugsnag/electron-test-helpers": "^7.19.0" }, "peerDependencies": { "@bugsnag/core": "^7.9.2" diff --git a/packages/plugin-electron-client-state-persistence/test/client-state-persistence.test.ts b/packages/plugin-electron-client-state-persistence/test/client-state-persistence.test.ts index 1e4cdb1fe8..ee7aee0d84 100644 --- a/packages/plugin-electron-client-state-persistence/test/client-state-persistence.test.ts +++ b/packages/plugin-electron-client-state-persistence/test/client-state-persistence.test.ts @@ -1,114 +1,94 @@ -import Client from '@bugsnag/core/client' import { plugin } from '../' -import { Breadcrumb, Logger } from '@bugsnag/core' +import { Breadcrumb } from '@bugsnag/core' import stateManager from '@bugsnag/plugin-electron-client-state-manager' +import { makeClientForPlugin } from '@bugsnag/electron-test-helpers' + +const schema = { + enabledErrorTypes: { + defaultValue: () => ({ + unhandledExceptions: true, + unhandledRejections: true, + nativeCrashes: true + }), + allowPartialObject: true, + validate: value => true + } +} + +function makeClient (NativeClient: object, config?: object) { + return makeClientForPlugin({ plugins: [stateManager, plugin(NativeClient)], schema, config }) +} describe('plugin: electron client sync', () => { it('updates context', done => { - const c = new Client({ - apiKey: 'api_key', - plugins: [ - stateManager, - plugin({ - updateContext: (update: any) => { - expect(update).toBe('1234') - done() - } - }) - ] + const { client } = makeClient({ + updateContext: (update: any) => { + expect(update).toBe('1234') + done() + } }) - c.setContext('1234') + client.setContext('1234') }) it('updates metadata', done => { - const c = new Client({ - apiKey: 'api_key', - plugins: [ - stateManager, - plugin({ - updateMetadata: (key: string, updates: any) => { - expect(key).toBe('widget') - expect(updates).toEqual({ - id: '14', - count: 340 - }) - done() - } + const { client } = makeClient({ + updateMetadata: (key: string, updates: any) => { + expect(key).toBe('widget') + expect(updates).toEqual({ + id: '14', + count: 340 }) - ] + done() + } }) - c.addMetadata('widget', { id: '14', count: 340 }) - expect(c.getMetadata('widget')).toEqual({ id: '14', count: 340 }) + client.addMetadata('widget', { id: '14', count: 340 }) + expect(client.getMetadata('widget')).toEqual({ id: '14', count: 340 }) }) it('clears metadata', done => { - const c = new Client({ - apiKey: 'api_key', - plugins: [ - stateManager, - plugin({ - addMetadata: () => {}, - clearMetadata: () => {} - }) - ] + const { client } = makeClient({ + addMetadata: () => {}, + clearMetadata: () => {} }) - c.addMetadata('widget', { id: '14', count: 340 }) - expect(c.getMetadata('widget')).toEqual({ id: '14', count: 340 }) - c.clearMetadata('widget', 'count') - expect(c.getMetadata('widget', 'count')).toBeUndefined() - c.clearMetadata('widget') - expect(c.getMetadata('widget')).toBeUndefined() + client.addMetadata('widget', { id: '14', count: 340 }) + expect(client.getMetadata('widget')).toEqual({ id: '14', count: 340 }) + client.clearMetadata('widget', 'count') + expect(client.getMetadata('widget', 'count')).toBeUndefined() + client.clearMetadata('widget') + expect(client.getMetadata('widget')).toBeUndefined() done() }) it('updates user', done => { - const c = new Client({ - apiKey: 'api_key', - plugins: [ - stateManager, - plugin({ - updateUser: (id: string, email: string, name: string) => { - expect(id).toBe('1234') - expect(name).toBe('Ben') - expect(email).toBe('user@example.com') - done() - } - }) - ] + const { client } = makeClient({ + updateUser: (id: string, email: string, name: string) => { + expect(id).toBe('1234') + expect(name).toBe('Ben') + expect(email).toBe('user@example.com') + done() + } }) - c.setUser('1234', 'user@example.com', 'Ben') - expect(c.getUser()).toEqual({ id: '1234', name: 'Ben', email: 'user@example.com' }) + client.setUser('1234', 'user@example.com', 'Ben') + expect(client.getUser()).toEqual({ id: '1234', name: 'Ben', email: 'user@example.com' }) }) it('syncs breadcrumbs', (done) => { - const c = new Client({ - apiKey: 'api_key', - plugins: [ - stateManager, - plugin({ - leaveBreadcrumb: ({ message, metadata, type, timestamp }: Breadcrumb) => { - expect(message).toBe('Spin') - expect(type).toBe('manual') - expect(metadata).toEqual({ direction: 'ccw', deg: '90' }) - expect(timestamp).toBeTruthy() - done() - } - }) - ] + const { client } = makeClient({ + leaveBreadcrumb: ({ message, metadata, type, timestamp }: Breadcrumb) => { + expect(message).toBe('Spin') + expect(type).toBe('manual') + expect(metadata).toEqual({ direction: 'ccw', deg: '90' }) + expect(timestamp).toBeTruthy() + done() + } }) - c.leaveBreadcrumb('Spin', { direction: 'ccw', deg: '90' }) + client.leaveBreadcrumb('Spin', { direction: 'ccw', deg: '90' }) }) it('does not sync breadcrumbs that are cancelled by an onBreadcrumb callback', () => { const NativeClient = { leaveBreadcrumb: jest.fn() } - const client = new Client({ - apiKey: 'api_key', - plugins: [ - stateManager, - plugin(NativeClient) - ] - }) + const { client } = makeClient(NativeClient) client.addOnBreadcrumb(breadcrumb => { if (breadcrumb.message === 'skip me') { @@ -138,13 +118,7 @@ describe('plugin: electron client sync', () => { it('updates feature flags', () => { const updateFeatureFlags = jest.fn() - const client = new Client({ - apiKey: 'api_key', - plugins: [ - stateManager, - plugin({ updateFeatureFlags }) - ] - }) + const { client } = makeClient({ updateFeatureFlags }) client.addFeatureFlag('a', 'b') client.addFeatureFlags([{ name: 'c', variant: null }, { name: 'd', variant: 'e' }]) @@ -163,13 +137,7 @@ describe('plugin: electron client sync', () => { it('clears a single feature flag', () => { const updateFeatureFlags = jest.fn() - const client = new Client({ - apiKey: 'api_key', - plugins: [ - stateManager, - plugin({ updateFeatureFlags }) - ] - }) + const { client } = makeClient({ updateFeatureFlags }) client.addFeatureFlag('a', 'b') client.addFeatureFlags([{ name: 'c', variant: null }, { name: 'd', variant: 'e' }]) @@ -193,13 +161,7 @@ describe('plugin: electron client sync', () => { it('clears all feature flags', () => { const updateFeatureFlags = jest.fn() - const client = new Client({ - apiKey: 'api_key', - plugins: [ - stateManager, - plugin({ updateFeatureFlags }) - ] - }) + const { client } = makeClient({ updateFeatureFlags }) client.addFeatureFlag('a', 'b') client.addFeatureFlags([{ name: 'c', variant: null }, { name: 'd', variant: 'e' }]) @@ -217,81 +179,116 @@ describe('plugin: electron client sync', () => { expect(updateFeatureFlags).toHaveBeenNthCalledWith(3, []) }) - function loggingClient (NativeClient: object): [Client, Logger] { - const logger = { - debug: jest.fn(), - warn: jest.fn(), - info: jest.fn(), - error: jest.fn() - } - const client = new Client({ - apiKey: 'api_key', - plugins: [stateManager, plugin(NativeClient)], - logger - }) - return [client, logger] - } - it('logs errors thrown from updating context', () => { - const [client, logger] = loggingClient({ + // const [client, logger] = loggingClient({ + // updateContext: () => { throw new Error('wrong thing') } + // }) + const { client } = makeClient({ updateContext: () => { throw new Error('wrong thing') } }) + client.setContext('some invalid context') - const error = logger.error as jest.Mock + const error = client._logger.error as jest.Mock expect(error.mock.calls.length).toBe(1) expect(error.mock.calls[0][0].message).toContain('wrong thing') }) it('logs errors thrown from adding breadcrumbs', () => { - const [client, logger] = loggingClient({ + const { client } = makeClient({ leaveBreadcrumb: () => { throw new Error('wrong thing') } }) client.leaveBreadcrumb('Spin', { direction: 'ccw', deg: '90' }) - const error = logger.error as jest.Mock + const error = client._logger.error as jest.Mock expect(error.mock.calls.length).toBe(1) expect(error.mock.calls[0][0].message).toContain('wrong thing') }) it('logs errors thrown from adding metadata', () => { - const [client, logger] = loggingClient({ + const { client } = makeClient({ updateMetadata: () => { throw new Error('wrong thing') } }) client.addMetadata('widget', { id: '14', count: 340 }) - const error = logger.error as jest.Mock + const error = client._logger.error as jest.Mock expect(error.mock.calls.length).toBe(1) expect(error.mock.calls[0][0].message).toContain('wrong thing') }) it('logs errors thrown from clearing metadata', () => { - const [client, logger] = loggingClient({ + const { client } = makeClient({ updateMetadata: () => { throw new Error('wrong thing') } }) client.clearMetadata('widget') - const error = logger.error as jest.Mock + const error = client._logger.error as jest.Mock expect(error.mock.calls.length).toBe(1) expect(error.mock.calls[0][0].message).toContain('wrong thing') }) it('logs errors thrown from updating user info', () => { - const [client, logger] = loggingClient({ + const { client } = makeClient({ updateUser: () => { throw new Error('wrong thing') } }) client.setUser('404', 'tim@example.com', undefined) - const error = logger.error as jest.Mock + const error = client._logger.error as jest.Mock expect(error.mock.calls.length).toBe(1) expect(error.mock.calls[0][0].message).toContain('wrong thing') }) it('logs errors thrown from updating feature flags', () => { - const [client, logger] = loggingClient({ + const { client } = makeClient({ updateFeatureFlags: () => { throw new Error('wrong thing') } }) client.addFeatureFlag('a', 'b') - const error = logger.error as jest.Mock + const error = client._logger.error as jest.Mock expect(error.mock.calls.length).toBe(1) expect(error.mock.calls[0][0].message).toContain('wrong thing') }) + + it('does not sync data to the NativeClient if enabledErrorTypes.nativeCrashes is disabled', () => { + const NativeClient = { + leaveBreadcrumb: jest.fn(), + updateUser: jest.fn(), + updateContext: jest.fn(), + updateMetadata: jest.fn(), + updateFeatureFlags: jest.fn() + } + + const { client } = makeClient(NativeClient, { enabledErrorTypes: { nativeCrashes: false } }) + client.leaveBreadcrumb('no sync') + client.setUser('1234', 'user@example.com', 'Ben') + client.setContext('no sync') + client.addMetadata('no sync', { id: '14', count: 340 }) + client.addFeatureFlag('no', 'sync') + + expect(NativeClient.leaveBreadcrumb).not.toHaveBeenCalled() + expect(NativeClient.updateUser).not.toHaveBeenCalled() + expect(NativeClient.updateContext).not.toHaveBeenCalled() + expect(NativeClient.updateMetadata).not.toHaveBeenCalled() + expect(NativeClient.updateFeatureFlags).not.toHaveBeenCalled() + }) + + it('does not sync data to the NativeClient if autoDetectErrors is disabled', () => { + const NativeClient = { + leaveBreadcrumb: jest.fn(), + updateUser: jest.fn(), + updateContext: jest.fn(), + updateMetadata: jest.fn(), + updateFeatureFlags: jest.fn() + } + + const { client } = makeClient(NativeClient, { autoDetectErrors: false }) + client.leaveBreadcrumb('no sync') + client.setUser('1234', 'user@example.com', 'Ben') + client.setContext('no sync') + client.addMetadata('no sync', { id: '14', count: 340 }) + client.addFeatureFlag('no', 'sync') + + expect(NativeClient.leaveBreadcrumb).not.toHaveBeenCalled() + expect(NativeClient.updateUser).not.toHaveBeenCalled() + expect(NativeClient.updateContext).not.toHaveBeenCalled() + expect(NativeClient.updateMetadata).not.toHaveBeenCalled() + expect(NativeClient.updateFeatureFlags).not.toHaveBeenCalled() + }) })