Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add unit tests for clone-client #1880

Merged
merged 2 commits into from
Dec 6, 2022
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
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 }
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

_featuresIndex needed adding here to get the unit test to compile


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)
})
})
})