Skip to content

Commit f69c859

Browse files
author
Reno
authored
fix: Parse unhandledrejection error objects (#123)
* fix: Parse unhandledrejection error objects
1 parent cf59ecb commit f69c859

File tree

3 files changed

+105
-7
lines changed

3 files changed

+105
-7
lines changed

src/plugins/event-plugins/JsErrorPlugin.ts

Lines changed: 3 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,3 @@
1-
import { JSErrorEvent } from '../../events/js-error-event';
21
import { RecordEvent, Plugin, PluginContext } from '../Plugin';
32
import { JS_ERROR_EVENT_TYPE } from '../utils/constant';
43
import { errorEventToJsErrorEvent } from '../utils/js-error-utils';
@@ -70,12 +69,10 @@ export class JsErrorPlugin implements Plugin {
7069
};
7170

7271
private promiseRejectEventHandler = (event: PromiseRejectionEvent) => {
73-
const errorEvent: JSErrorEvent = {
74-
version: '1.0.0',
72+
this.eventHandler({
7573
type: event.type,
76-
message: event.reason
77-
};
78-
this.recordEvent(JS_ERROR_EVENT_TYPE, errorEvent);
74+
error: event.reason
75+
} as ErrorEvent);
7976
};
8077

8178
private addEventHandler(): void {

src/plugins/event-plugins/__tests__/JsErrorPlugin.test.ts

Lines changed: 98 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -422,4 +422,102 @@ describe('JsErrorPlugin tests', () => {
422422
})
423423
);
424424
});
425+
426+
test('when unhandledrejection error event outputs empty object as reason then message is recorded as undefined', async () => {
427+
// Init
428+
const plugin: JsErrorPlugin = new JsErrorPlugin();
429+
430+
// Run
431+
plugin.load(context);
432+
const promiseRejectionEvent: PromiseRejectionEvent = new Event(
433+
'unhandledrejection'
434+
) as PromiseRejectionEvent;
435+
// JSDOM has not implemented PromiseRejectionEvent, so we 'extend'
436+
// Event to have the same functionality
437+
window.dispatchEvent(
438+
Object.assign(promiseRejectionEvent, {
439+
promise: new Promise(() => {}),
440+
reason: {}
441+
})
442+
);
443+
plugin.disable();
444+
445+
// Assert
446+
expect(record).toHaveBeenCalledTimes(1);
447+
expect(record.mock.calls[0][0]).toEqual(JS_ERROR_EVENT_TYPE);
448+
expect(record.mock.calls[0][1]).toMatchObject(
449+
expect.objectContaining({
450+
version: '1.0.0',
451+
type: 'unhandledrejection',
452+
message: 'undefined'
453+
})
454+
);
455+
});
456+
457+
test('when unhandledrejection error event outputs null object as reason then message is recorded as undefined', async () => {
458+
// Init
459+
const plugin: JsErrorPlugin = new JsErrorPlugin();
460+
461+
// Run
462+
plugin.load(context);
463+
const promiseRejectionEvent: PromiseRejectionEvent = new Event(
464+
'unhandledrejection'
465+
) as PromiseRejectionEvent;
466+
// JSDOM has not implemented PromiseRejectionEvent, so we 'extend'
467+
// Event to have the same functionality
468+
window.dispatchEvent(
469+
Object.assign(promiseRejectionEvent, {
470+
promise: new Promise(() => {}),
471+
reason: null
472+
})
473+
);
474+
plugin.disable();
475+
476+
// Assert
477+
expect(record).toHaveBeenCalledTimes(1);
478+
expect(record.mock.calls[0][0]).toEqual(JS_ERROR_EVENT_TYPE);
479+
expect(record.mock.calls[0][1]).toMatchObject(
480+
expect.objectContaining({
481+
version: '1.0.0',
482+
type: 'unhandledrejection',
483+
message: 'undefined'
484+
})
485+
);
486+
});
487+
488+
test('when unhandledrejection error event outputs error object as reason then error object is used', async () => {
489+
// Init
490+
const plugin: JsErrorPlugin = new JsErrorPlugin();
491+
492+
// Run
493+
plugin.load(context);
494+
const promiseRejectionEvent: PromiseRejectionEvent = new Event(
495+
'unhandledrejection'
496+
) as PromiseRejectionEvent;
497+
// JSDOM has not implemented PromiseRejectionEvent, so we 'extend'
498+
// Event to have the same functionality
499+
window.dispatchEvent(
500+
Object.assign(promiseRejectionEvent, {
501+
promise: new Promise(() => {}),
502+
reason: {
503+
name: 'TypeError',
504+
message: 'NetworkError when attempting to fetch resource.',
505+
stack: 't/n.fetch@mock_client.js:2:104522t/n.fetchWrapper'
506+
}
507+
})
508+
);
509+
plugin.disable();
510+
511+
// Assert
512+
expect(record).toHaveBeenCalledTimes(1);
513+
expect(record.mock.calls[0][0]).toEqual(JS_ERROR_EVENT_TYPE);
514+
expect(record.mock.calls[0][1]).toMatchObject(
515+
expect.objectContaining({
516+
version: '1.0.0',
517+
type: 'TypeError',
518+
message: 'NetworkError when attempting to fetch resource.',
519+
stack: 't/n.fetch@mock_client.js:2:104522t/n.fetchWrapper'
520+
})
521+
);
522+
});
425523
});

src/plugins/utils/js-error-utils.ts

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -48,7 +48,10 @@ const appendErrorPrimitiveDetails = (
4848
rumEvent: JSErrorEvent,
4949
error: any
5050
): void => {
51-
rumEvent.type = error.toString();
51+
// Keep unhandledrejection as type as it will write to rumEvent.message
52+
if (rumEvent.type !== 'unhandledrejection') {
53+
rumEvent.type = error.toString();
54+
}
5255
rumEvent.message = error.toString();
5356
};
5457

0 commit comments

Comments
 (0)