Skip to content

Commit c8d2771

Browse files
committed
add e2e test
1 parent 5e835e3 commit c8d2771

File tree

9 files changed

+168
-17
lines changed

9 files changed

+168
-17
lines changed
Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,2 @@
1+
@sentry:registry=http://127.0.0.1:4873
2+
@sentry-internal:registry=http://127.0.0.1:4873
Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,22 @@
1+
{
2+
"name": "node-express-app",
3+
"version": "1.0.0",
4+
"private": true,
5+
"scripts": {
6+
"start": "node src/run.mjs",
7+
"test": "playwright test",
8+
"clean": "npx rimraf node_modules pnpm-lock.yaml",
9+
"test:build": "pnpm install",
10+
"test:assert": "pnpm test"
11+
},
12+
"dependencies": {
13+
"@sentry/aws-serverless": "link:../../../../packages/aws-serverless/build/aws/dist-serverless/nodejs/node_modules/@sentry/aws-serverless"
14+
},
15+
"devDependencies": {
16+
"@sentry-internal/test-utils": "link:../../../test-utils",
17+
"@playwright/test": "~1.53.2"
18+
},
19+
"volta": {
20+
"extends": "../../package.json"
21+
}
22+
}
Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
import { getPlaywrightConfig } from '@sentry-internal/test-utils';
2+
3+
export default getPlaywrightConfig();
Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,21 @@
1+
import * as Sentry from '@sentry/aws-serverless';
2+
3+
import * as http from 'node:http';
4+
5+
async function handle() {
6+
await Sentry.startSpan({ name: 'manual-span', op: 'test' }, async () => {
7+
await new Promise(resolve => {
8+
http.get('http://example.com', res => {
9+
res.on('data', d => {
10+
process.stdout.write(d);
11+
});
12+
13+
res.on('end', () => {
14+
resolve();
15+
});
16+
});
17+
});
18+
});
19+
}
20+
21+
export { handle };
Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,8 @@
1+
import { handle } from './lambda-function.mjs';
2+
3+
const event = {};
4+
const context = {
5+
invokedFunctionArn: 'arn:aws:lambda:us-east-1:123453789012:function:my-lambda',
6+
functionName: 'my-lambda',
7+
};
8+
await handle(event, context);
Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,17 @@
1+
import child_process from 'node:child_process';
2+
3+
child_process.execSync('node ./src/run-lambda.mjs', {
4+
stdio: 'inherit',
5+
env: {
6+
...process.env,
7+
// On AWS, LAMBDA_TASK_ROOT is usually /var/task but for testing, we set it to the CWD to correctly apply our handler
8+
LAMBDA_TASK_ROOT: process.cwd(),
9+
_HANDLER: 'src/lambda-function.handle',
10+
11+
NODE_OPTIONS: '--import @sentry/aws-serverless/awslambda-auto',
12+
SENTRY_DSN: 'http://public@localhost:3031/1337',
13+
SENTRY_TRACES_SAMPLE_RATE: '1.0',
14+
SENTRY_DEBUG: 'true',
15+
},
16+
cwd: process.cwd(),
17+
});
Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,6 @@
1+
import { startEventProxyServer } from '@sentry-internal/test-utils';
2+
3+
startEventProxyServer({
4+
port: 3031,
5+
proxyServerName: 'aws-serverless-lambda-layer-esm',
6+
});
Lines changed: 72 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,72 @@
1+
import * as child_process from 'child_process';
2+
import { expect, test } from '@playwright/test';
3+
import { waitForTransaction } from '@sentry-internal/test-utils';
4+
5+
test('Lambda layer SDK bundle sends events', async ({ request }) => {
6+
const transactionEventPromise = waitForTransaction('aws-serverless-lambda-layer-esm', transactionEvent => {
7+
return transactionEvent?.transaction === 'my-lambda';
8+
});
9+
10+
// Waiting for 1s here because attaching the listener for events in `waitForTransaction` is not synchronous
11+
// Since in this test, we don't start a browser via playwright, we don't have the usual delays (page.goto, etc)
12+
// which are usually enough for us to never have noticed this race condition before.
13+
// This is a workaround but probably sufficient as long as we only experience it in this test.
14+
await new Promise<void>(resolve =>
15+
setTimeout(() => {
16+
resolve();
17+
}, 1000),
18+
);
19+
20+
child_process.execSync('pnpm start', {
21+
stdio: 'ignore',
22+
});
23+
24+
const transactionEvent = await transactionEventPromise;
25+
26+
// shows the SDK sent a transaction
27+
expect(transactionEvent.transaction).toEqual('my-lambda'); // name should be the function name
28+
expect(transactionEvent.contexts?.trace).toEqual({
29+
data: {
30+
'sentry.sample_rate': 1,
31+
'sentry.source': 'custom',
32+
'sentry.origin': 'auto.otel.aws-lambda',
33+
'sentry.op': 'function.aws.lambda',
34+
'cloud.account.id': '123453789012',
35+
'faas.id': 'arn:aws:lambda:us-east-1:123453789012:function:my-lambda',
36+
'faas.coldstart': true,
37+
'otel.kind': 'SERVER',
38+
},
39+
op: 'function.aws.lambda',
40+
origin: 'auto.otel.aws-lambda',
41+
span_id: expect.stringMatching(/[a-f0-9]{16}/),
42+
status: 'ok',
43+
trace_id: expect.stringMatching(/[a-f0-9]{32}/),
44+
});
45+
46+
expect(transactionEvent.spans).toHaveLength(2);
47+
48+
// shows that the Otel Http instrumentation is working
49+
expect(transactionEvent.spans).toContainEqual(
50+
expect.objectContaining({
51+
data: expect.objectContaining({
52+
'sentry.op': 'http.client',
53+
'sentry.origin': 'auto.http.otel.http',
54+
url: 'http://example.com/',
55+
}),
56+
description: 'GET http://example.com/',
57+
op: 'http.client',
58+
}),
59+
);
60+
61+
// shows that the manual span creation is working
62+
expect(transactionEvent.spans).toContainEqual(
63+
expect.objectContaining({
64+
data: expect.objectContaining({
65+
'sentry.op': 'test',
66+
'sentry.origin': 'manual',
67+
}),
68+
description: 'manual-span',
69+
op: 'test',
70+
}),
71+
);
72+
});

