Skip to content

Commit 539b026

Browse files
authored
test(browser): Add integration tests for startTransaction (#4343)
1 parent 74d2755 commit 539b026

File tree

5 files changed

+124
-5
lines changed

5 files changed

+124
-5
lines changed
Lines changed: 30 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,30 @@
1+
const transaction = Sentry.startTransaction({ name: 'test_transaction_1' });
2+
const span_1 = transaction.startChild({
3+
op: 'span_1',
4+
data: {
5+
foo: 'bar',
6+
baz: [1, 2, 3],
7+
},
8+
});
9+
for (let i = 0; i < 2000; i++);
10+
11+
// span_1 finishes
12+
span_1.finish();
13+
14+
// span_2 doesn't finish
15+
const span_2 = transaction.startChild({ op: 'span_2' });
16+
for (let i = 0; i < 4000; i++);
17+
18+
const span_3 = transaction.startChild({ op: 'span_3' });
19+
for (let i = 0; i < 4000; i++);
20+
21+
// span_4 is the child of span_3 but doesn't finish.
22+
const span_4 = span_3.startChild({ op: 'span_4', data: { qux: 'quux' } });
23+
24+
// span_5 is another child of span_3 but finishes.
25+
const span_5 = span_3.startChild({ op: 'span_5' }).finish();
26+
27+
// span_3 also finishes
28+
span_3.finish();
29+
30+
transaction.finish();
Lines changed: 34 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,34 @@
1+
import { expect } from '@playwright/test';
2+
3+
import { sentryTest } from '../../../../utils/fixtures';
4+
import { getSentryTransactionRequest } from '../../../../utils/helpers';
5+
6+
sentryTest('should report a transaction in an envelope', async ({ getLocalTestPath, page }) => {
7+
const url = await getLocalTestPath({ testDir: __dirname });
8+
const transaction = await getSentryTransactionRequest(page, url);
9+
10+
expect(transaction.transaction).toBe('test_transaction_1');
11+
expect(transaction.spans).toBeDefined();
12+
});
13+
14+
sentryTest('should report finished spans as children of the root transaction', async ({ getLocalTestPath, page }) => {
15+
const url = await getLocalTestPath({ testDir: __dirname });
16+
const transaction = await getSentryTransactionRequest(page, url);
17+
18+
const rootSpanId = transaction?.contexts?.trace.spanId;
19+
20+
expect(transaction.spans).toHaveLength(3);
21+
22+
const span_1 = transaction.spans?.[0];
23+
expect(span_1?.op).toBe('span_1');
24+
expect(span_1?.parentSpanId).toEqual(rootSpanId);
25+
expect(span_1?.data).toMatchObject({ foo: 'bar', baz: [1, 2, 3] });
26+
27+
const span_3 = transaction.spans?.[1];
28+
expect(span_3?.op).toBe('span_3');
29+
expect(span_3?.parentSpanId).toEqual(rootSpanId);
30+
31+
const span_5 = transaction.spans?.[2];
32+
expect(span_5?.op).toBe('span_5');
33+
expect(span_5?.parentSpanId).toEqual(span_3?.spanId);
34+
});
Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
import * as Sentry from '@sentry/browser';
2+
// eslint-disable-next-line no-unused-vars
3+
import * as _ from '@sentry/tracing';
4+
5+
window.Sentry = Sentry;
6+
7+
Sentry.init({
8+
dsn: 'https://[email protected]/1337',
9+
tracesSampleRate: 1.0,
10+
});
Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
<!DOCTYPE html>
2+
<html>
3+
<head>
4+
<meta charset="utf-8" />
5+
<title></title>
6+
<script src="{{htmlWebpackPlugin.options.initialization}}"></script>
7+
</head>
8+
<body>
9+
<script src="{{htmlWebpackPlugin.options.subject}}"></script>
10+
</body>
11+
</html>

packages/integration-tests/utils/helpers.ts

Lines changed: 39 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,10 @@
1-
import { Page } from '@playwright/test';
1+
import { Page, Request } from '@playwright/test';
22
import { Event } from '@sentry/types';
33

44
const storeUrlRegex = /\.sentry\.io\/api\/\d+\/store\//;
5+
const envelopeUrlRegex = /\.sentry\.io\/api\/\d+\/envelope\//;
6+
7+
type SentryRequestType = 'event' | 'transaction';
58

69
/**
710
* Run script at the given path inside the test environment.
@@ -15,18 +18,41 @@ async function runScriptInSandbox(page: Page, path: string): Promise<void> {
1518
}
1619

1720
/**
18-
* Wait and get Sentry's request sending the event at the given URL
21+
* Wait and get Sentry's request sending the event.
22+
*
23+
* @param {Page} page
24+
* @returns {*} {Promise<Request>}
25+
*/
26+
async function waitForSentryRequest(page: Page, requestType: SentryRequestType = 'event'): Promise<Request> {
27+
return page.waitForRequest(requestType === 'event' ? storeUrlRegex : envelopeUrlRegex);
28+
}
29+
30+
/**
31+
* Wait and get Sentry's request sending the event at the given URL, or the current page
1932
*
2033
* @param {Page} page
2134
* @param {string} url
2235
* @return {*} {Promise<Event>}
2336
*/
24-
async function getSentryRequest(page: Page, url: string): Promise<Event> {
25-
const request = (await Promise.all([page.goto(url), page.waitForRequest(storeUrlRegex)]))[1];
37+
async function getSentryRequest(page: Page, url?: string): Promise<Event> {
38+
const request = (await Promise.all([page.goto(url || '#'), waitForSentryRequest(page)]))[1];
2639

2740
return JSON.parse((request && request.postData()) || '');
2841
}
2942

43+
async function getSentryTransactionRequest(page: Page, url?: string): Promise<Event> {
44+
const request = (await Promise.all([page.goto(url || '#'), waitForSentryRequest(page, 'transaction')]))[1];
45+
46+
try {
47+
// https://develop.sentry.dev/sdk/envelopes/
48+
const envelope = request?.postData() || '';
49+
50+
// Third row of the envelop is the event payload.
51+
return envelope.split('\n').map(line => JSON.parse(line))[2];
52+
} catch (err) {
53+
return Promise.reject(err);
54+
}
55+
}
3056
/**
3157
* Get Sentry events at the given URL, or the current page.
3258
*
@@ -96,4 +122,12 @@ async function injectScriptAndGetEvents(page: Page, url: string, scriptPath: str
96122
return await getSentryEvents(page);
97123
}
98124

99-
export { runScriptInSandbox, getMultipleSentryRequests, getSentryRequest, getSentryEvents, injectScriptAndGetEvents };
125+
export {
126+
runScriptInSandbox,
127+
waitForSentryRequest,
128+
getMultipleSentryRequests,
129+
getSentryRequest,
130+
getSentryTransactionRequest,
131+
getSentryEvents,
132+
injectScriptAndGetEvents,
133+
};

0 commit comments

Comments
 (0)