Skip to content

Commit a413f76

Browse files
committed
polish(sentry): Cleanup browser.ts and tests
1 parent 54b6629 commit a413f76

2 files changed

Lines changed: 76 additions & 84 deletions

File tree

libs/shared/sentry/src/lib/browser.spec.ts

Lines changed: 27 additions & 27 deletions
Original file line numberDiff line numberDiff line change
@@ -3,12 +3,17 @@
33
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
44
import 'jsdom-global/register';
55
import * as Sentry from '@sentry/browser';
6-
import sentryMetrics, { _Sentry } from './browser';
6+
import * as sentryWrapper from './browser';
77
import { SentryConfigOpts } from './models/SentryConfigOpts';
8-
import { Logger } from './sentry.types';
98

10-
const sinon = require('sinon');
11-
const sandbox = sinon.createSandbox();
9+
jest.mock('@sentry/browser', () => {
10+
const actual = jest.requireActual('@sentry/browser');
11+
return {
12+
...actual,
13+
init: jest.fn(),
14+
captureException: jest.fn(),
15+
};
16+
});
1217

1318
const config: SentryConfigOpts = {
1419
release: 'v0.0.0',
@@ -19,45 +24,41 @@ const config: SentryConfigOpts = {
1924
sampleRate: 0,
2025
},
2126
};
22-
const logger: Logger = {
27+
const logger = {
2328
info: jest.fn(),
2429
warn: jest.fn(),
2530
error: jest.fn(),
2631
debug: jest.fn(),
2732
};
2833

2934
describe('sentry/browser', () => {
30-
beforeAll(() => {
31-
// Reduce console log noise in test output
32-
sandbox.spy(console, 'error');
33-
});
34-
3535
beforeEach(() => {
3636
// Make sure it's enabled by default
37-
sentryMetrics.enable();
37+
sentryWrapper.enable();
3838
});
3939

40-
afterAll(() => {
41-
sandbox.restore();
40+
afterEach(() => {
41+
jest.resetAllMocks();
42+
jest.resetModules();
4243
});
4344

4445
describe('init', () => {
4546
it('properly configures with dsn', () => {
46-
sentryMetrics.configure(config, logger);
47+
sentryWrapper.configure(config, logger);
4748
});
4849
});
4950

5051
describe('beforeSend', () => {
5152
beforeAll(() => {
52-
sentryMetrics.configure(config, logger);
53+
sentryWrapper.configure(config, logger);
5354
});
5455

5556
it('works without request url', () => {
5657
const data = {
5758
key: 'value',
5859
} as Sentry.Event;
5960

60-
const resultData = sentryMetrics.__beforeSend(config, data, {});
61+
const resultData = sentryWrapper.beforeSend(config, data, {});
6162

6263
expect(data).toEqual(resultData);
6364
});
@@ -72,35 +73,34 @@ describe('sentry/browser', () => {
7273
},
7374
} as Sentry.Event;
7475

75-
const resultData = sentryMetrics.__beforeSend(config, data, {});
76+
const resultData = sentryWrapper.beforeSend(config, data, {});
7677
expect(resultData?.fingerprint?.[0]).toEqual('errno100');
7778
expect(resultData?.level).toEqual('info');
7879
});
7980
});
8081

8182
describe('captureException', () => {
8283
it('calls Sentry.captureException', () => {
83-
const sentryCaptureException = sinon.stub(_Sentry, 'captureException');
84-
sentryMetrics.captureException(new Error('testo'));
85-
sinon.assert.calledOnce(sentryCaptureException);
86-
sentryCaptureException.restore();
84+
const spy = jest.spyOn(Sentry, 'captureException');
85+
Sentry.captureException(new Error('testo'));
86+
expect(spy).toHaveBeenCalledTimes(1);
8787
});
8888
});
8989

9090
describe('disable / enables', () => {
9191
it('enables', () => {
92-
sentryMetrics.enable();
93-
expect(sentryMetrics.__sentryEnabled()).toBeTruthy();
92+
sentryWrapper.enable();
93+
expect(sentryWrapper.isEnabled()).toBeTruthy();
9494
});
9595

9696
it('disables', () => {
97-
sentryMetrics.disable();
98-
expect(sentryMetrics.__sentryEnabled()).toBeFalsy();
97+
sentryWrapper.disable();
98+
expect(sentryWrapper.isEnabled()).toBeFalsy();
9999
});
100100

101101
it('will return null from before send when disabled', () => {
102-
sentryMetrics.disable();
103-
expect(sentryMetrics.__beforeSend({}, {}, {})).toBeNull();
102+
sentryWrapper.disable();
103+
expect(sentryWrapper.beforeSend({}, {}, {})).toBeNull();
104104
});
105105
});
106106
});

libs/shared/sentry/src/lib/browser.ts

Lines changed: 49 additions & 57 deletions
Original file line numberDiff line numberDiff line change
@@ -16,48 +16,7 @@ const EXCEPTION_TAGS = ['code', 'context', 'errno', 'namespace', 'status'];
1616
// Internal flag to keep track of whether or not sentry is initialized
1717
let sentryEnabled = false;
1818

19-
// HACK: allow tests to stub this function from Sentry
20-
// https://stackoverflow.com/questions/35240469/how-to-mock-the-imports-of-an-es6-module
21-
export const _Sentry = {
22-
captureException: Sentry.captureException,
23-
close: Sentry.close,
24-
};
25-
26-
/**
27-
* function that gets called before data gets sent to error metrics
28-
*
29-
* @param {Object} event
30-
* Error object data
31-
* @returns {Object} data
32-
* Modified error object data
33-
* @private
34-
*/
35-
function beforeSend(
36-
opts: SentryConfigOpts,
37-
event: Sentry.ErrorEvent,
38-
hint?: Sentry.EventHint
39-
) {
40-
if (sentryEnabled === false) {
41-
return null;
42-
}
43-
44-
if (event.request) {
45-
if (event.tags) {
46-
// if this is a known errno, then use grouping with fingerprints
47-
// Docs: https://docs.sentry.io/hosted/learn/rollups/#fallback-grouping
48-
if (event.tags.errno) {
49-
event.fingerprint = ['errno' + (event.tags.errno as number)];
50-
// if it is a known error change the error level to info.
51-
event.level = 'info';
52-
}
53-
}
54-
}
55-
56-
event = tagFxaName(event, opts.sentry?.clientName || opts.sentry?.serverName);
57-
return event;
58-
}
59-
60-
function captureException(err: Error) {
19+
export function captureException(err: Error) {
6120
if (!sentryEnabled) {
6221
return;
6322
}
@@ -79,15 +38,59 @@ function captureException(err: Error) {
7938
});
8039
}
8140

82-
function disable() {
41+
export function isEnabled() {
42+
return sentryEnabled;
43+
}
44+
45+
/**
46+
* Toggle sentry error capture to be disabled.
47+
*/
48+
export function disable() {
8349
sentryEnabled = false;
8450
}
8551

86-
function enable() {
52+
/**
53+
* Toggle sentry error capture to be enabled.
54+
*/
55+
export function enable() {
8756
sentryEnabled = true;
8857
}
8958

90-
function configure(config: SentryConfigOpts, log?: Logger) {
59+
/**
60+
* Gets called before data gets sent to error metrics. Useful for altering event state before it gets sent to Sentry.
61+
* For example, we use this to set the event fingerprint based on known error numbers.
62+
*
63+
* @param {Object} opts - Sentry configuration options
64+
* @param {Object} event - Sentry error object data
65+
* @param {Object} hint - Sentry error object hint data
66+
* @returns {Object} event - Modified error object data
67+
*/
68+
export function beforeSend(
69+
opts: SentryConfigOpts,
70+
event: Sentry.Event,
71+
_hint?: Sentry.EventHint
72+
) {
73+
if (sentryEnabled === false) {
74+
return null;
75+
}
76+
77+
if (event.request) {
78+
if (event.tags) {
79+
// if this is a known errno, then use grouping with fingerprints
80+
// Docs: https://docs.sentry.io/hosted/learn/rollups/#fallback-grouping
81+
if (event.tags.errno) {
82+
event.fingerprint = ['errno' + (event.tags.errno as number)];
83+
// if it is a known error change the error level to info.
84+
event.level = 'info';
85+
}
86+
}
87+
}
88+
89+
event = tagFxaName(event, opts.sentry?.clientName || opts.sentry?.serverName);
90+
return event;
91+
}
92+
93+
export function configure(config: SentryConfigOpts, log?: Logger) {
9194
if (!log) {
9295
log = console;
9396
}
@@ -106,22 +109,11 @@ function configure(config: SentryConfigOpts, log?: Logger) {
106109
try {
107110
Sentry.init({
108111
...opts,
109-
beforeSend: function (event: Sentry.ErrorEvent, hint: Sentry.EventHint) {
112+
beforeSend: function (event: Sentry.ErrorEvent, hint?: Sentry.EventHint) {
110113
return beforeSend(opts, event, hint);
111114
},
112115
});
113116
} catch (e) {
114117
log.error(e);
115118
}
116119
}
117-
118-
export default {
119-
configure,
120-
captureException,
121-
disable,
122-
enable,
123-
__sentryEnabled: function () {
124-
return sentryEnabled;
125-
},
126-
__beforeSend: beforeSend,
127-
};

0 commit comments

Comments
 (0)