yarn.lock

Lines changed: 17 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -28318,7 +28318,7 @@ string-template@~0.2.1:
2831828318
is-fullwidth-code-point "^3.0.0"
2831928319
strip-ansi "^6.0.1"
2832028320

28321-
"string-width@^1.0.2 || 2 || 3 || 4", string-width@^4.0.0, string-width@^4.1.0, string-width@^4.2.0, string-width@^4.2.2, string-width@^4.2.3:
28321+
[email protected], "string-width@^1.0.2 || 2 || 3 || 4", string-width@^4.0.0, string-width@^4.1.0, string-width@^4.2.0, string-width@^4.2.2, string-width@^4.2.3:
2832228322
version "4.2.3"
2832328323
resolved "https://registry.yarnpkg.com/string-width/-/string-width-4.2.3.tgz#269c7117d27b05ad2e536830a8ec895ef9c6d010"
2832428324
integrity sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==
@@ -28428,6 +28428,13 @@ stringify-object@^3.2.1:
2842828428
dependencies:
2842928429
ansi-regex "^5.0.1"
2843028430

28431+
[email protected], strip-ansi@^6.0.0, strip-ansi@^6.0.1:
28432+
version "6.0.1"
28433+
resolved "https://registry.yarnpkg.com/strip-ansi/-/strip-ansi-6.0.1.tgz#9e26c63d30f53443e9489495b2105d37b67a85d9"
28434+
integrity sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==
28435+
dependencies:
28436+
ansi-regex "^5.0.1"
28437+
2843128438
strip-ansi@^3.0.0:
2843228439
version "3.0.1"
2843328440
resolved "https://registry.yarnpkg.com/strip-ansi/-/strip-ansi-3.0.1.tgz#6a385fb8853d952d5ff05d0e8aaf94278dc63dcf"
@@ -28449,13 +28456,6 @@ strip-ansi@^5.1.0, strip-ansi@^5.2.0:
2844928456
dependencies:
2845028457
ansi-regex "^4.1.0"
2845128458

