@@ -7,14 +7,17 @@ import {
77 SPAN_STATUS_UNSET ,
88 SentrySpan ,
99 TRACEPARENT_REGEXP ,
10+ convertSpanLinksForEnvelope ,
1011 setCurrentClient ,
1112 spanToTraceHeader ,
1213 startInactiveSpan ,
1314 startSpan ,
1415 timestampInSeconds ,
1516} from '../../../src' ;
1617import type { Span , SpanAttributes , SpanStatus , SpanTimeInput } from '../../../src/types-hoist' ;
18+ import type { SpanLink } from '../../../src/types-hoist/link' ;
1719import type { OpenTelemetrySdkTraceBaseSpan } from '../../../src/utils/spanUtils' ;
20+ import { TRACE_FLAG_NONE , TRACE_FLAG_SAMPLED } from '../../../src/utils/spanUtils' ;
1821import {
1922 getRootSpan ,
2023 spanIsSampled ,
@@ -156,6 +159,115 @@ describe('spanToTraceContext', () => {
156159 } ) ;
157160} ) ;
158161
162+ describe ( 'convertSpanLinksForEnvelope' , ( ) => {
163+ it ( 'returns undefined for undefined input' , ( ) => {
164+ expect ( convertSpanLinksForEnvelope ( undefined ) ) . toBeUndefined ( ) ;
165+ } ) ;
166+
167+ it ( 'returns undefined for empty array input' , ( ) => {
168+ expect ( convertSpanLinksForEnvelope ( [ ] ) ) . toBeUndefined ( ) ;
169+ } ) ;
170+
171+ it ( 'converts a single span link to a flattened envelope item' , ( ) => {
172+ const links : SpanLink [ ] = [
173+ {
174+ context : {
175+ spanId : 'span1' ,
176+ traceId : 'trace1' ,
177+ traceFlags : TRACE_FLAG_SAMPLED ,
178+ } ,
179+ attributes : {
180+ 'sentry.link.type' : 'previous_trace' ,
181+ } ,
182+ } ,
183+ ] ;
184+
185+ const result = convertSpanLinksForEnvelope ( links ) ;
186+
187+ result ?. forEach ( item => expect ( item ) . not . toHaveProperty ( 'context' ) ) ;
188+ expect ( result ) . toEqual ( [
189+ {
190+ span_id : 'span1' ,
191+ trace_id : 'trace1' ,
192+ sampled : true ,
193+ attributes : {
194+ 'sentry.link.type' : 'previous_trace' ,
195+ } ,
196+ } ,
197+ ] ) ;
198+ } ) ;
199+
200+ it ( 'converts multiple span links to a flattened envelope item' , ( ) => {
201+ const links : SpanLink [ ] = [
202+ {
203+ context : {
204+ spanId : 'span1' ,
205+ traceId : 'trace1' ,
206+ traceFlags : TRACE_FLAG_SAMPLED ,
207+ } ,
208+ attributes : {
209+ 'sentry.link.type' : 'previous_trace' ,
210+ } ,
211+ } ,
212+ {
213+ context : {
214+ spanId : 'span2' ,
215+ traceId : 'trace2' ,
216+ traceFlags : TRACE_FLAG_NONE ,
217+ } ,
218+ attributes : {
219+ 'sentry.link.type' : 'another_trace' ,
220+ } ,
221+ } ,
222+ ] ;
223+
224+ const result = convertSpanLinksForEnvelope ( links ) ;
225+
226+ result ?. forEach ( item => expect ( item ) . not . toHaveProperty ( 'context' ) ) ;
227+ expect ( result ) . toEqual ( [
228+ {
229+ span_id : 'span1' ,
230+ trace_id : 'trace1' ,
231+ sampled : true ,
232+ attributes : {
233+ 'sentry.link.type' : 'previous_trace' ,
234+ } ,
235+ } ,
236+ {
237+ span_id : 'span2' ,
238+ trace_id : 'trace2' ,
239+ sampled : false ,
240+ attributes : {
241+ 'sentry.link.type' : 'another_trace' ,
242+ } ,
243+ } ,
244+ ] ) ;
245+ } ) ;
246+
247+ it ( 'handles span links without attributes' , ( ) => {
248+ const links : SpanLink [ ] = [
249+ {
250+ context : {
251+ spanId : 'span1' ,
252+ traceId : 'trace1' ,
253+ traceFlags : TRACE_FLAG_SAMPLED ,
254+ } ,
255+ } ,
256+ ] ;
257+
258+ const result = convertSpanLinksForEnvelope ( links ) ;
259+
260+ result ?. forEach ( item => expect ( item ) . not . toHaveProperty ( 'context' ) ) ;
261+ expect ( result ) . toEqual ( [
262+ {
263+ span_id : 'span1' ,
264+ trace_id : 'trace1' ,
265+ sampled : true ,
266+ } ,
267+ ] ) ;
268+ } ) ;
269+ } ) ;
270+
159271describe ( 'spanTimeInputToSeconds' , ( ) => {
160272 it ( 'works with undefined' , ( ) => {
161273 const now = timestampInSeconds ( ) ;
0 commit comments