Skip to content

Commit 781f1d0

Browse files
authored
feat(segment): add on event error to handle all your events from provider (#598)
1 parent a82efee commit 781f1d0

File tree

2 files changed

+60
-8
lines changed

2 files changed

+60
-8
lines changed

packages/use-segment/src/__tests__/index.tsx

Lines changed: 51 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -3,9 +3,20 @@ import { renderHook } from '@testing-library/react-hooks'
33
import React, { ReactNode } from 'react'
44
import waitForExpect from 'wait-for-expect'
55
import SegmentProvider, { useSegment } from '..'
6-
import type { Analytics, SegmentProviderProps } from '..'
6+
import type { Analytics, OnEventError, SegmentProviderProps } from '..'
7+
8+
const eventError = new Error('Error Event')
79

810
const defaultEvents = {
11+
errorEvent: (_?: Analytics, onEventError?: OnEventError) => async () => {
12+
try {
13+
await new Promise((resolve, reject) => {
14+
reject(eventError)
15+
})
16+
} catch (error) {
17+
await onEventError?.(error as Error)
18+
}
19+
},
920
pageVisited:
1021
(analytics?: Analytics) =>
1122
async (
@@ -34,6 +45,7 @@ const wrapper =
3445
settings,
3546
initOptions,
3647
onError,
48+
onEventError,
3749
events = defaultEvents,
3850
cdn,
3951
}: Omit<SegmentProviderProps<DefaultEvents>, 'children'>) =>
@@ -43,6 +55,7 @@ const wrapper =
4355
settings={settings}
4456
initOptions={initOptions}
4557
onError={onError}
58+
onEventError={onEventError}
4659
events={events}
4760
cdn={cdn}
4861
>
@@ -124,9 +137,8 @@ describe('segment hook', () => {
124137
})
125138

126139
it('Provider should load and call onError on analytics load error', async () => {
127-
const mock = jest
128-
.spyOn(AnalyticsBrowser, 'load')
129-
.mockRejectedValue(new Error('not good'))
140+
const error = new Error('not good')
141+
const mock = jest.spyOn(AnalyticsBrowser, 'load').mockRejectedValue(error)
130142

131143
const onError = jest.fn()
132144
const settings = { writeKey: 'pleasethrow' }
@@ -144,7 +156,41 @@ describe('segment hook', () => {
144156

145157
await waitForExpect(() => {
146158
expect(onError).toHaveBeenCalledTimes(1)
147-
expect(onError).toHaveBeenCalledWith(new Error('not good'))
159+
expect(onError).toHaveBeenCalledWith(error)
160+
})
161+
})
162+
163+
it('Provider call onEventError when an event is trigger with an error', async () => {
164+
const mock = jest
165+
.spyOn(AnalyticsBrowser, 'load')
166+
.mockResolvedValue([{} as Analytics, {} as Context])
167+
168+
const onEventError = jest.fn()
169+
const onError = jest.fn()
170+
171+
const settings = { writeKey: 'pleasethrow' }
172+
173+
const { result, waitForNextUpdate } = renderHook(
174+
() => useSegment<DefaultEvents>(),
175+
{
176+
wrapper: wrapper({
177+
events: defaultEvents,
178+
onError,
179+
onEventError,
180+
settings,
181+
}),
182+
},
183+
)
184+
185+
expect(mock).toHaveBeenCalledTimes(1)
186+
187+
await waitForNextUpdate()
188+
189+
await result.current.events.errorEvent()
190+
191+
await waitForExpect(() => {
192+
expect(onEventError).toHaveBeenCalledTimes(1)
193+
expect(onEventError).toHaveBeenCalledWith(eventError)
148194
})
149195
})
150196

packages/use-segment/src/useSegment.tsx

Lines changed: 9 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -13,8 +13,12 @@ import React, {
1313
useState,
1414
} from 'react'
1515

16+
export type OnEventError = (error: Error) => Promise<void> | void
1617
type EventFunction = (...args: never[]) => Promise<void>
17-
type Events = Record<string, (analytics?: Analytics) => EventFunction>
18+
type Events = Record<
19+
string,
20+
(analytics?: Analytics, onEventError?: OnEventError) => EventFunction
21+
>
1822

1923
interface SegmentContextInterface<T extends Events = Events> {
2024
analytics: Analytics | undefined
@@ -41,6 +45,7 @@ export type SegmentProviderProps<T> = {
4145
settings?: AnalyticsSettings
4246
initOptions?: InitOptions
4347
onError?: (err: Error) => void
48+
onEventError?: OnEventError
4449
events: T
4550
children: ReactNode
4651
}
@@ -58,6 +63,7 @@ function SegmentProvider<T extends Events>({
5863
settings,
5964
initOptions,
6065
onError,
66+
onEventError,
6167
events,
6268
cdn,
6369
}: SegmentProviderProps<T>) {
@@ -86,7 +92,7 @@ function SegmentProvider<T extends Events>({
8692
const curiedEvents = Object.entries(events).reduce(
8793
(acc, [eventName, eventFn]) => ({
8894
...acc,
89-
[eventName]: eventFn(internalAnalytics),
95+
[eventName]: eventFn(internalAnalytics, onEventError),
9096
}),
9197
{},
9298
) as { [K in keyof T]: ReturnType<T[K]> }
@@ -95,7 +101,7 @@ function SegmentProvider<T extends Events>({
95101
analytics: internalAnalytics,
96102
events: curiedEvents,
97103
}
98-
}, [internalAnalytics, events])
104+
}, [internalAnalytics, events, onEventError])
99105

100106
return (
101107
<SegmentContext.Provider value={value}>{children}</SegmentContext.Provider>

0 commit comments

Comments
 (0)