Skip to content

Commit 722683d

Browse files
committed
create test that actually failed previously
1 parent 7e6d2ae commit 722683d

File tree

4 files changed

+72
-12
lines changed

4 files changed

+72
-12
lines changed
Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,25 @@
1+
<!DOCTYPE html>
2+
<html>
3+
<head>
4+
<meta charset="utf-8" />
5+
<title></title>
6+
</head>
7+
<body>
8+
<button id="button1" type="button">Button 1</button>
9+
10+
<script type="module">
11+
async function run() {
12+
Sentry.startSpan({ name: 'parent_span', op: 'test' }, async () => {
13+
console.log('throwing error')
14+
throw new Error('Async Thrown Error');
15+
});
16+
}
17+
18+
const button = document.getElementById('button1');
19+
button.addEventListener('click', () => {
20+
void run();
21+
console.log('click');
22+
});
23+
</script>
24+
</body>
25+
</html>
Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,27 @@
1+
import { expect } from '@playwright/test';
2+
import type { Event } from '@sentry/types';
3+
4+
import { sentryTest } from '../../../../utils/fixtures';
5+
import { getMultipleSentryEnvelopeRequests, shouldSkipTracingTest } from '../../../../utils/helpers';
6+
7+
sentryTest(
8+
"should capture a thrown error within an async startSpan callback that's not awaited properly",
9+
async ({ getLocalTestPath, page }) => {
10+
if (shouldSkipTracingTest()) {
11+
sentryTest.skip();
12+
}
13+
const envelopePromise = getMultipleSentryEnvelopeRequests<Event>(page, 2);
14+
15+
const url = await getLocalTestPath({ testDir: __dirname });
16+
await page.goto(url);
17+
18+
const clickPromise = page.getByText('Button 1').click();
19+
20+
// awaiting both events simultaneously to avoid race conditions
21+
const [, events] = await Promise.all([clickPromise, envelopePromise]);
22+
const [txn, err] = events[0]?.type === 'transaction' ? [events[0], events[1]] : [events[1], events[0]];
23+
24+
expect(txn).toMatchObject({ transaction: 'parent_span' });
25+
expect(err?.exception?.values?.[0]?.value).toBe('Async Thrown Error');
26+
},
27+
);

packages/browser-integration-tests/suites/public-api/startSpan/error-async-throw/template.html

Lines changed: 6 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -7,16 +7,19 @@
77
<body>
88
<button id="button1" type="button">Button 1</button>
99

10-
<script>
10+
<script type="module">
1111
async function run() {
12+
await Promise.resolve();
1213
await Sentry.startSpan({ name: 'parent_span', op: 'test' }, async () => {
14+
console.log('throwing error')
1315
throw new Error('Async Thrown Error');
1416
});
1517
}
1618

1719
const button = document.getElementById('button1');
18-
button.addEventListener('click', async () => {
19-
await run();
20+
button.addEventListener('click', () => {
21+
void run();
22+
console.log('click');
2023
});
2124
</script>
2225
</body>

packages/core/src/tracing/trace.ts

Lines changed: 14 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -89,9 +89,9 @@ export function trace<T>(
8989
* and the `span` returned from the callback will be undefined.
9090
*/
9191
export function startSpan<T>(context: TransactionContext, callback: (span: Span | undefined) => T): T {
92-
console.log('START SPAN 2');
9392
const ctx = normalizeContext(context);
9493

94+
// @ts-expect-error - wtf
9595
return withScope(scope => {
9696
const hub = getCurrentHub();
9797
const parentSpan = scope.getSpan();
@@ -113,20 +113,21 @@ export function startSpan<T>(context: TransactionContext, callback: (span: Span
113113
}
114114

115115
if (isThenable(maybePromiseResult)) {
116-
Promise.resolve(maybePromiseResult).then(
117-
() => {
116+
return maybePromiseResult.then(
117+
res => {
118118
finishAndSetSpan();
119+
return res;
119120
},
120-
() => {
121+
e => {
121122
activeSpan && activeSpan.setStatus('internal_error');
122123
finishAndSetSpan();
124+
throw e;
123125
},
124126
);
125127
} else {
126128
finishAndSetSpan();
129+
return maybePromiseResult;
127130
}
128-
129-
return maybePromiseResult;
130131
});
131132
}
132133

@@ -172,9 +173,13 @@ export function startSpanManual<T>(
172173
}
173174

174175
if (isThenable(maybePromiseResult)) {
175-
Promise.resolve(maybePromiseResult).then(undefined, () => {
176-
activeSpan && activeSpan.setStatus('internal_error');
177-
});
176+
maybePromiseResult.then(
177+
res => res,
178+
e => {
179+
activeSpan && activeSpan.setStatus('internal_error');
180+
throw e;
181+
},
182+
);
178183
}
179184

180185
return maybePromiseResult;

0 commit comments

Comments
 (0)