Skip to content

Commit 2ec5e09

Browse files
committed
test(e2e): Port the astro-6-cf-workers E2E app to span streaming
Drops the `traceLifecycle: 'static'` pin and rewrites the specs to assert on streamed spans.
1 parent 19a3913 commit 2ec5e09

5 files changed

Lines changed: 241 additions & 371 deletions

File tree

‎dev-packages/e2e-tests/test-applications/astro-6-cf-workers/sentry.client.config.js‎

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,6 @@
11
import * as Sentry from '@sentry/astro';
22

33
Sentry.init({
4-
traceLifecycle: 'static',
54
dsn: import.meta.env.PUBLIC_E2E_TEST_DSN,
65
environment: 'qa',
76
tracesSampleRate: 1.0,

‎dev-packages/e2e-tests/test-applications/astro-6-cf-workers/sentry.server.config.js‎

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,6 @@ import handler from '@astrojs/cloudflare/entrypoints/server';
33

44
export default Sentry.withSentry(
55
env => ({
6-
traceLifecycle: 'static',
76
dsn: env.E2E_TEST_DSN,
87
environment: 'qa',
98
tracesSampleRate: 1.0,
Lines changed: 34 additions & 27 deletions
Original file line numberDiff line numberDiff line change
@@ -1,43 +1,50 @@
11
import { expect, test } from '@playwright/test';
2-
import { waitForTransaction } from '@sentry-internal/test-utils';
2+
import { collectStreamedSpans, getSpanOp } from '@sentry-internal/test-utils';
3+
4+
const APP_NAME = 'astro-6-cf-workers';
35

46
test('a real mysql query emits a db span with orchestrion-channel attributes', async ({ request }) => {
5-
const transactionPromise = waitForTransaction('astro-6-cf-workers', transactionEvent => {
6-
return (
7-
transactionEvent.contexts?.trace?.op === 'http.server' &&
8-
(transactionEvent.spans?.some(span => span.op === 'db') ?? false)
9-
);
10-
});
7+
const spansPromise = collectStreamedSpans(
8+
APP_NAME,
9+
spans =>
10+
spans.some(span => getSpanOp(span) === 'http.server' && span.is_segment) &&
11+
spans.some(span => getSpanOp(span) === 'db'),
12+
);
1113

1214
const res = await request.get('/db-mysql');
1315
expect(res.status()).toBe(200);
1416

15-
const transactionEvent = await transactionPromise;
16-
const dbSpans = transactionEvent.spans!.filter(span => span.op === 'db');
17+
const spans = await spansPromise;
18+
const dbSpans = spans.filter(span => getSpanOp(span) === 'db');
1719

18-
const firstQuery = dbSpans.find(span => span.description === 'SELECT 1 + 1 AS solution');
20+
const firstQuery = dbSpans.find(span => span.attributes['db.query.text']?.value === 'SELECT 1 + 1 AS solution');
1921
expect(firstQuery).toBeDefined();
20-
expect(firstQuery!.data?.['sentry.origin']).toBe('auto.db.mysql');
21-
expect(firstQuery!.data?.['db.system.name']).toBe('mysql');
22-
expect(firstQuery!.data?.['db.query.text']).toBe('SELECT 1 + 1 AS solution');
23-
expect(firstQuery!.data?.['server.address']).toBe('127.0.0.1');
24-
expect(firstQuery!.data?.['server.port']).toBe(3306);
25-
expect(firstQuery!.data?.['db.user']).toBe('root');
22+
// With span streaming the span name is the low-cardinality query summary; the statement stays in
23+
// `db.query.text`.
24+
expect(firstQuery!.name).toBe('SELECT');
25+
expect(firstQuery!.attributes['sentry.origin']?.value).toBe('auto.db.mysql');
26+
expect(firstQuery!.attributes['db.system.name']?.value).toBe('mysql');
27+
expect(firstQuery!.attributes['db.query.text']?.value).toBe('SELECT 1 + 1 AS solution');
28+
expect(firstQuery!.attributes['server.address']?.value).toBe('127.0.0.1');
29+
expect(firstQuery!.attributes['server.port']?.value).toBe(3306);
30+
expect(firstQuery!.attributes['db.user']?.value).toBe('root');
2631
});
2732

28-
test('a nested query lands on the same transaction (async context restored)', async ({ request }) => {
29-
const transactionPromise = waitForTransaction('astro-6-cf-workers', transactionEvent => {
30-
return (
31-
transactionEvent.contexts?.trace?.op === 'http.server' &&
32-
(transactionEvent.spans?.filter(span => span.op === 'db').length ?? 0) >= 2
33-
);
34-
});
33+
test('a nested query lands on the same trace (async context restored)', async ({ request }) => {
34+
const spansPromise = collectStreamedSpans(
35+
APP_NAME,
36+
spans =>
37+
spans.some(span => getSpanOp(span) === 'http.server' && span.is_segment) &&
38+
spans.filter(span => getSpanOp(span) === 'db').length >= 2,
39+
);
3540

3641
const res = await request.get('/db-mysql');
3742
expect(res.status()).toBe(200);
3843

39-
const transactionEvent = await transactionPromise;
40-
const descriptions = transactionEvent.spans!.filter(span => span.op === 'db').map(span => span.description);
41-
expect(descriptions).toContain('SELECT 1 + 1 AS solution');
42-
expect(descriptions).toContain('SELECT NOW()');
44+
const spans = await spansPromise;
45+
const queryTexts = spans
46+
.filter(span => getSpanOp(span) === 'db')
47+
.map(span => span.attributes['db.query.text']?.value);
48+
expect(queryTexts).toContain('SELECT 1 + 1 AS solution');
49+
expect(queryTexts).toContain('SELECT NOW()');
4350
});

‎dev-packages/e2e-tests/test-applications/astro-6-cf-workers/tests/errors.server.test.ts‎

Lines changed: 17 additions & 32 deletions
Original file line numberDiff line numberDiff line change
@@ -1,14 +1,14 @@
11
import { expect, test } from '@playwright/test';
2-
import { waitForError, waitForTransaction } from '@sentry-internal/test-utils';
2+
import { getSpanOp, waitForError, waitForStreamedSpan } from '@sentry-internal/test-utils';
33

44
test.describe('server-side errors', () => {
55
test('captures SSR error', async ({ page }) => {
66
const errorEventPromise = waitForError('astro-6-cf-workers', errorEvent => {
77
return errorEvent?.exception?.values?.[0]?.value === "Cannot read properties of undefined (reading 'x')";
88
});
99

10-
const transactionEventPromise = waitForTransaction('astro-6-cf-workers', transactionEvent => {
11-
return transactionEvent.transaction === 'GET /ssr-error';
10+
const spanPromise = waitForStreamedSpan('astro-6-cf-workers', span => {
11+
return getSpanOp(span) === 'http.server' && span.is_segment && span.name === 'GET /ssr-error';
1212
});
1313

1414
// This page returns an error status code, so we need to catch the navigation error
@@ -17,19 +17,14 @@ test.describe('server-side errors', () => {
1717
});
1818

1919
const errorEvent = await errorEventPromise;
20-
const transactionEvent = await transactionEventPromise;
20+
const span = await spanPromise;
2121

22-
expect(transactionEvent).toMatchObject({
23-
transaction: 'GET /ssr-error',
24-
spans: [],
25-
});
26-
27-
const traceId = transactionEvent.contexts?.trace?.trace_id;
28-
const spanId = transactionEvent.contexts?.trace?.span_id;
22+
const traceId = span.trace_id;
23+
const spanId = span.span_id;
2924

3025
expect(traceId).toMatch(/[a-f0-9]{32}/);
3126
expect(spanId).toMatch(/[a-f0-9]{16}/);
32-
expect(transactionEvent.contexts?.trace?.parent_span_id).toBeUndefined();
27+
expect(span.parent_span_id).toBeUndefined();
3328

3429
expect(errorEvent).toMatchObject({
3530
contexts: {
@@ -80,38 +75,28 @@ test.describe('server-side errors', () => {
8075
const errorEventPromise = waitForError('astro-6-cf-workers', errorEvent => {
8176
return errorEvent?.exception?.values?.[0]?.value === 'Endpoint Error';
8277
});
83-
const transactionEventApiPromise = waitForTransaction('astro-6-cf-workers', transactionEvent => {
84-
return transactionEvent.transaction === 'GET /endpoint-error/api';
78+
const apiSpanPromise = waitForStreamedSpan('astro-6-cf-workers', span => {
79+
return getSpanOp(span) === 'http.server' && span.name === 'GET /endpoint-error/api';
8580
});
86-
const transactionEventEndpointPromise = waitForTransaction('astro-6-cf-workers', transactionEvent => {
87-
return transactionEvent.transaction === 'GET /endpoint-error';
81+
const endpointSpanPromise = waitForStreamedSpan('astro-6-cf-workers', span => {
82+
return getSpanOp(span) === 'http.server' && span.is_segment && span.name === 'GET /endpoint-error';
8883
});
8984

9085
await page.goto('/endpoint-error');
9186
await page.getByText('Get Data').click();
9287

9388
const errorEvent = await errorEventPromise;
94-
const transactionEventApi = await transactionEventApiPromise;
95-
const transactionEventEndpoint = await transactionEventEndpointPromise;
96-
97-
expect(transactionEventEndpoint).toMatchObject({
98-
transaction: 'GET /endpoint-error',
99-
spans: [],
100-
});
89+
const apiSpan = await apiSpanPromise;
90+
const endpointSpan = await endpointSpanPromise;
10191

102-
const traceId = transactionEventEndpoint.contexts?.trace?.trace_id;
103-
const endpointSpanId = transactionEventApi.contexts?.trace?.span_id;
92+
const traceId = endpointSpan.trace_id;
93+
const endpointSpanId = apiSpan.span_id;
10494

10595
expect(traceId).toMatch(/[a-f0-9]{32}/);
10696
expect(endpointSpanId).toMatch(/[a-f0-9]{16}/);
10797

108-
expect(transactionEventApi).toMatchObject({
109-
transaction: 'GET /endpoint-error/api',
110-
spans: [],
111-
});
112-
113-
const spanId = transactionEventApi.contexts?.trace?.span_id;
114-
const parentSpanId = transactionEventApi.contexts?.trace?.parent_span_id;
98+
const spanId = apiSpan.span_id;
99+
const parentSpanId = apiSpan.parent_span_id;
115100

116101
expect(spanId).toMatch(/[a-f0-9]{16}/);
117102
// TODO: This is incorrect, for whatever reason, it should be the endpointSpanId ideally

0 commit comments

Comments
 (0)