⋯ 244 lines Show the 244 lines above this hunk @@ -245,6 +245,37 @@ final class NativeNavigationUnitTests: XCTestCase { 245 245 XCTAssertFalse ( text . isScrollEnabled ) 246 246 } 247 247 248 + func testKeyedRowButtonKeepsItsNativeHitTargetAndDispatchAfterInputReordersRows ( ) async throws { 249 + let home = try XCTUnwrap ( stack ( "/" ) ) 250 + let screen = try XCTUnwrap ( home . topViewController as ? CraftNativeScreenController ) 251 + func find ( _ id : String , in view : UIView ) - > UIView ? { 252 + if view . accessibilityIdentifier = = id { return view } 253 + return view . subviews . lazy . compactMap { find ( id , in : $0 ) } . first 254 + } 255 + await displayWait ( "keyed input mounted" ) { find ( "navigation-input-b" , in : screen . view ) ! = nil } 256 + let input = try XCTUnwrap ( find ( "navigation-input-b" , in : screen . view ) as ? UITextField ) 257 + XCTAssertTrue ( input . becomeFirstResponder ( ) ) 258 + input . text = "draft" 259 + input . sendActions ( for : . editingChanged ) 260 + await displayWait ( "input-driven keyed reorder" ) { 261 + find ( "navigation-input-c" , in : screen . view ) ! = nil 262 + } 263 + XCTAssertTrue ( input = = = find ( "navigation-input-b" , in : screen . view ) ) 264 + let button = try XCTUnwrap ( find ( "navigation-select-b" , in : screen . view ) as ? UIButton ) 265 + let scroll = try XCTUnwrap ( find ( "native-root-scroll" , in : screen . view ) as ? UIScrollView ) 266 + screen . view . layoutIfNeeded ( ) 267 + scroll . scrollRectToVisible ( button . convert ( button . bounds , to : scroll ) , animated : false ) 268 + window . layoutIfNeeded ( ) 269 + let point = button . convert ( CGPoint ( x : button . bounds . midX , y : button . bounds . midY ) , to : window ) 270 + let hit = window . hitTest ( point , with : nil ) 271 + XCTAssertTrue ( hit = = = button | | hit ? . isDescendant ( of : button ) = = true , 272 + "The retained button's visible center hit \(String(describing: hit)) at \(point), button frame \(button.frame)" ) 273 + button . sendActions ( for : . touchUpInside ) 274 + await displayWait ( "retained row button callback" ) { 275 + ( find ( "keyed-list-status" , in : screen . view ) as ? UILabel ) ? . text = = "Selected: b" 276 + } 277 + } 278 + 248 279 func testRepeatedSelectorsRetainDistinctProtocolViewsAcrossReorders ( ) throws { 249 280 let controller = CraftNativeScreenController ( config : CraftConfig ( ) ) 250 281 window . rootViewController = controller