androidx.xr.compose.testing

Classes

SubspaceSemanticsMatcher

Wrapper for semantics matcher lambdas that allows building a description string explaining to the developer what conditions were being tested.

SubspaceSemanticsNodeInteraction

Represents a semantics node and the path to fetch it from the subspace semantics tree.

SubspaceSemanticsNodeInteractionCollection

Represents a collection of semantics nodes and the path to fetch them from the subspace semantics tree.

SubspaceTestContext

Provides the testing context used for retrieving and interacting with 3D Semantics nodes present within a Subspace spatial compose hierarchy.

Top-level functions summary

SubspaceSemanticsMatcher

Verifies whether any ancestor in the path to the 3D semantics root satisfies the given matcher.

SubspaceSemanticsMatcher

Verifies whether any immediate child of the 3D semantic node satisfies the given criteria.

SubspaceSemanticsMatcher

Verifies whether any descendant of the 3D semantic node satisfies the given condition.

SubspaceSemanticsMatcher

Verifies whether the 3D semantic node has any sibling satisfying the given condition.

SubspaceSemanticsMatcher
hasContentDescription(
    value: String,
    substring: Boolean,
    ignoreCase: Boolean
)

Verifies the 3D semantic node's content description for accessibility services.

SubspaceSemanticsMatcher

Verifies the direct parent of a 3D semantic node.

SubspaceSemanticsMatcher
hasTestTag(testTag: String)

Verifies the 3D semantic node's test tag.

SubspaceSemanticsMatcher

Verifies that the node is the root of the 3D semantics hierarchy.

Extension functions summary

SubspaceSemanticsNodeInteraction

Asserts that the layout of this node has depth that is greater than or equal to expectedMinDepth.

SubspaceSemanticsNodeInteraction

Asserts that the layout of this node has depth equal to expectedDepth.

SubspaceSemanticsNodeInteraction

Asserts that the layout of this node has depth that is NOT equal to expectedDepth.

SubspaceSemanticsNodeInteraction

Asserts that the layout of this node has height that is greater than or equal to expectedMinHeight.

SubspaceSemanticsNodeInteraction

Asserts that the layout of this node has height equal to expectedHeight.

SubspaceSemanticsNodeInteraction

Asserts that the layout of this node has height that is NOT equal to expectedHeight.

SubspaceSemanticsNodeInteraction

Asserts that the layout of this node has the left position in the root composable that is equal to the given position.

SubspaceSemanticsNodeInteraction
@CanIgnoreReturnValue
SubspaceSemanticsNodeInteraction.assertPositionInRootIsEqualTo(
    expectedX: Dp,
    expectedY: Dp,
    expectedZ: Dp
)

Asserts that the layout of this node has position in the root composable that is equal to the given position.

SubspaceSemanticsNodeInteraction
@CanIgnoreReturnValue
SubspaceSemanticsNodeInteraction.assertPositionIsEqualTo(
    expectedX: Dp,
    expectedY: Dp,
    expectedZ: Dp
)

Asserts that the layout of this node has position that is equal to the given position.

SubspaceSemanticsNodeInteraction

Asserts that the layout of this node has rotation in the root composable that is equal to the given rotation.

SubspaceSemanticsNodeInteraction

Asserts that the layout of this node has rotation that is equal to the given rotation.

SubspaceSemanticsNodeInteraction

Asserts that the layout of this node has the top position in the root composable that is equal to the given position.

SubspaceSemanticsNodeInteraction

Asserts that the layout of this node has width that is greater than or equal to expectedMinWidth.

SubspaceSemanticsNodeInteraction

Asserts that the layout of this node has width equal to expectedWidth.

SubspaceSemanticsNodeInteraction

Asserts that the layout of this node has width that is NOT equal to expectedWidth.

SubspaceSemanticsNodeInteraction

Asserts that the layout of this node has the x position in the root composable that is equal to the given position.

SubspaceSemanticsNodeInteraction

Asserts that the layout of this node has the x position that is equal to the given position.

SubspaceSemanticsNodeInteraction

Asserts that the layout of this node has the y position in the root composable that is equal to the given position.

SubspaceSemanticsNodeInteraction

Asserts that the layout of this node has the y position that is equal to the given position.

SubspaceSemanticsNodeInteraction

Asserts that the layout of this node has the z position in the root composable that is equal to the given position.

SubspaceSemanticsNodeInteraction

Asserts that the layout of this node has the z position that is equal to the given position.

Vector3

Returns the position of the node relative to its parent layout node.

Vector3

