@@ -32,7 +32,7 @@ import { mockAppRegistryIntegration } from '../mocks/appRegistryIntegrationMock'
3232import { getDefaultTestClientOptions , TestClient } from '../mocks/client' ;
3333import { NATIVE } from '../mockWrapper' ;
3434import { getDevServer } from './../../src/js/integrations/debugsymbolicatorutils' ;
35- import { createMockNavigationAndAttachTo } from './reactnavigationutils' ;
35+ import { createMockNavigationAndAttachTo , createMockNavigationWithNestedState } from './reactnavigationutils' ;
3636
3737const dummyRoute = {
3838 name : 'Route' ,
@@ -792,6 +792,218 @@ describe('ReactNavigationInstrumentation', () => {
792792 } ) ;
793793 } ) ;
794794
795+ describe ( 'useFullPathsForNavigationRoutes option' , ( ) => {
796+ test ( 'transaction uses full path when useFullPathsForNavigationRoutes is true' , async ( ) => {
797+ const rNavigation = reactNavigationIntegration ( {
798+ routeChangeTimeoutMs : 200 ,
799+ useFullPathsForNavigationRoutes : true ,
800+ } ) ;
801+
802+ const mockNavigationWithNestedState = createMockNavigationWithNestedState ( rNavigation ) ;
803+
804+ const options = getDefaultTestClientOptions ( {
805+ enableNativeFramesTracking : false ,
806+ enableStallTracking : false ,
807+ tracesSampleRate : 1.0 ,
808+ integrations : [ rNavigation , reactNativeTracingIntegration ( ) ] ,
809+ enableAppStartTracking : false ,
810+ } ) ;
811+
812+ client = new TestClient ( options ) ;
813+ setCurrentClient ( client ) ;
814+ client . init ( ) ;
815+
816+ jest . runOnlyPendingTimers ( ) ; // Flush the init transaction
817+
818+ // Navigate to a nested screen: Home -> Settings -> Profile
819+ mockNavigationWithNestedState . navigateToNestedScreen ( ) ;
820+ jest . runOnlyPendingTimers ( ) ;
821+
822+ await client . flush ( ) ;
823+
824+ const actualEvent = client . event ;
825+ expect ( actualEvent ) . toEqual (
826+ expect . objectContaining ( {
827+ contexts : expect . objectContaining ( {
828+ trace : expect . objectContaining ( {
829+ data : expect . objectContaining ( {
830+ [ SEMANTIC_ATTRIBUTE_ROUTE_NAME ] : 'Home/Settings/Profile' ,
831+ [ SEMANTIC_ATTRIBUTE_ROUTE_KEY ] : 'profile_screen' ,
832+ } ) ,
833+ } ) ,
834+ } ) ,
835+ } ) ,
836+ ) ;
837+ } ) ;
838+
839+ test ( 'transaction uses only route name when useFullPathsForNavigationRoutes is false' , async ( ) => {
840+ const rNavigation = reactNavigationIntegration ( {
841+ routeChangeTimeoutMs : 200 ,
842+ useFullPathsForNavigationRoutes : false ,
843+ } ) ;
844+
845+ const mockNavigationWithNestedState = createMockNavigationWithNestedState ( rNavigation ) ;
846+
847+ const options = getDefaultTestClientOptions ( {
848+ enableNativeFramesTracking : false ,
849+ enableStallTracking : false ,
850+ tracesSampleRate : 1.0 ,
851+ integrations : [ rNavigation , reactNativeTracingIntegration ( ) ] ,
852+ enableAppStartTracking : false ,
853+ } ) ;
854+
855+ client = new TestClient ( options ) ;
856+ setCurrentClient ( client ) ;
857+ client . init ( ) ;
858+
859+ jest . runOnlyPendingTimers ( ) ;
860+
861+ mockNavigationWithNestedState . navigateToNestedScreen ( ) ;
862+ jest . runOnlyPendingTimers ( ) ;
863+
864+ await client . flush ( ) ;
865+
866+ const actualEvent = client . event ;
867+ expect ( actualEvent ) . toEqual (
868+ expect . objectContaining ( {
869+ contexts : expect . objectContaining ( {
870+ trace : expect . objectContaining ( {
871+ data : expect . objectContaining ( {
872+ [ SEMANTIC_ATTRIBUTE_ROUTE_NAME ] : 'Profile' ,
873+ [ SEMANTIC_ATTRIBUTE_ROUTE_KEY ] : 'profile_screen' ,
874+ } ) ,
875+ } ) ,
876+ } ) ,
877+ } ) ,
878+ ) ;
879+ } ) ;
880+
881+ test ( 'transaction uses two-level path with nested tab navigator' , async ( ) => {
882+ const rNavigation = reactNavigationIntegration ( {
883+ routeChangeTimeoutMs : 200 ,
884+ useFullPathsForNavigationRoutes : true ,
885+ } ) ;
886+
887+ const mockNavigationWithNestedState = createMockNavigationWithNestedState ( rNavigation ) ;
888+
889+ const options = getDefaultTestClientOptions ( {
890+ enableNativeFramesTracking : false ,
891+ enableStallTracking : false ,
892+ tracesSampleRate : 1.0 ,
893+ integrations : [ rNavigation , reactNativeTracingIntegration ( ) ] ,
894+ enableAppStartTracking : false ,
895+ } ) ;
896+
897+ client = new TestClient ( options ) ;
898+ setCurrentClient ( client ) ;
899+ client . init ( ) ;
900+
901+ jest . runOnlyPendingTimers ( ) ;
902+
903+ mockNavigationWithNestedState . navigateToTwoLevelNested ( ) ;
904+ jest . runOnlyPendingTimers ( ) ;
905+
906+ await client . flush ( ) ;
907+
908+ const actualEvent = client . event ;
909+ expect ( actualEvent ) . toEqual (
910+ expect . objectContaining ( {
911+ contexts : expect . objectContaining ( {
912+ trace : expect . objectContaining ( {
913+ data : expect . objectContaining ( {
914+ [ SEMANTIC_ATTRIBUTE_ROUTE_NAME ] : 'Tabs/Settings' ,
915+ [ SEMANTIC_ATTRIBUTE_ROUTE_KEY ] : 'settings_screen' ,
916+ } ) ,
917+ } ) ,
918+ } ) ,
919+ } ) ,
920+ ) ;
921+ } ) ;
922+
923+ test ( 'setCurrentRoute receives full path when useFullPathsForNavigationRoutes is true' , async ( ) => {
924+ const mockSetCurrentRoute = jest . fn ( ) ;
925+ const rnTracingIntegration = reactNativeTracingIntegration ( ) ;
926+ rnTracingIntegration . setCurrentRoute = mockSetCurrentRoute ;
927+
928+ const rNavigation = reactNavigationIntegration ( {
929+ routeChangeTimeoutMs : 200 ,
930+ useFullPathsForNavigationRoutes : true ,
931+ } ) ;
932+
933+ const mockNavigationWithNestedState = createMockNavigationWithNestedState ( rNavigation ) ;
934+
935+ const options = getDefaultTestClientOptions ( {
936+ enableNativeFramesTracking : false ,
937+ enableStallTracking : false ,
938+ tracesSampleRate : 1.0 ,
939+ integrations : [ rNavigation , rnTracingIntegration ] ,
940+ enableAppStartTracking : false ,
941+ } ) ;
942+
943+ client = new TestClient ( options ) ;
944+ setCurrentClient ( client ) ;
945+ client . init ( ) ;
946+
947+ jest . runOnlyPendingTimers ( ) ;
948+
949+ mockSetCurrentRoute . mockClear ( ) ;
950+ mockNavigationWithNestedState . navigateToNestedScreen ( ) ;
951+ jest . runOnlyPendingTimers ( ) ;
952+
953+ expect ( mockSetCurrentRoute ) . toHaveBeenCalledWith ( 'Home/Settings/Profile' ) ;
954+ } ) ;
955+
956+ test ( 'previous route uses full path when useFullPathsForNavigationRoutes is true' , async ( ) => {
957+ const rNavigation = reactNavigationIntegration ( {
958+ routeChangeTimeoutMs : 200 ,
959+ useFullPathsForNavigationRoutes : true ,
960+ } ) ;
961+
962+ const mockNavigationWithNestedState = createMockNavigationWithNestedState ( rNavigation ) ;
963+
964+ const options = getDefaultTestClientOptions ( {
965+ enableNativeFramesTracking : false ,
966+ enableStallTracking : false ,
967+ tracesSampleRate : 1.0 ,
968+ integrations : [ rNavigation , reactNativeTracingIntegration ( ) ] ,
969+ enableAppStartTracking : false ,
970+ } ) ;
971+
972+ client = new TestClient ( options ) ;
973+ setCurrentClient ( client ) ;
974+ client . init ( ) ;
975+
976+ jest . runOnlyPendingTimers ( ) ; // Flush the init transaction
977+
978+ // First navigation
979+ mockNavigationWithNestedState . navigateToNestedScreen ( ) ;
980+ jest . runOnlyPendingTimers ( ) ;
981+
982+ await client . flush ( ) ;
983+
984+ // Second navigation
985+ mockNavigationWithNestedState . navigateToTwoLevelNested ( ) ;
986+ jest . runOnlyPendingTimers ( ) ;
987+
988+ await client . flush ( ) ;
989+
990+ const actualEvent = client . event ;
991+ expect ( actualEvent ) . toEqual (
992+ expect . objectContaining ( {
993+ contexts : expect . objectContaining ( {
994+ trace : expect . objectContaining ( {
995+ data : expect . objectContaining ( {
996+ [ SEMANTIC_ATTRIBUTE_ROUTE_NAME ] : 'Tabs/Settings' ,
997+ [ SEMANTIC_ATTRIBUTE_PREVIOUS_ROUTE_NAME ] : 'Home/Settings/Profile' , // Full path in previous route
998+ [ SEMANTIC_ATTRIBUTE_PREVIOUS_ROUTE_KEY ] : 'profile_screen' ,
999+ } ) ,
1000+ } ) ,
1001+ } ) ,
1002+ } ) ,
1003+ ) ;
1004+ } ) ;
1005+ } ) ;
1006+
7951007 function setupTestClient (
7961008 setupOptions : {
7971009 beforeSpanStart ?: ( options : StartSpanOptions ) => StartSpanOptions ;
0 commit comments