Skip to content

Commit e134014

Browse files
authored
test(node): Add integration tests for aggregated sessions. (#4832)
1 parent 2934a73 commit e134014

File tree

5 files changed

+171
-2
lines changed

5 files changed

+171
-2
lines changed
Lines changed: 36 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,36 @@
1+
import path from 'path';
2+
3+
import { getEnvelopeRequest, runServer } from '../../../utils';
4+
5+
test('should aggregate successful and crashed sessions', async () => {
6+
const url = await runServer(__dirname, `${path.resolve(__dirname, '..')}/server.ts`);
7+
8+
const envelope = await Promise.race([
9+
getEnvelopeRequest(`${url}/success`),
10+
getEnvelopeRequest(`${url}/error_unhandled`),
11+
getEnvelopeRequest(`${url}/success_slow`),
12+
]);
13+
14+
expect(envelope).toHaveLength(3);
15+
expect(envelope[0]).toMatchObject({
16+
sent_at: expect.any(String),
17+
sdk: {
18+
name: 'sentry.javascript.node',
19+
version: expect.any(String),
20+
},
21+
});
22+
23+
expect(envelope[1]).toMatchObject({
24+
type: 'sessions',
25+
});
26+
27+
expect(envelope[2]).toMatchObject({
28+
aggregates: [
29+
{
30+
started: expect.any(String),
31+
exited: 2,
32+
crashed: 1,
33+
},
34+
],
35+
});
36+
});
Lines changed: 37 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,37 @@
1+
import path from 'path';
2+
3+
import { getEnvelopeRequest, runServer } from '../../../utils';
4+
5+
test('should aggregate successful, crashed and erroneous sessions', async () => {
6+
const url = await runServer(__dirname, `${path.resolve(__dirname, '..')}/server.ts`);
7+
8+
const envelope = await Promise.race([
9+
getEnvelopeRequest(`${url}/success_slow`),
10+
getEnvelopeRequest(`${url}/error_handled`),
11+
getEnvelopeRequest(`${url}/error_unhandled`),
12+
]);
13+
14+
expect(envelope).toHaveLength(3);
15+
expect(envelope[0]).toMatchObject({
16+
sent_at: expect.any(String),
17+
sdk: {
18+
name: 'sentry.javascript.node',
19+
version: expect.any(String),
20+
},
21+
});
22+
23+
expect(envelope[1]).toMatchObject({
24+
type: 'sessions',
25+
});
26+
27+
expect(envelope[2]).toMatchObject({
28+
aggregates: [
29+
{
30+
started: expect.any(String),
31+
exited: 1,
32+
crashed: 1,
33+
errored: 1,
34+
},
35+
],
36+
});
37+
});
Lines changed: 35 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,35 @@
1+
import path from 'path';
2+
3+
import { getEnvelopeRequest, runServer } from '../../../utils';
4+
5+
test('should aggregate successful sessions', async () => {
6+
const url = await runServer(__dirname, `${path.resolve(__dirname, '..')}/server.ts`);
7+
8+
const envelope = await Promise.race([
9+
getEnvelopeRequest(`${url}/success`),
10+
getEnvelopeRequest(`${url}/success_next`),
11+
getEnvelopeRequest(`${url}/success_slow`),
12+
]);
13+
14+
expect(envelope).toHaveLength(3);
15+
expect(envelope[0]).toMatchObject({
16+
sent_at: expect.any(String),
17+
sdk: {
18+
name: 'sentry.javascript.node',
19+
version: expect.any(String),
20+
},
21+
});
22+
23+
expect(envelope[1]).toMatchObject({
24+
type: 'sessions',
25+
});
26+
27+
expect(envelope[2]).toMatchObject({
28+
aggregates: [
29+
{
30+
started: expect.any(String),
31+
exited: 3,
32+
},
33+
],
34+
});
35+
});
Lines changed: 60 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,60 @@
1+
/* eslint-disable no-console */
2+
import * as Sentry from '@sentry/node';
3+
import express from 'express';
4+
5+
const app = express();
6+
7+
Sentry.init({
8+
dsn: 'https://[email protected]/1337',
9+
release: '1.0',
10+
});
11+
12+
app.use(Sentry.Handlers.requestHandler());
13+
14+
// ### Taken from manual tests ###
15+
// Hack that resets the 60s default flush interval, and replaces it with just a one second interval
16+
// @ts-ignore: need access to `_sessionFlusher`
17+
const flusher = (Sentry.getCurrentHub()?.getClient() as Sentry.NodeClient)?._sessionFlusher;
18+
19+
// @ts-ignore: need access to `_intervalId`
20+
let flusherIntervalId = flusher?._intervalId;
21+
22+
clearInterval(flusherIntervalId);
23+
24+
// @ts-ignore: need access to `_intervalId`
25+
flusherIntervalId = flusher?._intervalId = setInterval(() => flusher?.flush(), 1000);
26+
27+
// @ts-ignore: need access to `_intervalId` again
28+
setTimeout(() => clearInterval(flusherIntervalId), 3000);
29+
30+
app.get('/test/success', (_req, res) => {
31+
res.send('Success!');
32+
});
33+
34+
app.get('/test/success_next', (_req, res, next) => {
35+
res.send('Success!');
36+
next();
37+
});
38+
39+
app.get('/test/success_slow', async (_req, res) => {
40+
await new Promise(res => setTimeout(res, 500));
41+
42+
res.send('Success!');
43+
});
44+
45+
app.get('/test/error_unhandled', () => {
46+
throw new Error('Crash!');
47+
});
48+
49+
app.get('/test/error_handled', (_req, res) => {
50+
try {
51+
throw new Error('Crash!');
52+
} catch (e) {
53+
Sentry.captureException(e);
54+
}
55+
res.send('Crash!');
56+
});
57+
58+
app.use(Sentry.Handlers.errorHandler());
59+
60+
export default app;

packages/node-integration-tests/utils/index.ts

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -194,12 +194,13 @@ export async function runServer(testDir: string, serverPath?: string, scenarioPa
194194

195195
app.get('/test', async () => {
196196
require(scenarioPath || `${testDir}/scenario`);
197-
198-
setTimeout(() => server.close(), 500);
199197
});
200198

201199
const server = app.listen(port, () => {
202200
resolve();
201+
setTimeout(() => {
202+
server.close();
203+
}, 4000);
203204
});
204205
});
205206

0 commit comments

Comments
 (0)