Skip to content

Commit de04922

Browse files
msonnbcodex
andcommitted
test(e2e): Migrate Effect to span streaming
Co-Authored-By: GPT-6 <codex@openai.com>
1 parent 37118dd commit de04922

4 files changed

Lines changed: 100 additions & 176 deletions

File tree

‎dev-packages/e2e-tests/test-applications/effect-3-node/src/app.ts‎

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,6 @@ import { createServer } from 'http';
1010

1111
const SentryLive = Layer.mergeAll(
1212
Sentry.effectLayer({
13-
traceLifecycle: 'static',
1413
dsn: process.env.E2E_TEST_DSN,
1514
environment: 'qa',
1615
debug: !!process.env.DEBUG,
Lines changed: 50 additions & 87 deletions
Original file line numberDiff line numberDiff line change
@@ -1,102 +1,65 @@
11
import { expect, test } from '@playwright/test';
2-
import { waitForTransaction } from '@sentry-internal/test-utils';
3-
4-
test('Sends an HTTP transaction', async ({ baseURL }) => {
5-
const transactionEventPromise = waitForTransaction('effect-3-node', transactionEvent => {
6-
return transactionEvent?.transaction === 'http.server GET';
7-
});
8-
9-
await fetch(`${baseURL}/test-success`);
2+
import { collectStreamedSpans, getSpanOp, waitForStreamedSpan } from '@sentry-internal/test-utils';
3+
4+
['test-success', 'test-error'].forEach(route => {
5+
test(`Sends an HTTP segment for ${route}`, async ({ baseURL }) => {
6+
const spanPromise = waitForStreamedSpan(
7+
'effect-3-node',
8+
span =>
9+
span.is_segment && getSpanOp(span) === 'http.server' && span.attributes['url.path']?.value === `/${route}`,
10+
);
1011

11-
const transactionEvent = await transactionEventPromise;
12+
await fetch(`${baseURL}/${route}`);
1213

13-
expect(transactionEvent.transaction).toBe('http.server GET');
14+
const span = await spanPromise;
15+
expect(span.name).toBe('http.server GET');
16+
expect(span.attributes['sentry.origin']?.value).toBe('auto.http.effect');
17+
});
1418
});
1519

16-
test('Sends transaction with manual Effect span', async ({ baseURL }) => {
17-
const transactionEventPromise = waitForTransaction('effect-3-node', transactionEvent => {
18-
return (
19-
transactionEvent?.transaction === 'http.server GET' &&
20-
transactionEvent?.spans?.some(span => span.description === 'test-span')
21-
);
22-
});
20+
test('Sends a manual Effect span', async ({ baseURL }) => {
21+
const spansPromise = collectStreamedSpans(
22+
'effect-3-node',
23+
spans =>
24+
spans.some(span => span.is_segment && getSpanOp(span) === 'http.server') &&
25+
spans.some(span => span.name === 'test-span'),
26+
);
2327

2428
await fetch(`${baseURL}/test-transaction`);
2529

26-
const transactionEvent = await transactionEventPromise;
27-
28-
expect(transactionEvent.transaction).toBe('http.server GET');
29-
30-
const spans = transactionEvent.spans || [];
31-
expect(spans).toEqual([
32-
expect.objectContaining({
33-
description: 'test-span',
34-
}),
35-
]);
30+
const spans = await spansPromise;
31+
const segment = spans.find(span => span.is_segment)!;
32+
const children = spans.filter(span => !span.is_segment);
33+
expect(segment.name).toBe('http.server GET');
34+
expect(children).toHaveLength(1);
35+
expect(children[0]).toMatchObject({ name: 'test-span', parent_span_id: segment.span_id });
3636
});
3737

3838
test('Sends Effect spans with correct parent-child structure', async ({ baseURL }) => {
39-
const transactionEventPromise = waitForTransaction('effect-3-node', transactionEvent => {
40-
return (
41-
transactionEvent?.transaction === 'http.server GET' &&
42-
transactionEvent?.spans?.some(span => span.description === 'custom-effect-span')
43-
);
44-
});
45-
46-
await fetch(`${baseURL}/test-effect-span`);
47-
48-
const transactionEvent = await transactionEventPromise;
49-
50-
expect(transactionEvent.transaction).toBe('http.server GET');
51-
52-
expect(transactionEvent).toEqual(
53-
expect.objectContaining({
54-
contexts: expect.objectContaining({
55-
trace: expect.objectContaining({
56-
op: 'http.server',
57-
origin: 'auto.http.effect',
58-
}),
59-
}),
60-
spans: [
61-
expect.objectContaining({
62-
description: 'custom-effect-span',
63-
op: 'function',
64-
origin: 'auto.function.effect',
65-
}),
66-
expect.objectContaining({
67-
description: 'nested-span',
68-
op: 'function',
69-
origin: 'auto.function.effect',
70-
}),
71-
],
72-
sdk: expect.objectContaining({
73-
name: 'sentry.javascript.effect',
74-
packages: [
75-
expect.objectContaining({
76-
name: 'npm:@sentry/effect',
77-
}),
78-
expect.objectContaining({
79-
name: 'npm:@sentry/node',
80-
}),
81-
],
82-
}),
83-
}),
39+
const spansPromise = collectStreamedSpans(
40+
'effect-3-node',
41+
spans =>
42+
spans.some(span => span.is_segment && getSpanOp(span) === 'http.server') &&
43+
spans.some(span => span.name === 'custom-effect-span') &&
44+
spans.some(span => span.name === 'nested-span'),
8445
);
8546

86-
const parentSpan = transactionEvent.spans?.[0]?.span_id;
87-
const nestedSpan = transactionEvent.spans?.[1]?.parent_span_id;
88-
89-
expect(nestedSpan).toBe(parentSpan);
90-
});
91-
92-
test('Sends transaction for error route', async ({ baseURL }) => {
93-
const transactionEventPromise = waitForTransaction('effect-3-node', transactionEvent => {
94-
return transactionEvent?.transaction === 'http.server GET';
95-
});
96-
97-
await fetch(`${baseURL}/test-error`);
98-
99-
const transactionEvent = await transactionEventPromise;
47+
await fetch(`${baseURL}/test-effect-span`);
10048

101-
expect(transactionEvent.transaction).toBe('http.server GET');
49+
const spans = await spansPromise;
50+
const segment = spans.find(span => span.is_segment)!;
51+
const children = spans.filter(span => !span.is_segment);
52+
expect(segment.name).toBe('http.server GET');
53+
expect(segment.attributes['sentry.origin']?.value).toBe('auto.http.effect');
54+
expect(segment.attributes['sentry.sdk.name']?.value).toBe('sentry.javascript.effect');
55+
expect(children).toHaveLength(2);
56+
const parent = children.find(span => span.name === 'custom-effect-span')!;
57+
const nested = children.find(span => span.name === 'nested-span')!;
58+
expect(parent.parent_span_id).toBe(segment.span_id);
59+
expect(nested.parent_span_id).toBe(parent.span_id);
60+
for (const child of children) {
61+
expect(getSpanOp(child)).toBe('function');
62+
expect(child.attributes['sentry.origin']?.value).toBe('auto.function.effect');
63+
expect(child.trace_id).toBe(segment.trace_id);
64+
}
10265
});

‎dev-packages/e2e-tests/test-applications/effect-4-node/src/app.ts‎

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,6 @@ import { createServer } from 'http';
1111

1212
const SentryLive = Layer.mergeAll(
1313
Sentry.effectLayer({
14-
traceLifecycle: 'static',
1514
dsn: process.env.E2E_TEST_DSN,
1615
environment: 'qa',
1716
debug: !!process.env.DEBUG,
Lines changed: 50 additions & 87 deletions
Original file line numberDiff line numberDiff line change
@@ -1,102 +1,65 @@
11
import { expect, test } from '@playwright/test';
2-
import { waitForTransaction } from '@sentry-internal/test-utils';
3-
4-
test('Sends an HTTP transaction', async ({ baseURL }) => {
5-
const transactionEventPromise = waitForTransaction('effect-4-node', transactionEvent => {
6-
return transactionEvent?.transaction === 'http.server GET';
7-
});
8-
9-
await fetch(`${baseURL}/test-success`);
2+
import { collectStreamedSpans, getSpanOp, waitForStreamedSpan } from '@sentry-internal/test-utils';
3+
4+
['test-success', 'test-error'].forEach(route => {
5+
test(`Sends an HTTP segment for ${route}`, async ({ baseURL }) => {
6+
const spanPromise = waitForStreamedSpan(
7+
'effect-4-node',
8+
span =>
9+
span.is_segment && getSpanOp(span) === 'http.server' && span.attributes['url.path']?.value === `/${route}`,
10+
);
1011

11-
const transactionEvent = await transactionEventPromise;
12+
await fetch(`${baseURL}/${route}`);
1213

13-
expect(transactionEvent.transaction).toBe('http.server GET');
14+
const span = await spanPromise;
15+
expect(span.name).toBe('http.server GET');
16+
expect(span.attributes['sentry.origin']?.value).toBe('auto.http.effect');
17+
});
1418
});
1519

16-
test('Sends transaction with manual Effect span', async ({ baseURL }) => {
17-
const transactionEventPromise = waitForTransaction('effect-4-node', transactionEvent => {
18-
return (
19-
transactionEvent?.transaction === 'http.server GET' &&
20-
transactionEvent?.spans?.some(span => span.description === 'test-span')
21-
);
22-
});
20+
test('Sends a manual Effect span', async ({ baseURL }) => {
21+
const spansPromise = collectStreamedSpans(
22+
'effect-4-node',
23+
spans =>
24+
spans.some(span => span.is_segment && getSpanOp(span) === 'http.server') &&
25+
spans.some(span => span.name === 'test-span'),
26+
);
2327

2428
await fetch(`${baseURL}/test-transaction`);
2529

26-
const transactionEvent = await transactionEventPromise;
27-
28-
expect(transactionEvent.transaction).toBe('http.server GET');
29-
30-
const spans = transactionEvent.spans || [];
31-
expect(spans).toEqual([
32-
expect.objectContaining({
33-
description: 'test-span',
34-
}),
35-
]);
30+
const spans = await spansPromise;
31+
const segment = spans.find(span => span.is_segment)!;
32+
const children = spans.filter(span => !span.is_segment);
33+
expect(segment.name).toBe('http.server GET');
34+
expect(children).toHaveLength(1);
35+
expect(children[0]).toMatchObject({ name: 'test-span', parent_span_id: segment.span_id });
3636
});
3737

3838
test('Sends Effect spans with correct parent-child structure', async ({ baseURL }) => {
39-
const transactionEventPromise = waitForTransaction('effect-4-node', transactionEvent => {
40-
return (
41-
transactionEvent?.transaction === 'http.server GET' &&
42-
transactionEvent?.spans?.some(span => span.description === 'custom-effect-span')
43-
);
44-
});
45-
46-
await fetch(`${baseURL}/test-effect-span`);
47-
48-
const transactionEvent = await transactionEventPromise;
49-
50-
expect(transactionEvent.transaction).toBe('http.server GET');
51-
52-
expect(transactionEvent).toEqual(
53-
expect.objectContaining({
54-
contexts: expect.objectContaining({
55-
trace: expect.objectContaining({
56-
op: 'http.server',
57-
origin: 'auto.http.effect',
58-
}),
59-
}),
60-
spans: [
61-
expect.objectContaining({
62-
description: 'custom-effect-span',
63-
op: 'function',
64-
origin: 'auto.function.effect',
65-
}),
66-
expect.objectContaining({
67-
description: 'nested-span',
68-
op: 'function',
69-
origin: 'auto.function.effect',
70-
}),
71-
],
72-
sdk: expect.objectContaining({
73-
name: 'sentry.javascript.effect',
74-
packages: [
75-
expect.objectContaining({
76-
name: 'npm:@sentry/effect',
77-
}),
78-
expect.objectContaining({
79-
name: 'npm:@sentry/node',
80-
}),
81-
],
82-
}),
83-
}),
39+
const spansPromise = collectStreamedSpans(
40+
'effect-4-node',
41+
spans =>
42+
spans.some(span => span.is_segment && getSpanOp(span) === 'http.server') &&
43+
spans.some(span => span.name === 'custom-effect-span') &&
44+
spans.some(span => span.name === 'nested-span'),
8445
);
8546

86-
const parentSpan = transactionEvent.spans?.[0]?.span_id;
87-
const nestedSpan = transactionEvent.spans?.[1]?.parent_span_id;
88-
89-
expect(nestedSpan).toBe(parentSpan);
90-
});
91-
92-
test('Sends transaction for error route', async ({ baseURL }) => {
93-
const transactionEventPromise = waitForTransaction('effect-4-node', transactionEvent => {
94-
return transactionEvent?.transaction === 'http.server GET';
95-
});
96-
97-
await fetch(`${baseURL}/test-error`);
98-
99-
const transactionEvent = await transactionEventPromise;
47+
await fetch(`${baseURL}/test-effect-span`);
10048

101-
expect(transactionEvent.transaction).toBe('http.server GET');
49+
const spans = await spansPromise;
50+
const segment = spans.find(span => span.is_segment)!;
51+
const children = spans.filter(span => !span.is_segment);
52+
expect(segment.name).toBe('http.server GET');
53+
expect(segment.attributes['sentry.origin']?.value).toBe('auto.http.effect');
54+
expect(segment.attributes['sentry.sdk.name']?.value).toBe('sentry.javascript.effect');
55+
expect(children).toHaveLength(2);
56+
const parent = children.find(span => span.name === 'custom-effect-span')!;
57+
const nested = children.find(span => span.name === 'nested-span')!;
58+
expect(parent.parent_span_id).toBe(segment.span_id);
59+
expect(nested.parent_span_id).toBe(parent.span_id);
60+
for (const child of children) {
61+
expect(getSpanOp(child)).toBe('function');
62+
expect(child.attributes['sentry.origin']?.value).toBe('auto.function.effect');
63+
expect(child.trace_id).toBe(segment.trace_id);
64+
}
10265
});

0 commit comments

Comments
 (0)