Returns the position of the node relative to the root node.

Quaternion

Returns the rotation of the node relative to its parent layout node.

Quaternion

Returns the rotation of the node relative to the root node.

DpVolumeSize

Returns the size of the node.

SubspaceSemanticsNodeInteractionCollection

Finds all semantics nodes in the Subspace hierarchy that match the given condition.

SubspaceSemanticsNodeInteractionCollection

Finds all semantics nodes in the Subspace hierarchy identified by the provided test tag.

SubspaceSemanticsNodeInteraction

Finds a semantics node in the Subspace hierarchy that matches the given condition.

SubspaceSemanticsNodeInteraction

Finds a semantics node in the Subspace hierarchy identified by the provided test tag.

Top-level functions

fun hasAnyAncestor(matcher: SubspaceSemanticsMatcher): SubspaceSemanticsMatcher

Verifies whether any ancestor in the path to the 3D semantics root satisfies the given matcher.

Example: For the following spatial semantic tree:

|-X
|-A
|-B
|-C1
|-C2

In case of C1, we would check the matcher against A and B.

Parameters
matcher: SubspaceSemanticsMatcher

The semantic criteria to evaluate against all ancestors up to the root.

Returns
SubspaceSemanticsMatcher

a matcher validating the presence of the specified ancestor.

fun hasAnyChild(matcher: SubspaceSemanticsMatcher): SubspaceSemanticsMatcher

Verifies whether any immediate child of the 3D semantic node satisfies the given criteria.

Useful when testing spatial composite layouts or multiple anchored floating panels grouped under a common parent semantic container.

Parameters
matcher: SubspaceSemanticsMatcher

The semantic criteria for the expected child.

Returns
SubspaceSemanticsMatcher

a matcher validating the node's children.

hasAnyDescendant

fun hasAnyDescendant(matcher: SubspaceSemanticsMatcher): SubspaceSemanticsMatcher

Verifies whether any descendant of the 3D semantic node satisfies the given condition.

Recursively descends the 3D semantic structure to locate deeply nested elements.

Example usage:

|-X
|-A
|-B
|-C1
|-C2

In case of A, we would check the matcher against B, C1 and C2.

Parameters
matcher: SubspaceSemanticsMatcher

The semantic criteria for the expected descendant.

Returns
SubspaceSemanticsMatcher

a matcher validating the presence of the specified descendant.

fun hasAnySibling(matcher: SubspaceSemanticsMatcher): SubspaceSemanticsMatcher

Verifies whether the 3D semantic node has any sibling satisfying the given condition.

A sibling is defined as any other spatial node sharing the exact same parent container.

Parameters
matcher: SubspaceSemanticsMatcher

The semantic criteria to evaluate against siblings.

Returns
SubspaceSemanticsMatcher

a matcher validating the node's siblings.

hasContentDescription

fun hasContentDescription(
    value: String,
    substring: Boolean = false,
    ignoreCase: Boolean = false
): SubspaceSemanticsMatcher

Verifies the 3D semantic node's content description for accessibility services.

Note that 2D UI content rendered inside a Subspace panel (like text or buttons) maintains a separate 2D semantics tree.

Parameters
value: String

The exact or partial description string expected on the spatial node.

substring: Boolean = false

If true, matches any node whose description contains value. Defaults to false.

ignoreCase: Boolean = false

If true, case differences are ignored during comparison. Defaults to false.

Returns
SubspaceSemanticsMatcher

a matcher validating the presence of the content description.

fun hasParent(matcher: SubspaceSemanticsMatcher): SubspaceSemanticsMatcher

Verifies the direct parent of a 3D semantic node.

This is indispensable for nested spatial compositions, such as a PlanarEmbeddedSubspace composed inside a SpatialPanel, to confirm exact container anchoring.

Parameters
matcher: SubspaceSemanticsMatcher

The semantic check to evaluate against the parent node.

Returns
SubspaceSemanticsMatcher

a matcher validating the parent's properties.

fun hasTestTag(testTag: String): SubspaceSemanticsMatcher

Verifies the 3D semantic node's test tag.

This is the primary mechanism for addressing spatial containers, anchors, and 3D panels in Compose for XR tests.

Parameters
testTag: String

The string identifier assigned to the spatial element.

Returns
SubspaceSemanticsMatcher

a matcher for the specified testTag.

fun isRoot(): SubspaceSemanticsMatcher

Verifies that the node is the root of the 3D semantics hierarchy.

Returns
SubspaceSemanticsMatcher

a matcher that matches the root semantics node.

