@@ -14,9 +14,10 @@ import React
1414internal class DdRumTests : XCTestCase {
1515 private let mockNativeRUM = MockRUMMonitor ( )
1616 private let mockUIManager = MockUIManager ( )
17+ private let mockRootView = MockRootView ( )
1718 private let mockHeatmapIdentifierRegistry = MockHeatmapIdentifierRegistry ( )
1819 private var rum : DdRumImplementation ! // swiftlint:disable:this implicitly_unwrapped_optional
19-
20+
2021 private func mockResolve( args: Any ? ) { }
2122 private func mockReject( args: String ? , arg: String ? , err: Error ? ) { }
2223
@@ -27,6 +28,7 @@ internal class DdRumTests: XCTestCase {
2728 rum = DdRumImplementation (
2829 mainDispatchQueue: DispatchQueueMock ( ) ,
2930 uiManager: self . mockUIManager,
31+ rootViewProvider: { self . mockRootView } ,
3032 heatmapIdentifierRegistryProvider: { self . mockHeatmapIdentifierRegistry } ,
3133 rumProvider: { self . mockNativeRUM } ,
3234 rumInternalProvider: { self . mockNativeRUM. _internalMock }
@@ -40,6 +42,7 @@ internal class DdRumTests: XCTestCase {
4042 let rum = DdRumImplementation (
4143 mainDispatchQueue: DispatchQueueMock ( ) ,
4244 uiManager: MockUIManager ( ) ,
45+ rootViewProvider: { nil } ,
4346 heatmapIdentifierRegistryProvider: { nil } ,
4447 rumProvider: { [ unowned self] in
4548 expectation. fulfill ( )
@@ -141,7 +144,9 @@ internal class DdRumTests: XCTestCase {
141144 let touch : NSDictionary = [
142145 " reactTag " : 42 ,
143146 " x " : 10.0 ,
144- " y " : 20.0
147+ " y " : 20.0 ,
148+ " pageX " : 100.0 ,
149+ " pageY " : 200.0
145150 ]
146151
147152 // When
@@ -172,13 +177,24 @@ internal class DdRumTests: XCTestCase {
172177 )
173178 }
174179
175- func testAddActionWithTouchAndUnknownReactTag( ) throws {
180+ func testAddActionFallsBackToHitTestWhenReactTagNotFound( ) throws {
181+ // Given
182+ let hitView = UIView ( frame: CGRect ( x: 50 , y: 100 , width: 200 , height: 50 ) )
183+ mockRootView. addSubview ( hitView)
184+ mockRootView. hitTestResult = hitView
185+
186+ let identifier = HeatmapIdentifier ( rawValue: " abc123 " )
187+ mockHeatmapIdentifierRegistry. identifiers [ ObjectIdentifier ( hitView) ] = identifier
188+
176189 let touch : NSDictionary = [
177190 " reactTag " : 999 ,
178191 " x " : 10.0 ,
179- " y " : 20.0
192+ " y " : 20.0 ,
193+ " pageX " : 130.0 ,
194+ " pageY " : 220.0
180195 ]
181-
196+
197+ // When
182198 rum. addAction (
183199 type: " tap " ,
184200 name: " tap action " ,
@@ -188,7 +204,49 @@ internal class DdRumTests: XCTestCase {
188204 resolve: mockResolve,
189205 reject: mockReject
190206 )
191-
207+
208+ // Then
209+ XCTAssertEqual ( mockNativeRUM. calledMethods. count, 1 )
210+ XCTAssertEqual ( mockRootView. receivedHitTestPoints, [ CGPoint ( x: 130 , y: 220 ) ] )
211+ XCTAssertEqual (
212+ mockNativeRUM. calledMethods. last,
213+ . addAction(
214+ time: Date ( timeIntervalSince1970: randomTimestamp / 1_000 ) ,
215+ type: . tap,
216+ name: " tap action " ,
217+ heatmapAttributes: HeatmapAttributes (
218+ identifier: identifier,
219+ size: CGSize ( width: 200 , height: 50 ) ,
220+ location: CGPoint ( x: 80 , y: 120 )
221+ )
222+ )
223+ )
224+ }
225+
226+ func testAddActionWithTouchWhenFallbackHitTestMisses( ) throws {
227+ // Given
228+ mockRootView. hitTestResult = nil
229+
230+ let touch : NSDictionary = [
231+ " reactTag " : 999 ,
232+ " x " : 10.0 ,
233+ " y " : 20.0 ,
234+ " pageX " : 100.0 ,
235+ " pageY " : 200.0
236+ ]
237+
238+ // When
239+ rum. addAction (
240+ type: " tap " ,
241+ name: " tap action " ,
242+ touch: touch,
243+ context: [ : ] ,
244+ timestampMs: randomTimestamp,
245+ resolve: mockResolve,
246+ reject: mockReject
247+ )
248+
249+ // Then
192250 XCTAssertEqual ( mockNativeRUM. calledMethods. count, 1 )
193251 XCTAssertEqual (
194252 mockNativeRUM. calledMethods. last,
@@ -444,6 +502,16 @@ private class MockUIManager: RCTUIManager {
444502 }
445503}
446504
505+ private class MockRootView : UIView {
506+ var hitTestResult : UIView ?
507+ var receivedHitTestPoints : [ CGPoint ] = [ ]
508+
509+ override func hitTest( _ point: CGPoint , with event: UIEvent ? ) -> UIView ? {
510+ receivedHitTestPoints. append ( point)
511+ return hitTestResult
512+ }
513+ }
514+
447515private final class MockHeatmapIdentifierRegistry : @unchecked Sendable , HeatmapIdentifierRegistry {
448516 @ReadWriteLock
449517 var identifiers : [ ObjectIdentifier : HeatmapIdentifier ] = [ : ]
0 commit comments