|
1 | 1 | 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 | + ); |
10 | 11 |
|
11 | | - const transactionEvent = await transactionEventPromise; |
| 12 | + await fetch(`${baseURL}/${route}`); |
12 | 13 |
|
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 | + }); |
14 | 18 | }); |
15 | 19 |
|
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 | + ); |
23 | 27 |
|
24 | 28 | await fetch(`${baseURL}/test-transaction`); |
25 | 29 |
|
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 }); |
36 | 36 | }); |
37 | 37 |
|
38 | 38 | 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'), |
84 | 45 | ); |
85 | 46 |
|
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`); |
100 | 48 |
|
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 | + } |
102 | 65 | }); |
0 commit comments