Extension functions

SubspaceSemanticsNodeInteraction.assertDepthIsAtLeast

@CanIgnoreReturnValue
fun SubspaceSemanticsNodeInteraction.assertDepthIsAtLeast(
    expectedMinDepth: Dp
): SubspaceSemanticsNodeInteraction

Asserts that the layout of this node has depth that is greater than or equal to expectedMinDepth.

Parameters
expectedMinDepth: Dp

The minimum depth to assert.

Throws
AssertionError

if comparison fails.

SubspaceSemanticsNodeInteraction.assertDepthIsEqualTo

@CanIgnoreReturnValue
fun SubspaceSemanticsNodeInteraction.assertDepthIsEqualTo(
    expectedDepth: Dp
): SubspaceSemanticsNodeInteraction

Asserts that the layout of this node has depth equal to expectedDepth.

Parameters
expectedDepth: Dp

The depth to assert.

Throws
AssertionError

if comparison fails.

SubspaceSemanticsNodeInteraction.assertDepthIsNotEqualTo

@CanIgnoreReturnValue
fun SubspaceSemanticsNodeInteraction.assertDepthIsNotEqualTo(
    expectedDepth: Dp
): SubspaceSemanticsNodeInteraction

Asserts that the layout of this node has depth that is NOT equal to expectedDepth.

Parameters
expectedDepth: Dp

The depth to assert.

Throws
AssertionError

if comparison fails.

SubspaceSemanticsNodeInteraction.assertHeightIsAtLeast

@CanIgnoreReturnValue
fun SubspaceSemanticsNodeInteraction.assertHeightIsAtLeast(
    expectedMinHeight: Dp
): SubspaceSemanticsNodeInteraction

Asserts that the layout of this node has height that is greater than or equal to expectedMinHeight.

Parameters
expectedMinHeight: Dp

The minimum height to assert.

Throws
AssertionError

if comparison fails.

SubspaceSemanticsNodeInteraction.assertHeightIsEqualTo

@CanIgnoreReturnValue
fun SubspaceSemanticsNodeInteraction.assertHeightIsEqualTo(
    expectedHeight: Dp
): SubspaceSemanticsNodeInteraction

Asserts that the layout of this node has height equal to expectedHeight.

import androidx.compose.ui.unit.dp
import androidx.xr.compose.spatial.Subspace
import androidx.xr.compose.subspace.SpatialPanel
import androidx.xr.compose.subspace.layout.SubspaceModifier
import androidx.xr.compose.subspace.layout.height
import androidx.xr.compose.subspace.layout.width
import androidx.xr.compose.subspace.semantics.testTag
import androidx.xr.compose.testing.assertHeightIsEqualTo
import androidx.xr.compose.testing.assertPositionInRootIsEqualTo
import androidx.xr.compose.testing.assertWidthIsEqualTo
import androidx.xr.compose.testing.onSubspaceNodeWithTag

composeTestRule.setContent {
    Subspace {
        SpatialPanel(SubspaceModifier.width(100.dp).height(100.dp).testTag("myPanel")) {}
    }
}

// Check existence and exact spatial dimensions in DP using semantic matchers
composeTestRule
    .onSubspaceNodeWithTag("myPanel")
    .assertExists()
    .assertPositionInRootIsEqualTo(0.dp, 0.dp, 0.dp)
    .assertWidthIsEqualTo(100.toDp())
    .assertHeightIsEqualTo(100.toDp())
Parameters
expectedHeight: Dp

The height to assert.

Throws
AssertionError

if comparison fails.

SubspaceSemanticsNodeInteraction.assertHeightIsNotEqualTo

@CanIgnoreReturnValue
fun SubspaceSemanticsNodeInteraction.assertHeightIsNotEqualTo(
    expectedHeight: Dp
): SubspaceSemanticsNodeInteraction

Asserts that the layout of this node has height that is NOT equal to expectedHeight.

Parameters
expectedHeight: Dp

The height to assert.

Throws
AssertionError

if comparison fails.

SubspaceSemanticsNodeInteraction.assertLeftPositionInRootIsEqualTo

@CanIgnoreReturnValue
fun SubspaceSemanticsNodeInteraction.assertLeftPositionInRootIsEqualTo(
    expectedLeft: Dp
): SubspaceSemanticsNodeInteraction

Asserts that the layout of this node has the left position in the root composable that is equal to the given position.

Parameters
expectedLeft: Dp

The left position to assert.

Throws
AssertionError

if comparison fails.

