Skip to content

Commit 06c4664

Browse files
committed
add tests
1 parent bce7728 commit 06c4664

File tree

2 files changed

+279
-2
lines changed

2 files changed

+279
-2
lines changed

packages/core/test/lib/base.test.ts

Lines changed: 253 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -899,6 +899,18 @@ describe('BaseClient', () => {
899899
expect(TestClient.instance!.event!.message).toEqual('hello');
900900
});
901901

902+
test('calls `beforeSendTransaction` and uses original event without any changes', () => {
903+
expect.assertions(1);
904+
905+
const beforeSendTransaction = jest.fn(event => event);
906+
const options = getDefaultTestClientOptions({ dsn: PUBLIC_DSN, beforeSendTransaction });
907+
const client = new TestClient(options);
908+
909+
client.captureEvent({ transaction: '/dogs/are/great', type: 'transaction' });
910+
911+
expect(TestClient.instance!.event!.transaction).toBe('/dogs/are/great');
912+
});
913+
902914
test('calls `beforeSend` and uses the modified event', () => {
903915
expect.assertions(1);
904916

@@ -914,6 +926,21 @@ describe('BaseClient', () => {
914926
expect(TestClient.instance!.event!.message).toEqual('changed1');
915927
});
916928

929+
test('calls `beforeSendTransaction` and uses the modified event', () => {
930+
expect.assertions(1);
931+
932+
const beforeSendTransaction = jest.fn(event => {
933+
event.transaction = '/adopt/dont/shop';
934+
return event;
935+
});
936+
const options = getDefaultTestClientOptions({ dsn: PUBLIC_DSN, beforeSendTransaction });
937+
const client = new TestClient(options);
938+
939+
client.captureEvent({ transaction: '/dogs/are/great', type: 'transaction' });
940+
941+
expect(TestClient.instance!.event!.transaction).toBe('/adopt/dont/shop');
942+
});
943+
917944
test('calls `beforeSend` and discards the event', () => {
918945
expect.assertions(3);
919946

@@ -932,6 +959,24 @@ describe('BaseClient', () => {
932959
expect(loggerWarnSpy).toBeCalledWith('`beforeSend` returned `null`, will not send event.');
933960
});
934961

962+
test('calls `beforeSendTransaction` and discards the event', () => {
963+
expect.assertions(3);
964+
965+
const beforeSendTransaction = jest.fn(() => null);
966+
const options = getDefaultTestClientOptions({ dsn: PUBLIC_DSN, beforeSendTransaction });
967+
const client = new TestClient(options);
968+
const captureExceptionSpy = jest.spyOn(client, 'captureException');
969+
const loggerWarnSpy = jest.spyOn(logger, 'log');
970+
971+
client.captureEvent({ transaction: '/dogs/are/great', type: 'transaction' });
972+
973+
expect(TestClient.instance!.event).toBeUndefined();
974+
// This proves that the reason the event didn't send/didn't get set on the test client is not because there was an
975+
// error, but because `beforeSendTransaction` returned `null`
976+
expect(captureExceptionSpy).not.toBeCalled();
977+
expect(loggerWarnSpy).toBeCalledWith('`beforeSendTransaction` returned `null`, will not send event.');
978+
});
979+
935980
test('calls `beforeSend` and logs info about invalid return value', () => {
936981
const invalidValues = [undefined, false, true, [], 1];
937982
expect.assertions(invalidValues.length * 2);
@@ -950,6 +995,26 @@ describe('BaseClient', () => {
950995
}
951996
});
952997

998+
test('calls `beforeSendTransaction` and logs info about invalid return value', () => {
999+
const invalidValues = [undefined, false, true, [], 1];
1000+
expect.assertions(invalidValues.length * 2);
1001+
1002+
for (const val of invalidValues) {
1003+
const beforeSendTransaction = jest.fn(() => val);
1004+
// @ts-ignore we need to test regular-js behavior
1005+
const options = getDefaultTestClientOptions({ dsn: PUBLIC_DSN, beforeSendTransaction });
1006+
const client = new TestClient(options);
1007+
const loggerWarnSpy = jest.spyOn(logger, 'warn');
1008+
1009+
client.captureEvent({ transaction: '/dogs/are/great', type: 'transaction' });
1010+
1011+
expect(TestClient.instance!.event).toBeUndefined();
1012+
expect(loggerWarnSpy).toBeCalledWith(
1013+
new SentryError('`beforeSendTransaction` must return `null` or a valid event.'),
1014+
);
1015+
}
1016+
});
1017+
9531018
test('calls async `beforeSend` and uses original event without any changes', done => {
9541019
jest.useFakeTimers();
9551020
expect.assertions(1);
@@ -979,6 +1044,35 @@ describe('BaseClient', () => {
9791044
jest.runOnlyPendingTimers();
9801045
});
9811046

1047+
test('calls async `beforeSendTransaction` and uses original event without any changes', done => {
1048+
jest.useFakeTimers();
1049+
expect.assertions(1);
1050+
1051+
const beforeSendTransaction = jest.fn(
1052+
async event =>
1053+
new Promise<Event>(resolve => {
1054+
setTimeout(() => {
1055+
resolve(event);
1056+
}, 1);
1057+
}),
1058+
);
1059+
const options = getDefaultTestClientOptions({ dsn: PUBLIC_DSN, beforeSendTransaction });
1060+
const client = new TestClient(options);
1061+
1062+
client.captureEvent({ transaction: '/dogs/are/great', type: 'transaction' });
1063+
jest.runOnlyPendingTimers();
1064+
1065+
TestClient.sendEventCalled = (event: Event) => {
1066+
expect(event.transaction).toBe('/dogs/are/great');
1067+
};
1068+
1069+
setTimeout(() => {
1070+
done();
1071+
}, 5);
1072+
1073+
jest.runOnlyPendingTimers();
1074+
});
1075+
9821076
test('calls async `beforeSend` and uses the modified event', done => {
9831077
jest.useFakeTimers();
9841078
expect.assertions(1);
@@ -1008,6 +1102,35 @@ describe('BaseClient', () => {
10081102
jest.runOnlyPendingTimers();
10091103
});
10101104

1105+
test('calls async `beforeSendTransaction` and uses the modified event', done => {
1106+
jest.useFakeTimers();
1107+
expect.assertions(1);
1108+
1109+
const beforeSendTransaction = jest.fn(async event => {
1110+
event.transaction = '/adopt/dont/shop';
1111+
return new Promise<Event>(resolve => {
1112+
setTimeout(() => {
1113+
resolve(event);
1114+
}, 1);
1115+
});
1116+
});
1117+
const options = getDefaultTestClientOptions({ dsn: PUBLIC_DSN, beforeSendTransaction });
1118+
const client = new TestClient(options);
1119+
1120+
client.captureEvent({ transaction: '/dogs/are/great', type: 'transaction' });
1121+
jest.runOnlyPendingTimers();
1122+
1123+
TestClient.sendEventCalled = (event: Event) => {
1124+
expect(event.transaction).toBe('/adopt/dont/shop');
1125+
};
1126+
1127+
setTimeout(() => {
1128+
done();
1129+
}, 5);
1130+
1131+
jest.runOnlyPendingTimers();
1132+
});
1133+
10111134
test('calls async `beforeSend` and discards the event', () => {
10121135
jest.useFakeTimers();
10131136
expect.assertions(1);
@@ -1029,6 +1152,27 @@ describe('BaseClient', () => {
10291152
expect(TestClient.instance!.event).toBeUndefined();
10301153
});
10311154

1155+
test('calls async `beforeSendTransaction` and discards the event', () => {
1156+
jest.useFakeTimers();
1157+
expect.assertions(1);
1158+
1159+
const beforeSendTransaction = jest.fn(
1160+
async () =>
1161+
new Promise<null>(resolve => {
1162+
setTimeout(() => {
1163+
resolve(null);
1164+
});
1165+
}),
1166+
);
1167+
const options = getDefaultTestClientOptions({ dsn: PUBLIC_DSN, beforeSendTransaction });
1168+
const client = new TestClient(options);
1169+
1170+
client.captureEvent({ transaction: '/dogs/are/great', type: 'transaction' });
1171+
jest.runAllTimers();
1172+
1173+
expect(TestClient.instance!.event).toBeUndefined();
1174+
});
1175+
10321176
test('`beforeSend` gets access to a hint as a second argument', () => {
10331177
expect.assertions(2);
10341178

@@ -1042,6 +1186,22 @@ describe('BaseClient', () => {
10421186
expect((TestClient.instance!.event! as any).data).toEqual('someRandomThing');
10431187
});
10441188

1189+
test('`beforeSendTransaction` gets access to a hint as a second argument', () => {
1190+
expect.assertions(2);
1191+
1192+
const beforeSendTransaction = jest.fn((event, hint) => ({ ...event, data: hint.data }));
1193+
const options = getDefaultTestClientOptions({ dsn: PUBLIC_DSN, beforeSendTransaction });
1194+
const client = new TestClient(options);
1195+
1196+
client.captureEvent(
1197+
{ transaction: '/dogs/are/great', type: 'transaction' },
1198+
{ data: { dogs: 'yes', cats: 'maybe' } },
1199+
);
1200+
1201+
expect(TestClient.instance!.event!.transaction).toBe('/dogs/are/great');
1202+
expect((TestClient.instance!.event! as any).data).toEqual({ dogs: 'yes', cats: 'maybe' });
1203+
});
1204+
10451205
test('`beforeSend` records dropped events', () => {
10461206
expect.assertions(1);
10471207

@@ -1061,7 +1221,26 @@ describe('BaseClient', () => {
10611221
expect(recordLostEventSpy).toHaveBeenCalledWith('before_send', 'error');
10621222
});
10631223

1064-
test('event processor drops the event when it returns `null`', () => {
1224+
test('`beforeSendTransaction` records dropped events', () => {
1225+
expect.assertions(1);
1226+
1227+
const client = new TestClient(
1228+
getDefaultTestClientOptions({
1229+
dsn: PUBLIC_DSN,
1230+
beforeSendTransaction() {
1231+
return null;
1232+
},
1233+
}),
1234+
);
1235+
1236+
const recordLostEventSpy = jest.spyOn(client, 'recordDroppedEvent');
1237+
1238+
client.captureEvent({ transaction: '/dogs/are/great', type: 'transaction' });
1239+
1240+
expect(recordLostEventSpy).toHaveBeenCalledWith('before_send', 'transaction');
1241+
});
1242+
1243+
test('event processor drops error event when it returns `null`', () => {
10651244
expect.assertions(3);
10661245

10671246
const client = new TestClient(getDefaultTestClientOptions({ dsn: PUBLIC_DSN }));
@@ -1079,7 +1258,25 @@ describe('BaseClient', () => {
10791258
expect(loggerLogSpy).toBeCalledWith('An event processor returned `null`, will not send event.');
10801259
});
10811260

1082-
test('event processor records dropped events', () => {
1261+
test('event processor drops transaction event when it returns `null`', () => {
1262+
expect.assertions(3);
1263+
1264+
const client = new TestClient(getDefaultTestClientOptions({ dsn: PUBLIC_DSN }));
1265+
const captureExceptionSpy = jest.spyOn(client, 'captureException');
1266+
const loggerLogSpy = jest.spyOn(logger, 'log');
1267+
const scope = new Scope();
1268+
scope.addEventProcessor(() => null);
1269+
1270+
client.captureEvent({ transaction: '/dogs/are/great', type: 'transaction' }, {}, scope);
1271+
1272+
expect(TestClient.instance!.event).toBeUndefined();
1273+
// This proves that the reason the event didn't send/didn't get set on the test client is not because there was an
1274+
// error, but because the event processor returned `null`
1275+
expect(captureExceptionSpy).not.toBeCalled();
1276+
expect(loggerLogSpy).toBeCalledWith('An event processor returned `null`, will not send event.');
1277+
});
1278+
1279+
test('event processor records dropped error events', () => {
10831280
expect.assertions(1);
10841281

10851282
const options = getDefaultTestClientOptions({ dsn: PUBLIC_DSN });
@@ -1095,6 +1292,22 @@ describe('BaseClient', () => {
10951292
expect(recordLostEventSpy).toHaveBeenCalledWith('event_processor', 'error');
10961293
});
10971294

1295+
test('event processor records dropped transaction events', () => {
1296+
expect.assertions(1);
1297+
1298+
const options = getDefaultTestClientOptions({ dsn: PUBLIC_DSN });
1299+
const client = new TestClient(options);
1300+
1301+
const recordLostEventSpy = jest.spyOn(client, 'recordDroppedEvent');
1302+
1303+
const scope = new Scope();
1304+
scope.addEventProcessor(() => null);
1305+
1306+
client.captureEvent({ transaction: '/dogs/are/great', type: 'transaction' }, {}, scope);
1307+
1308+
expect(recordLostEventSpy).toHaveBeenCalledWith('event_processor', 'transaction');
1309+
});
1310+
10981311
test('mutating transaction name with event processors sets transaction-name-change metadata', () => {
10991312
const options = getDefaultTestClientOptions({ dsn: PUBLIC_DSN, enableSend: true });
11001313
const client = new TestClient(options);
@@ -1130,6 +1343,38 @@ describe('BaseClient', () => {
11301343
});
11311344
});
11321345

1346+
test('mutating transaction name with `beforeSendTransaction` sets transaction-name-change metadata', () => {
1347+
const beforeSendTransaction = jest.fn(event => {
1348+
event.transaction = '/adopt/dont/shop';
1349+
return event;
1350+
});
1351+
const options = getDefaultTestClientOptions({ dsn: PUBLIC_DSN, beforeSendTransaction });
1352+
const client = new TestClient(options);
1353+
1354+
client.captureEvent({
1355+
transaction: '/dogs/are/great',
1356+
type: 'transaction',
1357+
transaction_info: {
1358+
source: 'url',
1359+
changes: [],
1360+
propagations: 3,
1361+
},
1362+
});
1363+
1364+
expect(TestClient.instance!.event!.transaction).toBe('/adopt/dont/shop');
1365+
expect(TestClient.instance!.event!.transaction_info).toEqual({
1366+
source: 'custom',
1367+
changes: [
1368+
{
1369+
propagations: 3,
1370+
source: 'custom',
1371+
timestamp: expect.any(Number),
1372+
},
1373+
],
1374+
propagations: 3,
1375+
});
1376+
});
1377+
11331378
test('event processor sends an event and logs when it crashes', () => {
11341379
expect.assertions(3);
11351380

@@ -1375,6 +1620,7 @@ describe('BaseClient', () => {
13751620
client.recordDroppedEvent('network_error', 'transaction');
13761621
client.recordDroppedEvent('network_error', 'transaction');
13771622
client.recordDroppedEvent('before_send', 'error');
1623+
client.recordDroppedEvent('before_send', 'transaction');
13781624
client.recordDroppedEvent('event_processor', 'attachment');
13791625
client.recordDroppedEvent('network_error', 'transaction');
13801626

@@ -1397,6 +1643,11 @@ describe('BaseClient', () => {
13971643
category: 'error',
13981644
quantity: 1,
13991645
},
1646+
{
1647+
reason: 'before_send',
1648+
category: 'transaction',
1649+
quantity: 1,
1650+
},
14001651
{
14011652
reason: 'event_processor',
14021653
category: 'attachment',

packages/core/test/lib/hint.test.ts

Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -61,6 +61,32 @@ describe('Hint', () => {
6161
});
6262
});
6363

64+
test('gets passed through to `beforeSendTransaction` and can be further mutated', () => {
65+
expect.assertions(1);
66+
67+
const options = getDefaultTestClientOptions({
68+
dsn: PUBLIC_DSN,
69+
beforeSendTransaction: (event, hint) => {
70+
hint.attachments = [...(hint.attachments || []), { filename: 'another.file', data: 'more text' }];
71+
return event;
72+
},
73+
});
74+
75+
const client = new TestClient(options);
76+
client.captureEvent(
77+
{ transaction: '/dogs/are/great', type: 'transaction' },
78+
{ attachments: [{ filename: 'some-file.txt', data: 'Hello' }] },
79+
);
80+
81+
const [, hint] = sendEvent.mock.calls[0];
82+
expect(hint).toEqual({
83+
attachments: [
84+
{ filename: 'some-file.txt', data: 'Hello' },
85+
{ filename: 'another.file', data: 'more text' },
86+
],
87+
});
88+
});
89+
6490
test('can be mutated by an integration via event processor', () => {
6591
expect.assertions(1);
6692

0 commit comments

Comments
 (0)