@@ -91,6 +91,11 @@ const {
9191 RUNTIME_VERSION ,
9292} = require ( '../../dd-trace/src/plugins/util/env' )
9393const { DD_MAJOR } = require ( '../../../version' )
94+ const {
95+ resolveOriginalSourcePosition,
96+ resolveSourceLineForTest,
97+ shouldTrustInvocationDetailsLine,
98+ } = require ( './source-map-utils' )
9499
95100const TEST_FRAMEWORK_NAME = 'cypress'
96101
@@ -238,7 +243,6 @@ class CypressPlugin {
238243
239244 finishedTestsByFile = { }
240245 testStatuses = { }
241-
242246 isTestsSkipped = false
243247 isSuitesSkippingEnabled = false
244248 isCodeCoverageEnabled = false
@@ -391,7 +395,9 @@ class CypressPlugin {
391395 this . ciVisEvent ( TELEMETRY_EVENT_CREATED , 'suite' )
392396
393397 if ( testSuiteAbsolutePath ) {
394- const testSourceFile = getTestSuitePath ( testSuiteAbsolutePath , this . repositoryRoot )
398+ const resolvedSuitePosition = resolveOriginalSourcePosition ( testSuiteAbsolutePath , 1 )
399+ const resolvedSuiteAbsolutePath = resolvedSuitePosition ? resolvedSuitePosition . sourceFile : testSuiteAbsolutePath
400+ const testSourceFile = getTestSuitePath ( resolvedSuiteAbsolutePath , this . repositoryRoot )
395401 testSuiteSpanMetadata [ TEST_SOURCE_FILE ] = testSourceFile
396402 testSuiteSpanMetadata [ TEST_SOURCE_START ] = 1
397403 const codeOwners = this . getTestCodeOwners ( { testSuite, testSourceFile } )
@@ -804,8 +810,10 @@ class CypressPlugin {
804810 if ( this . itrCorrelationId ) {
805811 finishedTest . testSpan . setTag ( ITR_CORRELATION_ID , this . itrCorrelationId )
806812 }
807- const testSourceFile = spec . absolute && this . repositoryRoot
808- ? getTestSuitePath ( spec . absolute , this . repositoryRoot )
813+ const resolvedSpecPosition = spec . absolute ? resolveOriginalSourcePosition ( spec . absolute , 1 ) : null
814+ const resolvedSpecAbsolutePath = resolvedSpecPosition ? resolvedSpecPosition . sourceFile : spec . absolute
815+ const testSourceFile = resolvedSpecAbsolutePath && this . repositoryRoot
816+ ? getTestSuitePath ( resolvedSpecAbsolutePath , this . repositoryRoot )
809817 : spec . relative
810818 if ( testSourceFile ) {
811819 finishedTest . testSpan . setTag ( TEST_SOURCE_FILE , testSourceFile )
@@ -902,9 +910,11 @@ class CypressPlugin {
902910 error,
903911 isRUMActive,
904912 testSourceLine,
913+ testSourceStack,
905914 testSuite,
906915 testSuiteAbsolutePath,
907916 testName,
917+ testItTitle,
908918 isNew,
909919 isEfdRetry,
910920 isAttemptToFix,
@@ -946,8 +956,29 @@ class CypressPlugin {
946956 if ( isRUMActive ) {
947957 this . activeTestSpan . setTag ( TEST_IS_RUM_ACTIVE , 'true' )
948958 }
959+ // Source-line resolution strategy:
960+ // 1. If plain JS and no source map, trust invocationDetails.line directly.
961+ // 2. Otherwise, try invocationDetails.stack line mapped through source map.
962+ // 3. If that fails, scan generated file for it/test/specify declaration by test name.
963+ // 4. If declaration found:
964+ // - .ts file: use declaration line directly.
965+ // - .js file: map declaration line through source map.
966+ // 5. If all fail, keep original invocationDetails.line.
949967 if ( testSourceLine ) {
950- this . activeTestSpan . setTag ( TEST_SOURCE_START , testSourceLine )
968+ let resolvedLine = testSourceLine
969+ if ( testSuiteAbsolutePath && testItTitle ) {
970+ // Use invocationDetails directly only for plain JS specs without source maps.
971+ // Otherwise, resolve from the test declaration in the spec and map via source map.
972+ const shouldTrustInvocationDetails = shouldTrustInvocationDetailsLine ( testSuiteAbsolutePath , testSourceLine )
973+ if ( ! shouldTrustInvocationDetails ) {
974+ resolvedLine = resolveSourceLineForTest (
975+ testSuiteAbsolutePath ,
976+ testItTitle ,
977+ testSourceStack
978+ ) ?? testSourceLine
979+ }
980+ }
981+ this . activeTestSpan . setTag ( TEST_SOURCE_START , resolvedLine )
951982 }
952983 if ( isNew ) {
953984 this . activeTestSpan . setTag ( TEST_IS_NEW , 'true' )
0 commit comments