SubspaceSemanticsNodeInteraction.assertPositionInRootIsEqualTo

@CanIgnoreReturnValue
fun SubspaceSemanticsNodeInteraction.assertPositionInRootIsEqualTo(
    expectedX: Dp,
    expectedY: Dp,
    expectedZ: Dp
): SubspaceSemanticsNodeInteraction

Asserts that the layout of this node has position in the root composable that is equal to the given position.

Parameters
expectedX: Dp

The x position to assert.

expectedY: Dp

The y position to assert.

expectedZ: Dp

The z position to assert.

Throws
AssertionError

if comparison fails.

SubspaceSemanticsNodeInteraction.assertPositionIsEqualTo

@CanIgnoreReturnValue
fun SubspaceSemanticsNodeInteraction.assertPositionIsEqualTo(
    expectedX: Dp,
    expectedY: Dp,
    expectedZ: Dp
): SubspaceSemanticsNodeInteraction

Asserts that the layout of this node has position that is equal to the given position.

Parameters
expectedX: Dp

The x position to assert.

expectedY: Dp

The y position to assert.

expectedZ: Dp

The z position to assert.

Throws
AssertionError

if comparison fails.

SubspaceSemanticsNodeInteraction.assertRotationInRootIsEqualTo

@CanIgnoreReturnValue
fun SubspaceSemanticsNodeInteraction.assertRotationInRootIsEqualTo(
    expected: Quaternion,
    tolerance: Float = 0.01f
): SubspaceSemanticsNodeInteraction

Asserts that the layout of this node has rotation in the root composable that is equal to the given rotation.

This assertion uses a tolerance to account for floating-point inaccuracies.

Parameters
expected: Quaternion

The expected rotation in the root space to assert.

tolerance: Float = 0.01f

The maximum allowed angular distance in degrees between the orientations.

Throws
AssertionError

if comparison fails.

SubspaceSemanticsNodeInteraction.assertRotationIsEqualTo

@CanIgnoreReturnValue
fun SubspaceSemanticsNodeInteraction.assertRotationIsEqualTo(
    expected: Quaternion,
    tolerance: Float = 0.01f
): SubspaceSemanticsNodeInteraction

Asserts that the layout of this node has rotation that is equal to the given rotation.

This assertion uses a tolerance to account for floating-point inaccuracies.

Parameters
expected: Quaternion

The rotation to assert.

tolerance: Float = 0.01f

The maximum allowed angular distance in degrees between the orientations.

Throws
AssertionError

if comparison fails.

SubspaceSemanticsNodeInteraction.assertTopPositionInRootIsEqualTo

@CanIgnoreReturnValue
fun SubspaceSemanticsNodeInteraction.assertTopPositionInRootIsEqualTo(
    expectedTop: Dp
): SubspaceSemanticsNodeInteraction

Asserts that the layout of this node has the top position in the root composable that is equal to the given position.

Parameters
expectedTop: Dp

The top position to assert.

Throws
AssertionError

if comparison fails.

SubspaceSemanticsNodeInteraction.assertWidthIsAtLeast

@CanIgnoreReturnValue
fun SubspaceSemanticsNodeInteraction.assertWidthIsAtLeast(
    expectedMinWidth: Dp
): SubspaceSemanticsNodeInteraction

Asserts that the layout of this node has width that is greater than or equal to expectedMinWidth.

Parameters
expectedMinWidth: Dp

The minimum width to assert.

Throws
AssertionError

if comparison fails.

SubspaceSemanticsNodeInteraction.assertWidthIsEqualTo

@CanIgnoreReturnValue
fun SubspaceSemanticsNodeInteraction.assertWidthIsEqualTo(
    expectedWidth: Dp
): SubspaceSemanticsNodeInteraction

Asserts that the layout of this node has width equal to expectedWidth.

import androidx.compose.ui.unit.dp
import androidx.xr.compose.spatial.Subspace
import androidx.xr.compose.subspace.SpatialPanel
import androidx.xr.compose.subspace.layout.SubspaceModifier
import androidx.xr.compose.subspace.layout.height
import androidx.xr.compose.subspace.layout.width
import androidx.xr.compose.subspace.semantics.testTag
import androidx.xr.compose.testing.assertHeightIsEqualTo
import androidx.xr.compose.testing.assertPositionInRootIsEqualTo
import androidx.xr.compose.testing.assertWidthIsEqualTo
import androidx.xr.compose.testing.onSubspaceNodeWithTag

