Skip to content

Improve iOS Instrumented Tests for textfields - #3277

Merged
Vladimir Mazunin (mazunin-v-jb) merged 3 commits into
jb-mainfrom
v.mazunin/improve-instrumented-test-for-textfields
Aug 31, 2026
Merged

Improve iOS Instrumented Tests for textfields#3277
Vladimir Mazunin (mazunin-v-jb) merged 3 commits into
jb-mainfrom
v.mazunin/improve-instrumented-test-for-textfields

Conversation

@mazunin-v-jb

@mazunin-v-jb Vladimir Mazunin (mazunin-v-jb) commented Jul 30, 2026

Copy link
Copy Markdown
  • Added PlatformContext.RootForTestListener propagation to the iOS layer
  • Added test utilities for caret placement via tap and long press, as well as for finding and dragging selection handles for both BasicTextField implementations, including NITI variants
  • Added example tests using the new API
  • Rewrote the multitap tests to use the new API

New test API (internal)

test/utils/TextField+Utils.kt

provides character positioning and tap utilities:

  • tapCharacter(tag, offset)
  • longPressCharacter(tag, offset)
  • multiTapCharacter(tag, offset, count) (for double/triple tap)

All of these are based on characterPosition, which reads from TextLayoutResult via RootForTestListener

test/utils/SelectionHandle+Utils.kt

provides utilities for selection handles:

  • selectionHandles() returns a SelectionHandlePair

  • dragSelectionHandle(handle, tag, toOffset, duration = 0.5s) provides a single entry point for dragging a handle in Compose TextField, Native TextField, and SelectionContainer

  • SelectionHandlePair is a helper data class that stores the start and end TestSelectionHandle in deterministic order

  • TestSelectionHandle is a data class containing the information required by tests, parsed from Compose SelectionHandle and iOS native SelectionHandle (_UITextSelectionLollipopView)

Fixes:
CMP-10037 Extend iOSInstrumentedTest API for TextField testing
CMP-10648 [iOS] Instrumented Tests: native selection handle has a positional hysteresis when dragged downwards

Release Notes

N/A

}

/** Taps character [offset] in the text field tagged [tag]. */
internal fun UIKitInstrumentedTest.tapCharacter(tag: String, offset: Int) {

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

In the touches simulation API we're using the UIKitInstrumentedTest only to start initial touch. All other manipulations are done with the UITouch itself. The reason here - to narrow down API surface of the UIKitInstrumentedTest.

Here I would suggest doing kinda the same - make tapCharacter and other methods as extension of the SemanticsNode (or even AccessibilityTestNode - see P.S section).

P.S. Totally optional, but anyway:
Technically, AccessibilityTestNode also contains reference to the corresponding SemanticsNode. It will be (AccessibilityTestNode.element as? AccessibilityElement).node?.semanticsNode, but the problem is - AccessibilityElement is private. So we need some workaround to access the semanticsNode.

Copy link
Copy Markdown
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

done

also added dragSelectionHandle to the AccessibilityTestNode, however, inside there're lots of implementation methods which I didn't want to move to the UIKitInstrumentTest, so I had to leave UIKitInstrumentTest.dragSelectionHandleImpl.

…ew`.

Removed comment in `TextFieldCaretPlacementTest`.

Added examples for caret placement and selection handles tests using new API, rewritten multitap tests using new API, extracted BasicTextFieldType to the TextField+Utils.kt to reduce duplicates

Added SelectionContainer  tests examples for new API

refactored native handles detection and dragging, refactored drag gesture, considered positional hysteresis for native handles, fine-tuned stop conditions, cleaned the code and comments

Moved `objcClassName` utility to UIView+Utils; removed redundant imports in TextField+Utils.

Added todo

Fixed native selection handle dragging, updated & fixed comments

Updated `characterPosition` documentation to clarify iOS caret snap behavior to word boundaries.

Added support for native iOS text selection handles and updated handle utilities for unified behavior across native and Compose-rendered handles.

Simplify `TestHandle` and `TestSelectionHandleAnchor` enums by removing unused cases for iOS rendering.

Removed the method of fetching cursor handle from the semantics - it would be noop on ios

Add utilities for testing text selection handles and update `rootForTestListener` handling in iOS platform code to be able to grab selection handles since they're popups

Added character-based text field utilities for iOS (`characterPosition`, `tapCharacter`, `longPressCharacter`, and `multiTapCharacter`) to support advanced gesture handling.

Implemented `rootForTestListener` to support test roots tracking in iOS platform code.
@mazunin-v-jb
Vladimir Mazunin (mazunin-v-jb) force-pushed the v.mazunin/improve-instrumented-test-for-textfields branch from 6f34aab to b558553 Compare August 26, 2026 12:48
…tyTestNode` API, removed redundant utility methods, and updated gesture interaction logic for iOS.
@janinadavydova

Copy link
Copy Markdown

I tried the API, especially for the selection handles, looks like what we needed for our cases, thank you. So for now approve from my side.

@mazunin-v-jb
Vladimir Mazunin (mazunin-v-jb) merged commit 07023bf into jb-main Aug 31, 2026
20 checks passed
@mazunin-v-jb
Vladimir Mazunin (mazunin-v-jb) deleted the v.mazunin/improve-instrumented-test-for-textfields branch August 31, 2026 12:20
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants