@@ -39,6 +39,9 @@ import org.robolectric.annotation.Config
3939@Config(sdk = [30 ])
4040class SentryNavEffectTest {
4141
42+ private val defaultNameExtractor =
43+ RouteNameExtractor <Any > { entry -> entry::class .simpleName ? : " unknown" }
44+
4245 @get:Rule(order = 1 )
4346 val addActivityToRobolectricRule =
4447 object : TestWatcher () {
@@ -104,7 +107,12 @@ class SentryNavEffectTest {
104107 val backStack = mutableStateListOf<Any >(HomeRoute ())
105108
106109 composeRule.setContent {
107- SentryNavEffect (backStack = backStack, scopes = fixture.scopes)
110+ SentryNavEffect (
111+ backStack = backStack,
112+ nameExtractor = defaultNameExtractor,
113+ options = SentryNavOptions (),
114+ scopes = fixture.scopes,
115+ )
108116 }
109117
110118 composeRule.waitForIdle()
@@ -122,7 +130,12 @@ class SentryNavEffectTest {
122130 val backStack = mutableStateListOf<Any >(HomeRoute ())
123131
124132 composeRule.setContent {
125- SentryNavEffect (backStack = backStack, scopes = fixture.scopes)
133+ SentryNavEffect (
134+ backStack = backStack,
135+ nameExtractor = defaultNameExtractor,
136+ options = SentryNavOptions (),
137+ scopes = fixture.scopes,
138+ )
126139 }
127140 composeRule.waitForIdle()
128141
@@ -144,7 +157,12 @@ class SentryNavEffectTest {
144157 val backStack = mutableStateListOf(HomeRoute (), ProfileRoute (" 123" ))
145158
146159 composeRule.setContent {
147- SentryNavEffect (backStack = backStack, scopes = fixture.scopes)
160+ SentryNavEffect (
161+ backStack = backStack,
162+ nameExtractor = defaultNameExtractor,
163+ options = SentryNavOptions (),
164+ scopes = fixture.scopes,
165+ )
148166 }
149167 composeRule.waitForIdle()
150168
@@ -166,7 +184,12 @@ class SentryNavEffectTest {
166184 val backStack = mutableStateListOf(HomeRoute (), ProfileRoute (" 123" ))
167185
168186 composeRule.setContent {
169- SentryNavEffect (backStack = backStack, scopes = fixture.scopes)
187+ SentryNavEffect (
188+ backStack = backStack,
189+ nameExtractor = defaultNameExtractor,
190+ options = SentryNavOptions (),
191+ scopes = fixture.scopes,
192+ )
170193 }
171194 composeRule.waitForIdle()
172195
@@ -194,7 +217,12 @@ class SentryNavEffectTest {
194217 val backStack = mutableStateListOf<Any >(home, profile)
195218
196219 composeRule.setContent {
197- SentryNavEffect (backStack = backStack, scopes = fixture.scopes)
220+ SentryNavEffect (
221+ backStack = backStack,
222+ nameExtractor = defaultNameExtractor,
223+ options = SentryNavOptions (),
224+ scopes = fixture.scopes,
225+ )
198226 }
199227 composeRule.waitForIdle()
200228
@@ -216,6 +244,27 @@ class SentryNavEffectTest {
216244 )
217245 }
218246
247+ @Test
248+ fun `changing back stack with capture limit of 0 still emits top-entry Sentry data but not back stack copy` () {
249+ val fixture = Fixture ()
250+ val backStack = mutableStateListOf(HomeRoute (), ProfileRoute (" 123" ))
251+
252+ composeRule.setContent {
253+ SentryNavEffect (
254+ backStack = backStack,
255+ nameExtractor = defaultNameExtractor,
256+ options = SentryNavOptions { maxCapturedBackStackEntries = 0 },
257+ scopes = fixture.scopes,
258+ )
259+ }
260+ composeRule.waitForIdle()
261+
262+ assertThat(fixture.breadcrumbs.single().data[" to" ]).isEqualTo(" /ProfileRoute" )
263+ assertThat(fixture.transactions.single().name).isEqualTo(" /ProfileRoute" )
264+ assertThat(fixture.scope.screen).isEqualTo(" /ProfileRoute" )
265+ assertThat(fixture.scope.contexts.containsKey(NAVIGATION_CONTEXT_KEY )).isFalse()
266+ }
267+
219268 @Test
220269 fun `unrelated recomposition does not re-emit Sentry data` () {
221270 val fixture = Fixture ()
@@ -224,7 +273,12 @@ class SentryNavEffectTest {
224273
225274 composeRule.setContent {
226275 recomposeTick.intValue
227- SentryNavEffect (backStack = backStack, scopes = fixture.scopes)
276+ SentryNavEffect (
277+ backStack = backStack,
278+ nameExtractor = defaultNameExtractor,
279+ options = SentryNavOptions (),
280+ scopes = fixture.scopes,
281+ )
228282 }
229283 composeRule.waitForIdle()
230284
@@ -255,7 +309,12 @@ class SentryNavEffectTest {
255309 val observedTransactionNames = mutableListOf<String >()
256310
257311 composeRule.setContent {
258- SentryNavEffect (backStack = backStack, scopes = fixture.scopes)
312+ SentryNavEffect (
313+ backStack = backStack,
314+ nameExtractor = defaultNameExtractor,
315+ options = SentryNavOptions (),
316+ scopes = fixture.scopes,
317+ )
259318
260319 val currentTop = backStack.last()
261320 LaunchedEffect (currentTop) {
@@ -275,19 +334,23 @@ class SentryNavEffectTest {
275334 fun `updated name extractor is used for later navigation changes` () {
276335 val fixture = Fixture ()
277336 val backStack = mutableStateListOf<Any >(HomeRoute ())
278- val nameExtractor = mutableStateOf< ((Any ) -> String )? > (null )
337+ val nameExtractor =
338+ mutableStateOf<RouteNameExtractor <Any >>(
339+ RouteNameExtractor { entry -> entry::class .simpleName ? : " unknown" }
340+ )
279341
280342 composeRule.setContent {
281343 SentryNavEffect (
282344 backStack = backStack,
283- scopes = fixture.scopes,
284345 nameExtractor = nameExtractor.value,
346+ options = SentryNavOptions (),
347+ scopes = fixture.scopes,
285348 )
286349 }
287350 composeRule.waitForIdle()
288351
289352 composeRule.runOnIdle {
290- nameExtractor.value = { entry ->
353+ nameExtractor.value = RouteNameExtractor { entry ->
291354 if (entry is ProfileRoute ) " profile-updated" else " home-updated"
292355 }
293356 }
@@ -306,19 +369,23 @@ class SentryNavEffectTest {
306369 fun `changing the name extractor alone does not re-emit Sentry data for the current top entry` () {
307370 val fixture = Fixture ()
308371 val backStack = mutableStateListOf<Any >(HomeRoute (), ProfileRoute (" 123" ))
309- val nameExtractor = mutableStateOf< ((Any ) -> String )? > (null )
372+ val nameExtractor =
373+ mutableStateOf<RouteNameExtractor <Any >>(
374+ RouteNameExtractor { entry -> entry::class .simpleName ? : " unknown" }
375+ )
310376
311377 composeRule.setContent {
312378 SentryNavEffect (
313379 backStack = backStack,
314- scopes = fixture.scopes,
315380 nameExtractor = nameExtractor.value,
381+ options = SentryNavOptions (),
382+ scopes = fixture.scopes,
316383 )
317384 }
318385 composeRule.waitForIdle()
319386
320387 composeRule.runOnIdle {
321- nameExtractor.value = { entry ->
388+ nameExtractor.value = RouteNameExtractor { entry ->
322389 if (entry is ProfileRoute ) " profile-updated" else " home-updated"
323390 }
324391 }
@@ -337,19 +404,21 @@ class SentryNavEffectTest {
337404 fun `updated arguments extractor is used for later navigation changes` () {
338405 val fixture = Fixture ()
339406 val backStack = mutableStateListOf<Any >(HomeRoute ())
340- val argumentsExtractor = mutableStateOf< (( Any ) -> Map < String , Any ?>) ? > (null )
407+ val argumentsExtractor = mutableStateOf<RouteArgumentsExtractor < Any > ? > (null )
341408
342409 composeRule.setContent {
343410 SentryNavEffect (
344411 backStack = backStack,
345- scopes = fixture.scopes ,
412+ nameExtractor = defaultNameExtractor ,
346413 argumentsExtractor = argumentsExtractor.value,
414+ options = SentryNavOptions (),
415+ scopes = fixture.scopes,
347416 )
348417 }
349418 composeRule.waitForIdle()
350419
351420 composeRule.runOnIdle {
352- argumentsExtractor.value = { entry ->
421+ argumentsExtractor.value = RouteArgumentsExtractor { entry ->
353422 if (entry is ProfileRoute ) mapOf (" userId" to entry.userId) else emptyMap()
354423 }
355424 }
@@ -375,19 +444,21 @@ class SentryNavEffectTest {
375444 fun `changing the arguments extractor alone does not re-emit Sentry data for the current top entry` () {
376445 val fixture = Fixture ()
377446 val backStack = mutableStateListOf<Any >(HomeRoute (), ProfileRoute (" 123" ))
378- val argumentsExtractor = mutableStateOf< (( Any ) -> Map < String , Any ?>) ? > (null )
447+ val argumentsExtractor = mutableStateOf<RouteArgumentsExtractor < Any > ? > (null )
379448
380449 composeRule.setContent {
381450 SentryNavEffect (
382451 backStack = backStack,
383- scopes = fixture.scopes ,
452+ nameExtractor = defaultNameExtractor ,
384453 argumentsExtractor = argumentsExtractor.value,
454+ options = SentryNavOptions (),
455+ scopes = fixture.scopes,
385456 )
386457 }
387458 composeRule.waitForIdle()
388459
389460 composeRule.runOnIdle {
390- argumentsExtractor.value = { entry ->
461+ argumentsExtractor.value = RouteArgumentsExtractor { entry ->
391462 if (entry is ProfileRoute ) mapOf (" userId" to entry.userId) else emptyMap()
392463 }
393464 }
@@ -408,16 +479,29 @@ class SentryNavEffectTest {
408479 fun `changing options applies the new observer configuration` () {
409480 val fixture = Fixture ()
410481 val backStack = mutableStateListOf<Any >(HomeRoute ())
411- val options = mutableStateOf(SentryNavOptions ( captureBackStack = true ) )
482+ val options = mutableStateOf(SentryNavOptions { captureBackStack = true } )
412483
413484 composeRule.setContent {
414- SentryNavEffect (backStack = backStack, scopes = fixture.scopes, options = options.value)
485+ SentryNavEffect (
486+ backStack = backStack,
487+ options = options.value,
488+ nameExtractor = defaultNameExtractor,
489+ scopes = fixture.scopes,
490+ )
415491 }
416492 composeRule.waitForIdle()
417493
418- composeRule.runOnIdle { options.value = SentryNavOptions (captureBackStack = false ) }
494+ val originalTransaction = composeRule.runOnIdle { fixture.transactions.single() }
495+
496+ composeRule.runOnIdle { options.value = SentryNavOptions { captureBackStack = false } }
419497 composeRule.waitForIdle()
420498
499+ assertThat(originalTransaction.isFinished).isTrue()
500+ assertThat(fixture.transactions).hasSize(2 )
501+ assertThat(fixture.transactions.last().name).isEqualTo(" /HomeRoute" )
502+ assertThat(fixture.transactions.last().isFinished).isFalse()
503+ assertThat(fixture.scope.transaction).isSameInstanceAs(fixture.transactions.last())
504+ assertThat(fixture.scope.screen).isEqualTo(" /HomeRoute" )
421505 assertThat(fixture.scope.contexts.containsKey(" navigation" )).isFalse()
422506 }
423507
@@ -429,7 +513,11 @@ class SentryNavEffectTest {
429513
430514 composeRule.setContent {
431515 if (isShown.value) {
432- SentryNavEffect (backStack = backStack, scopes = fixture.scopes)
516+ SentryNavEffect (
517+ backStack = backStack,
518+ nameExtractor = defaultNameExtractor,
519+ scopes = fixture.scopes,
520+ )
433521 }
434522 }
435523 composeRule.waitForIdle()
0 commit comments