composeTestRule.setContent {
    Subspace {
        SpatialPanel(SubspaceModifier.width(100.dp).height(100.dp).testTag("myPanel")) {}
    }
}

// Check existence and exact spatial dimensions in DP using semantic matchers
composeTestRule
    .onSubspaceNodeWithTag("myPanel")
    .assertExists()
    .assertPositionInRootIsEqualTo(0.dp, 0.dp, 0.dp)
    .assertWidthIsEqualTo(100.toDp())
    .assertHeightIsEqualTo(100.toDp())
Parameters
expectedWidth: Dp

The width to assert.

Throws
AssertionError

if comparison fails.

SubspaceSemanticsNodeInteraction.assertWidthIsNotEqualTo

@CanIgnoreReturnValue
fun SubspaceSemanticsNodeInteraction.assertWidthIsNotEqualTo(
    expectedWidth: Dp
): SubspaceSemanticsNodeInteraction

Asserts that the layout of this node has width that is NOT equal to expectedWidth.

Parameters
expectedWidth: Dp

The width to assert.

Throws
AssertionError

if comparison fails.

SubspaceSemanticsNodeInteraction.assertXPositionInRootIsEqualTo

@CanIgnoreReturnValue
fun SubspaceSemanticsNodeInteraction.assertXPositionInRootIsEqualTo(
    expectedX: Dp
): SubspaceSemanticsNodeInteraction

Asserts that the layout of this node has the x position in the root composable that is equal to the given position.

Parameters
expectedX: Dp

The x position to assert.

Throws
AssertionError

if comparison fails.

SubspaceSemanticsNodeInteraction.assertXPositionIsEqualTo

@CanIgnoreReturnValue
fun SubspaceSemanticsNodeInteraction.assertXPositionIsEqualTo(
    expectedX: Dp
): SubspaceSemanticsNodeInteraction

Asserts that the layout of this node has the x position that is equal to the given position.

Parameters
expectedX: Dp

The x position to assert.

Throws
AssertionError

if comparison fails.

SubspaceSemanticsNodeInteraction.assertYPositionInRootIsEqualTo

@CanIgnoreReturnValue
fun SubspaceSemanticsNodeInteraction.assertYPositionInRootIsEqualTo(
    expectedY: Dp
): SubspaceSemanticsNodeInteraction

Asserts that the layout of this node has the y position in the root composable that is equal to the given position.

Parameters
expectedY: Dp

The y position to assert.

Throws
AssertionError

if comparison fails.

SubspaceSemanticsNodeInteraction.assertYPositionIsEqualTo

@CanIgnoreReturnValue
fun SubspaceSemanticsNodeInteraction.assertYPositionIsEqualTo(
    expectedY: Dp
): SubspaceSemanticsNodeInteraction

Asserts that the layout of this node has the y position that is equal to the given position.

Parameters
expectedY: Dp

The y position to assert.

Throws
AssertionError

if comparison fails.

SubspaceSemanticsNodeInteraction.assertZPositionInRootIsEqualTo

@CanIgnoreReturnValue
fun SubspaceSemanticsNodeInteraction.assertZPositionInRootIsEqualTo(
    expectedZ: Dp
): SubspaceSemanticsNodeInteraction

Asserts that the layout of this node has the z position in the root composable that is equal to the given position.

Parameters
expectedZ: Dp

The z position to assert.

Throws
AssertionError

if comparison fails.

SubspaceSemanticsNodeInteraction.assertZPositionIsEqualTo

@CanIgnoreReturnValue
fun SubspaceSemanticsNodeInteraction.assertZPositionIsEqualTo(
    expectedZ: Dp
): SubspaceSemanticsNodeInteraction

Asserts that the layout of this node has the z position that is equal to the given position.

Parameters
expectedZ: Dp

The z position to assert.

Throws
AssertionError

if comparison fails.

SubspaceSemanticsNodeInteraction.getPosition

fun SubspaceSemanticsNodeInteraction.getPosition(): Vector3

Returns the position of the node relative to its parent layout node.

Additional assertions with custom tolerances may be performed on the individual values.

SubspaceSemanticsNodeInteraction.getPositionInRoot

fun SubspaceSemanticsNodeInteraction.getPositionInRoot(): Vector3

Returns the position of the node relative to the root node.

Additional assertions with custom tolerances may be performed on the individual values.

SubspaceSemanticsNodeInteraction.getRotation

fun SubspaceSemanticsNodeInteraction.getRotation(): Quaternion

Returns the rotation of the node relative to its parent layout node.

Additional assertions with custom tolerances may be performed on the individual values.

