Skip to content

Commit

Permalink
Merge pull request #1880 from bugsnag/clone-client-unit-tests
Browse files Browse the repository at this point in the history
Add unit tests for clone-client
  • Loading branch information
imjoehaines authored Dec 6, 2022
2 parents 9e01911 + 5e3494a commit bfda2ce
Show file tree
Hide file tree
Showing 2 changed files with 292 additions and 1 deletion.
3 changes: 2 additions & 1 deletion packages/core/client.d.ts
Original file line number Diff line number Diff line change
Expand Up @@ -50,7 +50,8 @@ export default class ClientWithInternals<T extends Config = Config> extends Clie
_user: User

_metadata: { [key: string]: any }
_features: FeatureFlag | null[]
_features: Array<FeatureFlag | null>
_featuresIndex: { [key: string]: number }

startSession(): ClientWithInternals
resumeSession(): ClientWithInternals
Expand Down
290 changes: 290 additions & 0 deletions packages/core/test/lib/clone-client.test.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,290 @@
import Client from '../../client'
import clone from '../../lib/clone-client'

const apiKey = 'abcabcabcabcabcabcabc1234567890f'

describe('@bugsnag/core/lib/clone-client', () => {
describe('clone', () => {
it('clones a client', () => {
const original = new Client({ apiKey })
const cloned = clone(original)

expect(cloned._config.apiKey).toEqual(apiKey)
expect(cloned).not.toBe(original)
})

it('clones breadcrumbs', () => {
const original = new Client({ apiKey })
original.leaveBreadcrumb('abc', { a: 1 }, 'navigation')

const cloned = clone(original)

expect(cloned._breadcrumbs).not.toBe(original._breadcrumbs)
expect(cloned._breadcrumbs).toHaveLength(1)
expect(cloned._breadcrumbs[0].type).toEqual('navigation')
expect(cloned._breadcrumbs[0].message).toEqual('abc')
expect(cloned._breadcrumbs[0].metadata).toEqual({ a: 1 })

// leaving another breadcrumb should not affect the clone
original.leaveBreadcrumb('another', { x: 2 }, 'log')

expect(cloned._breadcrumbs).toHaveLength(1)
expect(cloned._breadcrumbs[0].type).toEqual('navigation')
expect(cloned._breadcrumbs[0].message).toEqual('abc')
expect(cloned._breadcrumbs[0].metadata).toEqual({ a: 1 })

expect(original._breadcrumbs).toHaveLength(2)
})

it('clones metadata', () => {
const original = new Client({ apiKey })
original.addMetadata('abc', { a: 1, b: 2, c: 3 })
original.addMetadata('xyz', { x: 9, y: 8, z: 7 })

const cloned = clone(original)
expect(cloned._metadata).not.toBe(original._metadata)
expect(cloned._metadata).toEqual({
abc: { a: 1, b: 2, c: 3 },
xyz: { x: 9, y: 8, z: 7 }
})

// changing the original's metadata should not affect the clone
original.addMetadata('abc', { d: 4 })
original.clearMetadata('abc', 'c')
original.clearMetadata('xyz')

expect(cloned._metadata).toEqual({
abc: { a: 1, b: 2, c: 3 },
xyz: { x: 9, y: 8, z: 7 }
})

expect(original._metadata).toEqual({ abc: { a: 1, b: 2, d: 4 } })
})

it('clones feature flags', () => {
const original = new Client({ apiKey })
original.addFeatureFlag('a', '1')
original.addFeatureFlags([
{ name: 'b', variant: '2' },
{ name: 'c' }
])

const cloned = clone(original)
expect(cloned._features).not.toBe(original._features)
expect(cloned._features).toEqual([
{ name: 'a', variant: '1' },
{ name: 'b', variant: '2' },
{ name: 'c', variant: null }
])
expect(cloned._featuresIndex).toEqual({ a: 0, b: 1, c: 2 })

// changing the original's feature flags should not affect the clone
original.clearFeatureFlags()

expect(cloned._features).toEqual([
{ name: 'a', variant: '1' },
{ name: 'b', variant: '2' },
{ name: 'c', variant: null }
])
expect(cloned._featuresIndex).toEqual({ a: 0, b: 1, c: 2 })
expect(original._features).toEqual([])
expect(original._featuresIndex).toEqual({})
})

it('clones user information', () => {
const original = new Client({ apiKey })
original.setUser('123', '[email protected]', 'bug snag')

const cloned = clone(original)
expect(cloned.getUser()).toEqual({
id: '123',
email: '[email protected]',
name: 'bug snag'
})
expect(cloned._user).not.toBe(original._user)

// changing the original's user should not affect the clone
original.setUser()

expect(cloned.getUser()).toEqual({
id: '123',
email: '[email protected]',
name: 'bug snag'
})
expect(original.getUser()).toEqual({})
})

it('clones context', () => {
const original = new Client({ apiKey })
original.setContext('contextual')

const cloned = clone(original)
expect(cloned.getContext()).toEqual('contextual')

// changing the original's context should not affect the clone
original.setContext('lautxetnoc')

expect(cloned.getContext()).toEqual('contextual')
expect(original.getContext()).toEqual('lautxetnoc')
})

it('clones on error callbacks', () => {
const onError1 = jest.fn()
const onError2 = jest.fn()

const original = new Client({ apiKey })
original.addOnError(onError1)

const cloned = clone(original)
expect(cloned._cbs.e).not.toBe(original._cbs.e)

// @ts-ignore
cloned._cbs.e.forEach(cb => { cb() })
expect(onError1).toHaveBeenCalledTimes(1)
expect(onError2).toHaveBeenCalledTimes(0)

// adding a new callback should not affect the clone
original.addOnError(onError2)

// @ts-ignore
cloned._cbs.e.forEach(cb => { cb() })
expect(onError1).toHaveBeenCalledTimes(2)
expect(onError2).toHaveBeenCalledTimes(0)

// @ts-ignore
original._cbs.e.forEach(cb => { cb() })
expect(onError1).toHaveBeenCalledTimes(3)
expect(onError2).toHaveBeenCalledTimes(1)
})

it('clones on session callbacks', () => {
const onSession1 = jest.fn()
const onSession2 = jest.fn()

const original = new Client({ apiKey })
original.addOnSession(onSession1)

const cloned = clone(original)
expect(cloned._cbs.s).not.toBe(original._cbs.s)

// @ts-ignore
cloned._cbs.s.forEach(cb => { cb() })
expect(onSession1).toHaveBeenCalledTimes(1)
expect(onSession2).toHaveBeenCalledTimes(0)

// adding a new callback should not affect the clone
original.addOnSession(onSession2)

// @ts-ignore
cloned._cbs.s.forEach(cb => { cb() })
expect(onSession1).toHaveBeenCalledTimes(2)
expect(onSession2).toHaveBeenCalledTimes(0)

// @ts-ignore
original._cbs.s.forEach(cb => { cb() })
expect(onSession1).toHaveBeenCalledTimes(3)
expect(onSession2).toHaveBeenCalledTimes(1)
})

it('clones on session payload callbacks', () => {
const onSessionPayload1 = jest.fn()
const onSessionPayload2 = jest.fn()

const original = new Client({ apiKey })
original._addOnSessionPayload(onSessionPayload1)

const cloned = clone(original)
expect(cloned._cbs.sp).not.toBe(original._cbs.sp)

// @ts-ignore
cloned._cbs.sp.forEach(cb => { cb() })
expect(onSessionPayload1).toHaveBeenCalledTimes(1)
expect(onSessionPayload2).toHaveBeenCalledTimes(0)

// adding a new callback should not affect the clone
original._addOnSessionPayload(onSessionPayload2)

// @ts-ignore
cloned._cbs.sp.forEach(cb => { cb() })
expect(onSessionPayload1).toHaveBeenCalledTimes(2)
expect(onSessionPayload2).toHaveBeenCalledTimes(0)

// @ts-ignore
original._cbs.sp.forEach(cb => { cb() })
expect(onSessionPayload1).toHaveBeenCalledTimes(3)
expect(onSessionPayload2).toHaveBeenCalledTimes(1)
})

it('clones on breadcrumb callbacks', () => {
const onBreadcrumb1 = jest.fn()
const onBreadcrumb2 = jest.fn()

const original = new Client({ apiKey })
original.addOnBreadcrumb(onBreadcrumb1)

const cloned = clone(original)
expect(cloned._cbs.b).not.toBe(original._cbs.b)

// @ts-ignore
cloned._cbs.b.forEach(cb => { cb() })
expect(onBreadcrumb1).toHaveBeenCalledTimes(1)
expect(onBreadcrumb2).toHaveBeenCalledTimes(0)

// adding a new callback should not affect the clone
original.addOnBreadcrumb(onBreadcrumb2)

// @ts-ignore
cloned._cbs.b.forEach(cb => { cb() })
expect(onBreadcrumb1).toHaveBeenCalledTimes(2)
expect(onBreadcrumb2).toHaveBeenCalledTimes(0)

// @ts-ignore
original._cbs.b.forEach(cb => { cb() })
expect(onBreadcrumb1).toHaveBeenCalledTimes(3)
expect(onBreadcrumb2).toHaveBeenCalledTimes(1)
})

it('assigns a logger', () => {
const logger = {
debug: jest.fn(),
info: jest.fn(),
warn: jest.fn(),
error: jest.fn()
}

const original = new Client({ apiKey, logger })
const cloned = clone(original)

expect(cloned._logger).toBe(original._logger)
})

it('assigns a delivery delegate', () => {
const delivery = () => ({
sendEvent: jest.fn(),
sendSession: jest.fn()
})

const original = new Client({ apiKey })
original._setDelivery(delivery)

const cloned = clone(original)

expect(cloned._delivery).toBe(original._delivery)
})

it('assigns a session delegate', () => {
const sessionDelegate = {
startSession: jest.fn(),
resumeSession: jest.fn(),
pauseSession: jest.fn()
}

const original = new Client({ apiKey })
original._sessionDelegate = sessionDelegate

const cloned = clone(original)

expect(cloned._sessionDelegate).toBe(original._sessionDelegate)
})
})
})

0 comments on commit bfda2ce

Please sign in to comment.