iOS UIKit simulator ARM64 utilities for Compose Multiplatform UI framework providing testing, interoperability, and platform-specific implementations.
—
iOS accessibility system integration with VoiceOver support, accessibility tree validation, and comprehensive testing utilities for ensuring app accessibility compliance.
Functions for building and analyzing the accessibility tree from the UI hierarchy.
/**
* Constructs accessibility tree from current UI hierarchy
* @return Root AccessibilityTestNode representing the complete accessibility tree
*/
internal fun UIKitInstrumentedTest.getAccessibilityTree(): AccessibilityTestNode
/**
* Normalizes accessibility tree by removing non-essential elements
* @return Normalized accessibility tree with only meaningful nodes, or null if empty
*/
internal fun AccessibilityTestNode.normalized(): AccessibilityTestNode?Usage Example:
runUIKitInstrumentedTest {
setContentWithAccessibilityEnabled {
Column {
Text("Welcome")
Button(onClick = {}) {
Text("Submit")
}
}
}
val tree = getAccessibilityTree()
val normalizedTree = tree.normalized()
println("Accessibility tree: $normalizedTree")
}Functions for finding specific nodes within the accessibility tree based on various criteria.
/**
* Finds accessibility node by identifier tag
* @param tag - Identifier tag to search for
* @return AccessibilityTestNode if found
* @throws AssertionError if node with tag is not found
*/
internal fun UIKitInstrumentedTest.findNodeWithTag(tag: String): AccessibilityTestNode
/**
* Finds accessibility node by accessibility label
* @param label - Accessibility label to search for
* @return AccessibilityTestNode if found
* @throws AssertionError if node with label is not found
*/
internal fun UIKitInstrumentedTest.findNodeWithLabel(label: String): AccessibilityTestNode
/**
* Finds first accessibility element in the tree
* @return AccessibilityTestNode of first accessible element
* @throws AssertionError if no accessibility element is found
*/
internal fun UIKitInstrumentedTest.firstAccessibleNode(): AccessibilityTestNode
/**
* Finds accessibility node matching a condition
* @param isValid - Predicate function to test nodes
* @return AccessibilityTestNode if found, null otherwise
*/
internal fun UIKitInstrumentedTest.findNodeOrNull(
isValid: (AccessibilityTestNode) -> Boolean
): AccessibilityTestNode?Usage Examples:
runUIKitInstrumentedTest {
setContentWithAccessibilityEnabled {
Button(
onClick = {},
modifier = Modifier.testTag("submit_button")
) {
Text("Submit Form")
}
}
// Find by test tag
val submitButton = findNodeWithTag("submit_button")
requireNotNull(submitButton) { "Submit button not found" }
// Find by accessibility label
val labeledNode = findNodeWithLabel("Submit Form")
requireNotNull(labeledNode) { "Node with label not found" }
}Comprehensive validation functions for asserting accessibility tree structure and content.
/**
* Asserts that accessibility tree matches expected structure
* @param block - DSL block defining expected tree structure
* @throws AssertionError if tree structure doesn't match expectations
*/
fun UIKitInstrumentedTest.assertAccessibilityTree(
block: AccessibilityTestNode.() -> Unit
)Usage Example:
runUIKitInstrumentedTest {
setContentWithAccessibilityEnabled {
Column {
Text("Header Text")
Row {
Text("Label:")
Text("Value")
}
Button(onClick = {}) {
Text("Action")
}
}
}
assertAccessibilityTree {
node {
label = "Header Text"
children = listOf(
node {
label = "Label:"
children = listOf(
node { label = "Value" }
)
},
node {
label = "Action"
role = "button"
}
)
}
}
}Functions for interacting with accessibility nodes through accessibility actions.
/**
* Simulates tap on accessibility element using accessibility actions
* @throws IllegalStateException if node is not accessible or tappable
*/
fun AccessibilityTestNode.tap()
/**
* Simulates double tap on accessibility element
* @throws IllegalStateException if node doesn't support double tap action
*/
fun AccessibilityTestNode.doubleTap()Usage Examples:
runUIKitInstrumentedTest {
setContentWithAccessibilityEnabled {
Button(onClick = { println("Button clicked!") }) {
Text("Click Me")
}
}
val button = findNodeWithLabel("Click Me")
requireNotNull(button) { "Button not found" }
// Tap using accessibility action
button.tap()
// Double tap if supported
button.doubleTap()
}Represents a node in the accessibility tree with comprehensive accessibility information.
/**
* Represents a node in the accessibility tree for testing purposes
* @param isAccessibilityElement - Whether element is exposed to accessibility services
* @param identifier - Unique identifier for the accessibility element
* @param label - Accessibility label for VoiceOver
* @param value - Current value of the accessibility element
* @param frame - Bounding rectangle in screen coordinates
* @param children - Child accessibility nodes
* @param traits - Accessibility traits as UIAccessibilityTraits values
* @param element - Reference to the underlying NSObject
* @param parent - Parent accessibility node
*/
internal data class AccessibilityTestNode(
var isAccessibilityElement: Boolean? = null,
var identifier: String? = null,
var label: String? = null,
var value: String? = null,
var frame: DpRect? = null,
var children: List<AccessibilityTestNode>? = null,
var traits: List<UIAccessibilityTraits>? = null,
var element: NSObject? = null,
var parent: AccessibilityTestNode? = null
) {
fun validate(actualNode: AccessibilityTestNode?)
fun node(builder: AccessibilityTestNode.() -> Unit)
fun traits(vararg trait: UIAccessibilityTraits)
fun printTree(): String
val hasAccessibilityComponents: Boolean
}Usage Example:
val node = AccessibilityTestNode(
identifier = "user_profile_button",
label = "User Profile",
hint = "Double tap to open profile",
role = "button",
traits = setOf("button", "enabled"),
frame = DpRect(
offset = DpOffset(10.dp, 10.dp),
size = DpSize(100.dp, 44.dp)
)
)runUIKitInstrumentedTest {
setContentWithAccessibilityEnabled {
NavigationView {
List {
ForEach(items) { item ->
NavigationLink(destination = DetailView(item)) {
VStack {
Text(item.title)
Text(item.subtitle)
}
}
}
}
}
}
assertAccessibilityTree {
node {
role = "list"
children = items.map { item ->
node {
label = item.title
role = "button"
traits = setOf("button", "link")
children = listOf(
node { label = item.subtitle }
)
}
}
}
}
}runUIKitInstrumentedTest {
var counter by remember { mutableStateOf(0) }
setContentWithAccessibilityEnabled {
Column {
Text("Count: $counter")
Button(onClick = { counter++ }) {
Text("Increment")
}
}
}
// Test initial state
val initialCount = findNodeWithLabel("Count: 0")
requireNotNull(initialCount)
// Interact and test updated state
val button = findNodeWithLabel("Increment")
button?.tap()
waitUntil {
findNodeWithLabel("Count: 1") != null
}
}Install with Tessl CLI
npx tessl i tessl/maven-org-jetbrains-compose-ui--ui-util-uikitsimarm64