SubspaceSemanticsNodeInteraction.getRotationInRoot

fun SubspaceSemanticsNodeInteraction.getRotationInRoot(): Quaternion

Returns the rotation of the node relative to the root node.

Additional assertions with custom tolerances may be performed on the individual values.

SubspaceSemanticsNodeInteraction.getSize

fun SubspaceSemanticsNodeInteraction.getSize(): DpVolumeSize

Returns the size of the node.

Additional assertions with custom tolerances may be performed on the individual values.

AndroidComposeTestRule.onAllSubspaceNodes

fun AndroidComposeTestRule<*, *>.onAllSubspaceNodes(
    matcher: SubspaceSemanticsMatcher
): SubspaceSemanticsNodeInteractionCollection

Finds all semantics nodes in the Subspace hierarchy that match the given condition.

This function only locates nodes within the Subspace hierarchy and does not include nodes from standard 2D compose contexts. For locating 2D nodes, use AndroidComposeTestRule.onAllNodes. If you are dealing with elements guaranteed to occur exactly once, prefer using onSubspaceNode to enforce uniqueness constraints and improve clarity.

import androidx.compose.material3.Button
import androidx.compose.material3.Text
import androidx.compose.ui.test.onNodeWithText
import androidx.compose.ui.test.performClick
import androidx.xr.compose.spatial.Subspace
import androidx.xr.compose.subspace.SpatialPanel
import androidx.xr.compose.subspace.layout.SubspaceModifier
import androidx.xr.compose.subspace.semantics.testTag
import androidx.xr.compose.testing.assertPositionInRootIsEqualTo
import androidx.xr.compose.testing.onSubspaceNodeWithTag

var count = 0

composeTestRule.setContent {
    Subspace {
        SpatialPanel(SubspaceModifier.testTag("spatialPanel")) {
            Button(onClick = { count++ }) { Text("Increment") }
        }
    }
}

// Assert subspace node existence, position, and dimensions in the Spatial hierarchy
composeTestRule
    .onSubspaceNodeWithTag("spatialPanel")
    .assertExists()
    .assertPositionInRootIsEqualTo(0.toDp(), 0.toDp(), 0.toDp())

// Interact with the 2D Compose node nested within the Spatial container
composeTestRule.onNodeWithText("Increment").performClick()

composeTestRule.waitForIdle()

// Verify outcomes
assert(count == 1)
import androidx.compose.ui.unit.dp
import androidx.xr.compose.spatial.Subspace
import androidx.xr.compose.subspace.SpatialPanel
import androidx.xr.compose.subspace.layout.SubspaceModifier
import androidx.xr.compose.subspace.layout.height
import androidx.xr.compose.subspace.layout.width
import androidx.xr.compose.subspace.semantics.testTag
import androidx.xr.compose.testing.assertHeightIsEqualTo
import androidx.xr.compose.testing.assertPositionInRootIsEqualTo
import androidx.xr.compose.testing.assertWidthIsEqualTo
import androidx.xr.compose.testing.onSubspaceNodeWithTag

composeTestRule.setContent {
    Subspace {
        SpatialPanel(SubspaceModifier.width(100.dp).height(100.dp).testTag("myPanel")) {}
    }
}

// Check existence and exact spatial dimensions in DP using semantic matchers
composeTestRule
    .onSubspaceNodeWithTag("myPanel")
    .assertExists()
    .assertPositionInRootIsEqualTo(0.dp, 0.dp, 0.dp)
    .assertWidthIsEqualTo(100.toDp())
    .assertHeightIsEqualTo(100.toDp())
Parameters
matcher: SubspaceSemanticsMatcher

the SubspaceSemanticsMatcher used to filter the semantics nodes.

Returns
SubspaceSemanticsNodeInteractionCollection

the SubspaceSemanticsNodeInteractionCollection containing all matching nodes.

See also
onSubspaceNode

AndroidComposeTestRule.onAllSubspaceNodesWithTag

fun AndroidComposeTestRule<*, *>.onAllSubspaceNodesWithTag(
    testTag: String
): SubspaceSemanticsNodeInteractionCollection

Finds all semantics nodes in the Subspace hierarchy identified by the provided test tag.

This convenience function specifically searches for nodes within the Subspace hierarchy and does not locate standard 2D compose elements. The search evaluates for an exact string match on the test tag.

