11import pytest
22from django .urls import reverse
33
4- from sentry .testutils .cases import SnubaTestCase , SpanTestCase
4+ from sentry .api .endpoints .organization_insights_tree import OrganizationInsightsTreeEndpoint
5+ from sentry .testutils .cases import SnubaTestCase , SpanTestCase , TestCase
56from sentry .testutils .helpers .datetime import before_now
67from sentry .testutils .skips import requires_snuba
78from tests .snuba .api .endpoints .test_organization_events import OrganizationEventsEndpointTestBase
@@ -30,6 +31,7 @@ def setUp(self) -> None:
3031 self ._store_unrelated_spans ()
3132
3233 def _store_nextjs_function_spans (self ) -> None :
34+ # Old SDK format (<10.32.0): '{ComponentType} Server Component ({route})'
3335 descriptions = [
3436 "Page Server Component (/app/dashboard/)" ,
3537 "Loading Server Component (/app/dashboard/)" ,
@@ -50,6 +52,13 @@ def _store_nextjs_function_spans(self) -> None:
5052 "Page Server Component (/app/[id]/)" ,
5153 "Page Server Component (/app/[...slug]/)" ,
5254 "Page Server Component (/app/[[...optional]]/)" ,
55+ # New SDK format (>=10.32.0): 'resolve {type} server component "{route_or_segment}"'
56+ 'resolve page server component "/dashboard"' ,
57+ 'resolve page server component "/nested-layout/[dynamic]"' ,
58+ 'resolve layout server component "nested-layout"' ,
59+ 'resolve layout server component "(route-group)"' ,
60+ 'resolve layout server component "[dynamic]"' ,
61+ "resolve root layout server component" ,
5362 "unrelated description" ,
5463 ]
5564 spans = []
@@ -125,4 +134,61 @@ def test_get_nextjs_function_data(self) -> None:
125134 assert element ["function.nextjs.component_type" ] == "Page Server Component"
126135 assert element ["function.nextjs.path" ] == ["app" , "[...slug]" ]
127136
137+ # New SDK format: resolve page server component with full route
138+ resolve_page_idx = span_descriptions .index (
139+ 'resolve page server component "/nested-layout/[dynamic]"'
140+ )
141+ element = response .data ["data" ][resolve_page_idx ]
142+ assert element ["function.nextjs.component_type" ] == "Page Server Component"
143+ assert element ["function.nextjs.path" ] == ["nested-layout" , "[dynamic]" ]
144+
145+ # New SDK format: resolve layout server component with segment
146+ resolve_layout_idx = span_descriptions .index (
147+ 'resolve layout server component "nested-layout"'
148+ )
149+ element = response .data ["data" ][resolve_layout_idx ]
150+ assert element ["function.nextjs.component_type" ] == "Layout Server Component"
151+ assert element ["function.nextjs.path" ] == ["nested-layout" ]
152+
153+ # New SDK format: resolve root layout server component (no path)
154+ resolve_root_idx = span_descriptions .index ("resolve root layout server component" )
155+ element = response .data ["data" ][resolve_root_idx ]
156+ assert element ["function.nextjs.component_type" ] == "Layout Server Component"
157+ assert element ["function.nextjs.path" ] == []
158+
159+ # New SDK format: route group segment
160+ resolve_group_idx = span_descriptions .index (
161+ 'resolve layout server component "(route-group)"'
162+ )
163+ element = response .data ["data" ][resolve_group_idx ]
164+ assert element ["function.nextjs.component_type" ] == "Layout Server Component"
165+ assert element ["function.nextjs.path" ] == ["(route-group)" ]
166+
128167 assert "INSERT value INTO table" not in span_descriptions
168+
169+
170+ class DescriptionParsingTest (TestCase ):
171+ """Verifies that old (<10.32.0) and new (>=10.32.0) SDK formats produce identical parsed output."""
172+
173+ _endpoint = OrganizationInsightsTreeEndpoint ()
174+
175+ def _parse (self , desc ):
176+ response = type ("R" , (), {"data" : {"data" : [{"span.description" : desc }]}})()
177+ self ._endpoint ._separate_span_description_info (response )
178+ row = response .data ["data" ][0 ]
179+ return row ["function.nextjs.component_type" ], row ["function.nextjs.path" ]
180+
181+ def test_page_simple_route (self ):
182+ assert self ._parse ("Page Server Component (/dashboard)" ) == self ._parse (
183+ 'resolve page server component "/dashboard"'
184+ )
185+
186+ def test_page_nested_route (self ):
187+ assert self ._parse ("Page Server Component (/nested/route)" ) == self ._parse (
188+ 'resolve page server component "/nested/route"'
189+ )
190+
191+ def test_layout_simple_route (self ):
192+ assert self ._parse ("Layout Server Component (/settings)" ) == self ._parse (
193+ 'resolve layout server component "/settings"'
194+ )
0 commit comments