Skip to content

Commit d5f1caf

Browse files
authored
test: Improve E2E node tests (#12258)
This does two main things: 1. Updates node E2E tests to use `fetch` instead of axios 2. Update node E2E tests to avoid sending to Sentry. Instead, we check everywhere via the proxy that the data sent is OK. Part of #11910
1 parent 38bd57b commit d5f1caf

File tree

17 files changed

+102
-550
lines changed

17 files changed

+102
-550
lines changed

dev-packages/e2e-tests/test-applications/create-next-app/tests/behaviour-server.test.ts

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,8 @@ const sentryTestProject = process.env.E2E_TEST_SENTRY_TEST_PROJECT;
77
const EVENT_POLLING_TIMEOUT = 90_000;
88

99
test('Sends a server-side exception to Sentry', async ({ baseURL }) => {
10-
const { data } = await axios.get(`${baseURL}/api/error`);
10+
const response = await fetch(`${baseURL}/api/error`);
11+
const data = await response.json();
1112
const { exceptionId } = data;
1213

1314
const url = `https://sentry.io/api/0/projects/${sentryTestOrgSlug}/${sentryTestProject}/events/${exceptionId}/`;
@@ -39,7 +40,8 @@ test('Sends a server-side exception to Sentry', async ({ baseURL }) => {
3940
});
4041

4142
test('Sends server-side transactions to Sentry', async ({ baseURL }) => {
42-
const { data } = await axios.get(`${baseURL}/api/success`);
43+
const response = await fetch(`${baseURL}/api/success`);
44+
const data = await response.json();
4345
const { transactionIds } = data;
4446

4547
console.log(`Polling for transaction eventIds: ${JSON.stringify(transactionIds)}`);

dev-packages/e2e-tests/test-applications/node-connect/tests/errors.test.ts

Lines changed: 1 addition & 43 deletions
Original file line numberDiff line numberDiff line change
@@ -1,54 +1,12 @@
11
import { expect, test } from '@playwright/test';
22
import { waitForError } from '@sentry-internal/event-proxy-server';
3-
import axios, { AxiosError } from 'axios';
4-
5-
const authToken = process.env.E2E_TEST_AUTH_TOKEN;
6-
const sentryTestOrgSlug = process.env.E2E_TEST_SENTRY_ORG_SLUG;
7-
const sentryTestProject = process.env.E2E_TEST_SENTRY_TEST_PROJECT;
8-
const EVENT_POLLING_TIMEOUT = 90_000;
9-
10-
test('Sends exception to Sentry', async ({ baseURL }) => {
11-
const { data } = await axios.get(`${baseURL}/test-error`);
12-
const { exceptionId } = data;
13-
14-
const url = `https://sentry.io/api/0/projects/${sentryTestOrgSlug}/${sentryTestProject}/events/${exceptionId}/`;
15-
16-
console.log(`Polling for error eventId: ${exceptionId}`);
17-
18-
await expect
19-
.poll(
20-
async () => {
21-
try {
22-
const response = await axios.get(url, { headers: { Authorization: `Bearer ${authToken}` } });
23-
24-
return response.status;
25-
} catch (e) {
26-
if (e instanceof AxiosError && e.response) {
27-
if (e.response.status !== 404) {
28-
throw e;
29-
} else {
30-
return e.response.status;
31-
}
32-
} else {
33-
throw e;
34-
}
35-
}
36-
},
37-
{ timeout: EVENT_POLLING_TIMEOUT },
38-
)
39-
.toBe(200);
40-
});
413

424
test('Sends correct error event', async ({ baseURL }) => {
435
const errorEventPromise = waitForError('node-connect', event => {
446
return !event.type && event.exception?.values?.[0]?.value === 'This is an exception';
457
});
468

47-
try {
48-
await axios.get(`${baseURL}/test-exception`);
49-
} catch {
50-
// this results in an error, but we don't care - we want to check the error event
51-
}
9+
await fetch(`${baseURL}/test-exception`);
5210

5311
const errorEvent = await errorEventPromise;
5412

dev-packages/e2e-tests/test-applications/node-connect/tests/transactions.test.ts

Lines changed: 2 additions & 31 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,5 @@
11
import { expect, test } from '@playwright/test';
22
import { waitForTransaction } from '@sentry-internal/event-proxy-server';
3-
import axios, { AxiosError } from 'axios';
43

54
const authToken = process.env.E2E_TEST_AUTH_TOKEN;
65
const sentryTestOrgSlug = process.env.E2E_TEST_SENTRY_ORG_SLUG;
@@ -15,7 +14,7 @@ test('Sends an API route transaction', async ({ baseURL }) => {
1514
);
1615
});
1716

18-
await axios.get(`${baseURL}/test-transaction`);
17+
await fetch(`${baseURL}/test-transaction`);
1918

2019
const transactionEvent = await pageloadTransactionEventPromise;
2120
const transactionEventId = transactionEvent.event_id;
@@ -35,7 +34,7 @@ test('Sends an API route transaction', async ({ baseURL }) => {
3534
'http.method': 'GET',
3635
'http.scheme': 'http',
3736
'http.target': '/test-transaction',
38-
'http.user_agent': 'axios/1.6.7',
37+
'http.user_agent': 'node',
3938
'http.flavor': '1.1',
4039
'net.transport': 'ip_tcp',
4140
'net.host.ip': expect.any(String),
@@ -97,32 +96,4 @@ test('Sends an API route transaction', async ({ baseURL }) => {
9796
},
9897
}),
9998
);
100-
101-
await expect
102-
.poll(
103-
async () => {
104-
try {
105-
const response = await axios.get(
106-
`https://sentry.io/api/0/projects/${sentryTestOrgSlug}/${sentryTestProject}/events/${transactionEventId}/`,
107-
{ headers: { Authorization: `Bearer ${authToken}` } },
108-
);
109-
110-
return response.status;
111-
} catch (e) {
112-
if (e instanceof AxiosError && e.response) {
113-
if (e.response.status !== 404) {
114-
throw e;
115-
} else {
116-
return e.response.status;
117-
}
118-
} else {
119-
throw e;
120-
}
121-
}
122-
},
123-
{
124-
timeout: EVENT_POLLING_TIMEOUT,
125-
},
126-
)
127-
.toBe(200);
12899
});
Lines changed: 7 additions & 90 deletions
Original file line numberDiff line numberDiff line change
@@ -1,54 +1,12 @@
11
import { expect, test } from '@playwright/test';
22
import { waitForError } from '@sentry-internal/event-proxy-server';
3-
import axios, { AxiosError, AxiosResponse } from 'axios';
4-
5-
const authToken = process.env.E2E_TEST_AUTH_TOKEN;
6-
const sentryTestOrgSlug = process.env.E2E_TEST_SENTRY_ORG_SLUG;
7-
const sentryTestProject = process.env.E2E_TEST_SENTRY_TEST_PROJECT;
8-
const EVENT_POLLING_TIMEOUT = 90_000;
9-
10-
test('Sends exception to Sentry', async ({ baseURL }) => {
11-
const { data } = await axios.get(`${baseURL}/test-error`);
12-
const { exceptionId } = data;
13-
14-
const url = `https://sentry.io/api/0/projects/${sentryTestOrgSlug}/${sentryTestProject}/events/${exceptionId}/`;
15-
16-
console.log(`Polling for error eventId: ${exceptionId}`);
17-
18-
await expect
19-
.poll(
20-
async () => {
21-
try {
22-
const response = await axios.get(url, { headers: { Authorization: `Bearer ${authToken}` } });
23-
24-
return response.status;
25-
} catch (e) {
26-
if (e instanceof AxiosError && e.response) {
27-
if (e.response.status !== 404) {
28-
throw e;
29-
} else {
30-
return e.response.status;
31-
}
32-
} else {
33-
throw e;
34-
}
35-
}
36-
},
37-
{ timeout: EVENT_POLLING_TIMEOUT },
38-
)
39-
.toBe(200);
40-
});
413

424
test('Sends correct error event', async ({ baseURL }) => {
435
const errorEventPromise = waitForError('node-express', event => {
446
return !event.type && event.exception?.values?.[0]?.value === 'This is an exception with id 123';
457
});
468

47-
try {
48-
await axios.get(`${baseURL}/test-exception/123`);
49-
} catch {
50-
// this results in an error, but we don't care - we want to check the error event
51-
}
9+
await fetch(`${baseURL}/test-exception/123`);
5210

5311
const errorEvent = await errorEventPromise;
5412

@@ -71,55 +29,14 @@ test('Sends correct error event', async ({ baseURL }) => {
7129
});
7230

7331
test('Should record caught exceptions with local variable', async ({ baseURL }) => {
74-
const { data } = await axios.get(`${baseURL}/test-local-variables-caught`);
75-
const { exceptionId } = data;
76-
77-
const url = `https://sentry.io/api/0/projects/${sentryTestOrgSlug}/${sentryTestProject}/events/${exceptionId}/json/`;
78-
79-
console.log(`Polling for error eventId: ${exceptionId}`);
80-
81-
let response: AxiosResponse;
82-
83-
await expect
84-
.poll(
85-
async () => {
86-
try {
87-
response = await axios.get(url, { headers: { Authorization: `Bearer ${authToken}` } });
88-
89-
return response.status;
90-
} catch (e) {
91-
if (e instanceof AxiosError && e.response) {
92-
if (e.response.status !== 404) {
93-
throw e;
94-
} else {
95-
return e.response.status;
96-
}
97-
} else {
98-
throw e;
99-
}
100-
}
101-
},
102-
{ timeout: EVENT_POLLING_TIMEOUT },
103-
)
104-
.toBe(200);
105-
106-
const frames = response!.data.exception.values[0].stacktrace.frames;
107-
108-
expect(frames[frames.length - 1].vars?.randomVariableToRecord).toBeDefined();
109-
});
110-
111-
test('Should record uncaught exceptions with local variable', async ({ baseURL }) => {
112-
const errorEventPromise = waitForError('node-express', errorEvent => {
113-
return !!errorEvent?.exception?.values?.[0]?.value?.includes('Uncaught Local Variable Error');
114-
});
115-
116-
await axios.get(`${baseURL}/test-local-variables-uncaught`).catch(() => {
117-
// noop
32+
const errorEventPromise = waitForError('node-express', event => {
33+
return event.transaction === 'GET /test-local-variables-caught';
11834
});
11935

120-
const routehandlerError = await errorEventPromise;
36+
await fetch(`${baseURL}/test-local-variables-caught`);
12137

122-
const frames = routehandlerError!.exception!.values![0]!.stacktrace!.frames!;
38+
const errorEvent = await errorEventPromise;
12339

124-
expect(frames[frames.length - 1].vars?.randomVariableToRecord).toBeDefined();
40+
const frames = errorEvent.exception?.values?.[0].stacktrace?.frames;
41+
expect(frames?.[frames.length - 1].vars?.randomVariableToRecord).toBeDefined();
12542
});

dev-packages/e2e-tests/test-applications/node-express/tests/transactions.test.ts

Lines changed: 2 additions & 36 deletions
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,5 @@
11
import { expect, test } from '@playwright/test';
22
import { waitForTransaction } from '@sentry-internal/event-proxy-server';
3-
import axios, { AxiosError } from 'axios';
4-
5-
const authToken = process.env.E2E_TEST_AUTH_TOKEN;
6-
const sentryTestOrgSlug = process.env.E2E_TEST_SENTRY_ORG_SLUG;
7-
const sentryTestProject = process.env.E2E_TEST_SENTRY_TEST_PROJECT;
8-
const EVENT_POLLING_TIMEOUT = 90_000;
93

104
test('Sends an API route transaction', async ({ baseURL }) => {
115
const pageloadTransactionEventPromise = waitForTransaction('node-express', transactionEvent => {
@@ -15,7 +9,7 @@ test('Sends an API route transaction', async ({ baseURL }) => {
159
);
1610
});
1711

18-
await axios.get(`${baseURL}/test-transaction`);
12+
await fetch(`${baseURL}/test-transaction`);
1913

2014
const transactionEvent = await pageloadTransactionEventPromise;
2115
const transactionEventId = transactionEvent.event_id;
@@ -35,7 +29,7 @@ test('Sends an API route transaction', async ({ baseURL }) => {
3529
'http.method': 'GET',
3630
'http.scheme': 'http',
3731
'http.target': '/test-transaction',
38-
'http.user_agent': 'axios/1.6.7',
32+
'http.user_agent': 'node',
3933
'http.flavor': '1.1',
4034
'net.transport': 'ip_tcp',
4135
'net.host.ip': expect.any(String),
@@ -124,32 +118,4 @@ test('Sends an API route transaction', async ({ baseURL }) => {
124118
timestamp: expect.any(Number),
125119
trace_id: expect.any(String),
126120
});
127-
128-
await expect
129-
.poll(
130-
async () => {
131-
try {
132-
const response = await axios.get(
133-
`https://sentry.io/api/0/projects/${sentryTestOrgSlug}/${sentryTestProject}/events/${transactionEventId}/`,
134-
{ headers: { Authorization: `Bearer ${authToken}` } },
135-
);
136-
137-
return response.status;
138-
} catch (e) {
139-
if (e instanceof AxiosError && e.response) {
140-
if (e.response.status !== 404) {
141-
throw e;
142-
} else {
143-
return e.response.status;
144-
}
145-
} else {
146-
throw e;
147-
}
148-
}
149-
},
150-
{
151-
timeout: EVENT_POLLING_TIMEOUT,
152-
},
153-
)
154-
.toBe(200);
155121
});

dev-packages/e2e-tests/test-applications/node-fastify/src/app.ts

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,19 @@
11
import type * as S from '@sentry/node';
22
const Sentry = require('@sentry/node') as typeof S;
33

4+
// We wrap console.warn to find out if a warning is incorrectly logged
5+
console.warn = new Proxy(console.warn, {
6+
apply: function (target, thisArg, argumentsList) {
7+
const msg = argumentsList[0];
8+
if (typeof msg === 'string' && msg.startsWith('[Sentry]')) {
9+
console.error(`Sentry warning was triggered: ${msg}`);
10+
process.exit(1);
11+
}
12+
13+
return target.apply(thisArg, argumentsList);
14+
},
15+
});
16+
417
Sentry.init({
518
environment: 'qa', // dynamic sampling bias to keep transactions
619
dsn: process.env.E2E_TEST_DSN,

dev-packages/e2e-tests/test-applications/node-fastify/tests/errors.test.ts

Lines changed: 1 addition & 43 deletions
Original file line numberDiff line numberDiff line change
@@ -1,54 +1,12 @@
11
import { expect, test } from '@playwright/test';
22
import { waitForError } from '@sentry-internal/event-proxy-server';
3-
import axios, { AxiosError } from 'axios';
4-
5-
const authToken = process.env.E2E_TEST_AUTH_TOKEN;
6-
const sentryTestOrgSlug = process.env.E2E_TEST_SENTRY_ORG_SLUG;
7-
const sentryTestProject = process.env.E2E_TEST_SENTRY_TEST_PROJECT;
8-
const EVENT_POLLING_TIMEOUT = 90_000;
9-
10-
test('Sends exception to Sentry', async ({ baseURL }) => {
11-
const { data } = await axios.get(`${baseURL}/test-error`);
12-
const { exceptionId } = data;
13-
14-
const url = `https://sentry.io/api/0/projects/${sentryTestOrgSlug}/${sentryTestProject}/events/${exceptionId}/`;
15-
16-
console.log(`Polling for error eventId: ${exceptionId}`);
17-
18-
await expect
19-
.poll(
20-
async () => {
21-
try {
22-
const response = await axios.get(url, { headers: { Authorization: `Bearer ${authToken}` } });
23-
24-
return response.status;
25-
} catch (e) {
26-
if (e instanceof AxiosError && e.response) {
27-
if (e.response.status !== 404) {
28-
throw e;
29-
} else {
30-
return e.response.status;
31-
}
32-
} else {
33-
throw e;
34-
}
35-
}
36-
},
37-
{ timeout: EVENT_POLLING_TIMEOUT },
38-
)
39-
.toBe(200);
40-
});
413

424
test('Sends correct error event', async ({ baseURL }) => {
435
const errorEventPromise = waitForError('node-fastify', event => {
446
return !event.type && event.exception?.values?.[0]?.value === 'This is an exception with id 123';
457
});
468

47-
try {
48-
await axios.get(`${baseURL}/test-exception/123`);
49-
} catch {
50-
// this results in an error, but we don't care - we want to check the error event
51-
}
9+
await fetch(`${baseURL}/test-exception/123`);
5210

5311
const errorEvent = await errorEventPromise;
5412

0 commit comments

Comments
 (0)