import androidx.compose.material3.Button
import androidx.compose.material3.Text
import androidx.compose.ui.test.onNodeWithText
import androidx.compose.ui.test.performClick
import androidx.xr.compose.spatial.Subspace
import androidx.xr.compose.subspace.SpatialPanel
import androidx.xr.compose.subspace.layout.SubspaceModifier
import androidx.xr.compose.subspace.semantics.testTag
import androidx.xr.compose.testing.assertPositionInRootIsEqualTo
import androidx.xr.compose.testing.onSubspaceNodeWithTag

var count = 0

composeTestRule.setContent {
    Subspace {
        SpatialPanel(SubspaceModifier.testTag("spatialPanel")) {
            Button(onClick = { count++ }) { Text("Increment") }
        }
    }
}

// Assert subspace node existence, position, and dimensions in the Spatial hierarchy
composeTestRule
    .onSubspaceNodeWithTag("spatialPanel")
    .assertExists()
    .assertPositionInRootIsEqualTo(0.toDp(), 0.toDp(), 0.toDp())

// Interact with the 2D Compose node nested within the Spatial container
composeTestRule.onNodeWithText("Increment").performClick()

composeTestRule.waitForIdle()

// Verify outcomes
assert(count == 1)
import androidx.compose.ui.unit.dp
import androidx.xr.compose.spatial.Subspace
import androidx.xr.compose.subspace.SpatialPanel
import androidx.xr.compose.subspace.layout.SubspaceModifier
import androidx.xr.compose.subspace.layout.height
import androidx.xr.compose.subspace.layout.width
import androidx.xr.compose.subspace.semantics.testTag
import androidx.xr.compose.testing.assertHeightIsEqualTo
import androidx.xr.compose.testing.assertPositionInRootIsEqualTo
import androidx.xr.compose.testing.assertWidthIsEqualTo
import androidx.xr.compose.testing.onSubspaceNodeWithTag

composeTestRule.setContent {
    Subspace {
        SpatialPanel(SubspaceModifier.width(100.dp).height(100.dp).testTag("myPanel")) {}
    }
}

// Check existence and exact spatial dimensions in DP using semantic matchers
composeTestRule
    .onSubspaceNodeWithTag("myPanel")
    .assertExists()
    .assertPositionInRootIsEqualTo(0.dp, 0.dp, 0.dp)
    .assertWidthIsEqualTo(100.toDp())
    .assertHeightIsEqualTo(100.toDp())
Parameters
testTag: String

the specific tag string to search for within the hierarchy.

Returns
SubspaceSemanticsNodeInteractionCollection

the SubspaceSemanticsNodeInteractionCollection containing all matching nodes.

AndroidComposeTestRule.onSubspaceNode

fun AndroidComposeTestRule<*, *>.onSubspaceNode(
    matcher: SubspaceSemanticsMatcher
): SubspaceSemanticsNodeInteraction

Finds a semantics node in the Subspace hierarchy that matches the given condition.

This function only locates nodes within the Subspace hierarchy and does not include nodes from standard 2D compose contexts. For example, it targets SpatialPanel, SpatialRow, or SpatialColumn nodes but not standard Row, Column, or Text nodes. For locating 2D nodes, use AndroidComposeTestRule.onNode.

Any subsequent operation on the returned interaction expects exactly one element to be found (unless SubspaceSemanticsNodeInteraction.assertDoesNotExist is used) and throws an AssertionError if zero or multiple elements are found.

import androidx.compose.material3.Button
import androidx.compose.material3.Text
import androidx.compose.ui.test.onNodeWithText
import androidx.compose.ui.test.performClick
import androidx.xr.compose.spatial.Subspace
import androidx.xr.compose.subspace.SpatialPanel
import androidx.xr.compose.subspace.layout.SubspaceModifier
import androidx.xr.compose.subspace.semantics.testTag
import androidx.xr.compose.testing.assertPositionInRootIsEqualTo
import androidx.xr.compose.testing.onSubspaceNodeWithTag

var count = 0

composeTestRule.setContent {
    Subspace {
        SpatialPanel(SubspaceModifier.testTag("spatialPanel")) {
            Button(onClick = { count++ }) { Text("Increment") }
        }
    }
}

// Assert subspace node existence, position, and dimensions in the Spatial hierarchy
composeTestRule
    .onSubspaceNodeWithTag("spatialPanel")
    .assertExists()
    .assertPositionInRootIsEqualTo(0.toDp(), 0.toDp(), 0.toDp())

// Interact with the 2D Compose node nested within the Spatial container
composeTestRule.onNodeWithText("Increment").performClick()

composeTestRule.waitForIdle()

