@@ -405,7 +405,61 @@ class SentryANRTrackingIntegrationTests: SentrySDKIntegrationTestsBase {
405405 XCTAssertEqual ( scope? . breadcrumbs ( ) . count, 0 )
406406 }
407407 }
408-
408+
409+ func testV2Detected_PauseCalled_ANRStopped_DoesCaptureEvent( ) throws {
410+ // Arrange
411+ givenInitializedTracker ( enableV2: true )
412+ setUpThreadInspector ( )
413+ Dynamic ( sut) . anrDetectedWithType ( SentryANRType . fullyBlocking)
414+
415+ sut. pauseAppHangTracking ( )
416+
417+ // Act
418+ let result = SentryANRStoppedResult ( minDuration: 1.851 , maxDuration: 2.249 )
419+ Dynamic ( sut) . anrStoppedWithResult ( result)
420+
421+ // Assert
422+ try assertEventWithScopeCaptured { event, scope, _ in
423+ let ex = try XCTUnwrap ( event? . exceptions? . first)
424+ XCTAssertEqual ( ex. mechanism? . type, " AppHang " )
425+ XCTAssertEqual ( ex. type, " App Hang Fully Blocked " )
426+ XCTAssertEqual ( ex. value, " App hanging between 1.9 and 2.2 seconds. " )
427+
428+ // We use the mechanism data to temporarily store the duration.
429+ // This asserts that we remove the mechanism data before sending the event.
430+ let mechanismData = try XCTUnwrap ( ex. mechanism? . data)
431+ XCTAssertTrue ( mechanismData. isEmpty)
432+
433+ XCTAssertNotNil ( ex. stacktrace)
434+ XCTAssertEqual ( ex. stacktrace? . frames. first? . function, " main " )
435+ XCTAssertEqual ( ex. stacktrace? . snapshot? . boolValue, true )
436+ XCTAssertEqual ( try XCTUnwrap ( event? . threads? . first) . current? . boolValue, true )
437+ XCTAssertEqual ( event? . isAppHangEvent, true )
438+
439+ let threads = try XCTUnwrap ( event? . threads)
440+
441+ // Sometimes during tests its possible to have one thread without frames
442+ // We just need to make sure we retrieve frame information for at least one other thread than the main thread
443+ let threadsWithFrames = threads. filter {
444+ ( $0. stacktrace? . frames. count ?? 0 ) >= 1
445+ } . count
446+
447+ XCTAssertTrue ( threadsWithFrames > 1 , " Not enough threads with frames " )
448+
449+ let tags = try XCTUnwrap ( event? . tags)
450+ XCTAssertEqual ( 1 , tags. count)
451+ XCTAssertEqual ( " value " , tags [ " key " ] )
452+
453+ let breadcrumbs = try XCTUnwrap ( event? . breadcrumbs)
454+ XCTAssertEqual ( 1 , breadcrumbs. count)
455+ XCTAssertEqual ( " crumb " , breadcrumbs. first? . message)
456+
457+ // Ensure we capture the event with an empty scope
458+ XCTAssertEqual ( scope? . tags. count, 0 )
459+ XCTAssertEqual ( scope? . breadcrumbs ( ) . count, 0 )
460+ }
461+ }
462+
409463 func testV2_ANRStopped_EmptyEventStored_DoesCaptureEvent( ) throws {
410464 // Arrange
411465 givenInitializedTracker ( enableV2: true )
@@ -459,7 +513,42 @@ class SentryANRTrackingIntegrationTests: SentrySDKIntegrationTestsBase {
459513 XCTAssertEqual ( " crumb " , breadcrumbs. first? . message)
460514 }
461515 }
462-
516+
517+ func testV2_ANRDetected_PauseCalledButStopNotCalled_SendsFatalANROnNextInstall( ) throws {
518+ // Arrange
519+ givenInitializedTracker ( enableV2: true )
520+ setUpThreadInspector ( )
521+ Dynamic ( sut) . anrDetectedWithType ( SentryANRType . nonFullyBlocking)
522+ sut. pauseAppHangTracking ( )
523+
524+ // Act
525+ givenInitializedTracker ( enableV2: true )
526+ sut. pauseAppHangTracking ( )
527+
528+ // Assert
529+ try assertCrashEventWithScope { event, _ in
530+ XCTAssertEqual ( event? . level, SentryLevel . fatal)
531+
532+ let ex = try XCTUnwrap ( event? . exceptions? . first)
533+
534+ XCTAssertEqual ( ex. type, " Fatal App Hang Non Fully Blocked " )
535+ XCTAssertEqual ( ex. value, " The user or the OS watchdog terminated your app while it blocked the main thread for at least 4500 ms. " )
536+
537+ // We use the mechanism data to temporarily store the duration.
538+ // This asserts that we remove the mechanism data before sending the event.
539+ let mechanismData = try XCTUnwrap ( ex. mechanism? . data)
540+ XCTAssertTrue ( mechanismData. isEmpty)
541+
542+ let tags = try XCTUnwrap ( event? . tags)
543+ XCTAssertEqual ( 1 , tags. count)
544+ XCTAssertEqual ( " value " , tags [ " key " ] )
545+
546+ let breadcrumbs = try XCTUnwrap ( event? . breadcrumbs)
547+ XCTAssertEqual ( 1 , breadcrumbs. count)
548+ XCTAssertEqual ( " crumb " , breadcrumbs. first? . message)
549+ }
550+ }
551+
463552 func testV2_ANRDetected_StopNotCalledAndAbnormalSession_SendsFatalAppHangOnNextInstall( ) throws {
464553 // Arrange
465554 givenInitializedTracker ( enableV2: true )
0 commit comments