28452-
strip-ansi@^6.0.0, strip-ansi@^6.0.1:
28453-
version "6.0.1"
28454-
resolved "https://registry.yarnpkg.com/strip-ansi/-/strip-ansi-6.0.1.tgz#9e26c63d30f53443e9489495b2105d37b67a85d9"
28455-
integrity sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==
28456-
dependencies:
28457-
ansi-regex "^5.0.1"
28458-
2845928459
strip-ansi@^7.0.1, strip-ansi@^7.1.0:
2846028460
version "7.1.0"
2846128461
resolved "https://registry.yarnpkg.com/strip-ansi/-/strip-ansi-7.1.0.tgz#d5b6568ca689d8561370b0707685d22434faff45"
@@ -28605,7 +28605,7 @@ [email protected], stylus@^0.59.0:
2860528605
sax "~1.2.4"
2860628606
source-map "^0.7.3"
2860728607

28608-
sucrase@^3.27.0, sucrase@^3.35.0:
28608+
sucrase@^3.27.0, sucrase@^3.35.0, sucrase@getsentry/sucrase#es2020-polyfills:
2860928609
version "3.36.0"
2861028610
resolved "https://codeload.github.com/getsentry/sucrase/tar.gz/fd682f6129e507c00bb4e6319cc5d6b767e36061"
2861128611
dependencies:
@@ -31475,19 +31475,19 @@ [email protected]:
3147531475
string-width "^4.1.0"
3147631476
strip-ansi "^6.0.0"
3147731477

31478-
wrap-ansi@^6.0.1:
31479-
version "6.2.0"
31480-
resolved "https://registry.yarnpkg.com/wrap-ansi/-/wrap-ansi-6.2.0.tgz#e9393ba07102e6c91a3b221478f0257cd2856e53"
31481-
integrity sha512-r6lPcBGxZXlIcymEu7InxDMhdW0KDxpLgoFLcguasxCaJ/SOIZwINatK9KY/tf+ZrlywOKU0UDj3ATXUBfxJXA==
31478+
wrap-ansi@7.0.0, wrap-ansi@^7.0.0:
31479+
version "7.0.0"
31480+
resolved "https://registry.yarnpkg.com/wrap-ansi/-/wrap-ansi-7.0.0.tgz#67e145cff510a6a6984bdf1152911d69d2eb9e43"
31481+
integrity sha512-YVGIj2kamLSTxw6NsZjoBxfSwsn0ycdesmc4p+Q21c5zPuZ1pl+NfxVdxPtdHvmNVOQ6XSYG4AUtyt/Fi7D16Q==
3148231482
dependencies:
3148331483
ansi-styles "^4.0.0"
3148431484
string-width "^4.1.0"
3148531485
strip-ansi "^6.0.0"
3148631486

31487-
wrap-ansi@^7.0.0:
31488-
version "7.0.0"
31489-
resolved "https://registry.yarnpkg.com/wrap-ansi/-/wrap-ansi-7.0.0.tgz#67e145cff510a6a6984bdf1152911d69d2eb9e43"
31490-
integrity sha512-YVGIj2kamLSTxw6NsZjoBxfSwsn0ycdesmc4p+Q21c5zPuZ1pl+NfxVdxPtdHvmNVOQ6XSYG4AUtyt/Fi7D16Q==
31487+
wrap-ansi@^6.0.1:
31488+
version "6.2.0"
31489+
resolved "https://registry.yarnpkg.com/wrap-ansi/-/wrap-ansi-6.2.0.tgz#e9393ba07102e6c91a3b221478f0257cd2856e53"
31490+
integrity sha512-r6lPcBGxZXlIcymEu7InxDMhdW0KDxpLgoFLcguasxCaJ/SOIZwINatK9KY/tf+ZrlywOKU0UDj3ATXUBfxJXA==
3149131491
dependencies:
3149231492
ansi-styles "^4.0.0"
3149331493
string-width "^4.1.0"

0 commit comments

Comments
 (0)