// Verify outcomes
assert(count == 1)
import androidx.compose.ui.unit.dp
import androidx.xr.compose.spatial.Subspace
import androidx.xr.compose.subspace.SpatialPanel
import androidx.xr.compose.subspace.layout.SubspaceModifier
import androidx.xr.compose.subspace.layout.height
import androidx.xr.compose.subspace.layout.width
import androidx.xr.compose.subspace.semantics.testTag
import androidx.xr.compose.testing.assertHeightIsEqualTo
import androidx.xr.compose.testing.assertPositionInRootIsEqualTo
import androidx.xr.compose.testing.assertWidthIsEqualTo
import androidx.xr.compose.testing.onSubspaceNodeWithTag

composeTestRule.setContent {
    Subspace {
        SpatialPanel(SubspaceModifier.width(100.dp).height(100.dp).testTag("myPanel")) {}
    }
}

// Check existence and exact spatial dimensions in DP using semantic matchers
composeTestRule
    .onSubspaceNodeWithTag("myPanel")
    .assertExists()
    .assertPositionInRootIsEqualTo(0.dp, 0.dp, 0.dp)
    .assertWidthIsEqualTo(100.toDp())
    .assertHeightIsEqualTo(100.toDp())
Parameters
matcher: SubspaceSemanticsMatcher

the SubspaceSemanticsMatcher used to identify the matching semantics node.

Returns
SubspaceSemanticsNodeInteraction

the SubspaceSemanticsNodeInteraction for the matched node.

AndroidComposeTestRule.onSubspaceNodeWithTag

fun AndroidComposeTestRule<*, *>.onSubspaceNodeWithTag(testTag: String): SubspaceSemanticsNodeInteraction

Finds a semantics node in the Subspace hierarchy identified by the provided test tag.

This convenience function specifically searches for nodes within the Subspace hierarchy and does not locate standard 2D compose elements. The search evaluates for an exact string match on the test tag.

import androidx.compose.material3.Button
import androidx.compose.material3.Text
import androidx.compose.ui.test.onNodeWithText
import androidx.compose.ui.test.performClick
import androidx.xr.compose.spatial.Subspace
import androidx.xr.compose.subspace.SpatialPanel
import androidx.xr.compose.subspace.layout.SubspaceModifier
import androidx.xr.compose.subspace.semantics.testTag
import androidx.xr.compose.testing.assertPositionInRootIsEqualTo
import androidx.xr.compose.testing.onSubspaceNodeWithTag

var count = 0

composeTestRule.setContent {
    Subspace {
        SpatialPanel(SubspaceModifier.testTag("spatialPanel")) {
            Button(onClick = { count++ }) { Text("Increment") }
        }
    }
}

// Assert subspace node existence, position, and dimensions in the Spatial hierarchy
composeTestRule
    .onSubspaceNodeWithTag("spatialPanel")
    .assertExists()
    .assertPositionInRootIsEqualTo(0.toDp(), 0.toDp(), 0.toDp())

// Interact with the 2D Compose node nested within the Spatial container
composeTestRule.onNodeWithText("Increment").performClick()

composeTestRule.waitForIdle()

// Verify outcomes
assert(count == 1)
import androidx.compose.ui.unit.dp
import androidx.xr.compose.spatial.Subspace
import androidx.xr.compose.subspace.SpatialPanel
import androidx.xr.compose.subspace.layout.SubspaceModifier
import androidx.xr.compose.subspace.layout.height
import androidx.xr.compose.subspace.layout.width
import androidx.xr.compose.subspace.semantics.testTag
import androidx.xr.compose.testing.assertHeightIsEqualTo
import androidx.xr.compose.testing.assertPositionInRootIsEqualTo
import androidx.xr.compose.testing.assertWidthIsEqualTo
import androidx.xr.compose.testing.onSubspaceNodeWithTag

composeTestRule.setContent {
    Subspace {
        SpatialPanel(SubspaceModifier.width(100.dp).height(100.dp).testTag("myPanel")) {}
    }
}

// Check existence and exact spatial dimensions in DP using semantic matchers
composeTestRule
    .onSubspaceNodeWithTag("myPanel")
    .assertExists()
    .assertPositionInRootIsEqualTo(0.dp, 0.dp, 0.dp)
    .assertWidthIsEqualTo(100.toDp())
    .assertHeightIsEqualTo(100.toDp())
Parameters
testTag: String

the specific tag string to search for within the hierarchy.

Returns
SubspaceSemanticsNodeInteraction

the SubspaceSemanticsNodeInteraction for the matched node.

See also
onSubspaceNode