SubspaceSemanticsMatcher

class SubspaceSemanticsMatcher


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

This class encapsulates a predicate that evaluates a SubspaceSemanticsInfo node to verify whether it matches the expected semantic properties. It is primarily used by the testing framework to locate nodes within a Subspace hierarchy.

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.onSubspaceNode
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.onSubspaceNode
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())
import androidx.compose.ui.semantics.SemanticsProperties
import androidx.xr.compose.spatial.Subspace
import androidx.xr.compose.testing.SubspaceSemanticsMatcher
import androidx.xr.compose.testing.onSubspaceNode

// Construct custom semantics matchers using factory methods
val hasTestTag =
    SubspaceSemanticsMatcher.expectValue(SemanticsProperties.TestTag, "customPanel")
val hasContentDescription =
    SubspaceSemanticsMatcher.keyIsDefined(SemanticsProperties.ContentDescription)

// Combine matchers using infix functions and logical operators
val complexMatcher = hasTestTag and hasContentDescription

// Use the combined matcher to locate and assert existence of the spatial node
composeTestRule.onSubspaceNode(complexMatcher).assertExists()

Summary

Public companion functions

SubspaceSemanticsMatcher
<T : Any?> expectValue(key: SemanticsPropertyKey<T>, expectedValue: T)

Builds a predicate that tests whether the value of the given key is equal to expectedValue.

SubspaceSemanticsMatcher

Builds a predicate that tests whether the given key is defined in semantics.

SubspaceSemanticsMatcher

Builds a predicate that tests whether the given key is NOT defined in semantics.

Public constructors

SubspaceSemanticsMatcher(
    description: String,
    matcher: (SubspaceSemanticsInfo) -> Boolean
)

Public functions

infix SubspaceSemanticsMatcher

Combines this matcher with other using a short-circuiting logical AND.

Boolean

Returns whether the given node is matched by this matcher.

Boolean

Returns whether at least one of the given nodes is matched by this matcher.

operator SubspaceSemanticsMatcher
not()

Inverts the evaluation logic of this matcher using a logical NOT.

infix SubspaceSemanticsMatcher

Combines this matcher with other using a short-circuiting logical OR.

Public properties

String

A human-readable explanation of the condition being tested, used in test failure messages.

Public companion functions

expectValue

Added in 1.0.0-alpha16
fun <T : Any?> expectValue(key: SemanticsPropertyKey<T>, expectedValue: T): SubspaceSemanticsMatcher

Builds a predicate that tests whether the value of the given key is equal to expectedValue.

Nullability & Edge Cases: If the key is not present in a node's semantics configuration, the comparison evaluates whether null == expectedValue. Therefore, passing null as the expectedValue successfully matches nodes where the key is entirely omitted, as well as nodes where the key is present but has a value of null.

import androidx.compose.ui.semantics.SemanticsProperties
import androidx.xr.compose.spatial.Subspace
import androidx.xr.compose.testing.SubspaceSemanticsMatcher
import androidx.xr.compose.testing.onSubspaceNode

// Construct custom semantics matchers using factory methods
val hasTestTag =
    SubspaceSemanticsMatcher.expectValue(SemanticsProperties.TestTag, "customPanel")
val hasContentDescription =
    SubspaceSemanticsMatcher.keyIsDefined(SemanticsProperties.ContentDescription)

// Combine matchers using infix functions and logical operators
val complexMatcher = hasTestTag and hasContentDescription

// Use the combined matcher to locate and assert existence of the spatial node
composeTestRule.onSubspaceNode(complexMatcher).assertExists()
Parameters
key: SemanticsPropertyKey<T>

The SemanticsPropertyKey to look up in the node's configuration.

expectedValue: T

The expected property value to verify against.

Returns
SubspaceSemanticsMatcher

A SubspaceSemanticsMatcher for the specified key-value condition.

keyIsDefined

Added in 1.0.0-alpha16
fun <T : Any?> keyIsDefined(key: SemanticsPropertyKey<T>): SubspaceSemanticsMatcher

Builds a predicate that tests whether the given key is defined in semantics.

Edge Cases: This check simply verifies the pre-existence of the key mapping in the node's configuration regardless of its underlying assigned value.

import androidx.compose.ui.semantics.SemanticsProperties
import androidx.xr.compose.spatial.Subspace
import androidx.xr.compose.testing.SubspaceSemanticsMatcher
import androidx.xr.compose.testing.onSubspaceNode

// Construct custom semantics matchers using factory methods
val hasTestTag =
    SubspaceSemanticsMatcher.expectValue(SemanticsProperties.TestTag, "customPanel")
val hasContentDescription =
    SubspaceSemanticsMatcher.keyIsDefined(SemanticsProperties.ContentDescription)

// Combine matchers using infix functions and logical operators
val complexMatcher = hasTestTag and hasContentDescription

// Use the combined matcher to locate and assert existence of the spatial node
composeTestRule.onSubspaceNode(complexMatcher).assertExists()
Parameters
key: SemanticsPropertyKey<T>

The SemanticsPropertyKey to inspect.

Returns
SubspaceSemanticsMatcher

A SubspaceSemanticsMatcher verifying the presence of the key.

keyNotDefined

Added in 1.0.0-alpha16
fun <T : Any?> keyNotDefined(key: SemanticsPropertyKey<T>): SubspaceSemanticsMatcher

Builds a predicate that tests whether the given key is NOT defined in semantics.

Edge Cases: This check validates that the key mapping is completely absent from the node's configuration.

import androidx.compose.ui.semantics.SemanticsProperties
import androidx.xr.compose.spatial.Subspace
import androidx.xr.compose.testing.SubspaceSemanticsMatcher
import androidx.xr.compose.testing.onSubspaceNode

// Construct custom semantics matchers using factory methods
val hasTestTag =
    SubspaceSemanticsMatcher.expectValue(SemanticsProperties.TestTag, "customPanel")
val hasContentDescription =
    SubspaceSemanticsMatcher.keyIsDefined(SemanticsProperties.ContentDescription)

// Combine matchers using infix functions and logical operators
val complexMatcher = hasTestTag and hasContentDescription

// Use the combined matcher to locate and assert existence of the spatial node
composeTestRule.onSubspaceNode(complexMatcher).assertExists()
Parameters
key: SemanticsPropertyKey<T>

The SemanticsPropertyKey to inspect.

Returns
SubspaceSemanticsMatcher

A SubspaceSemanticsMatcher verifying the absence of the key.

Public constructors

SubspaceSemanticsMatcher

Added in 1.0.0-alpha16
SubspaceSemanticsMatcher(
    description: String,
    matcher: (SubspaceSemanticsInfo) -> Boolean
)
Parameters
description: String

A human-readable explanation of the condition being tested, used in test failure messages.

matcher: (SubspaceSemanticsInfo) -> Boolean

The predicate function that evaluates a given SubspaceSemanticsInfo.

Public functions

and

Added in 1.0.0-alpha16
infix fun and(other: SubspaceSemanticsMatcher): SubspaceSemanticsMatcher

Combines this matcher with other using a short-circuiting logical AND.

The resulting matcher evaluates to true only if both this and the other matcher succeed on a given node.

import androidx.compose.ui.semantics.SemanticsProperties
import androidx.xr.compose.spatial.Subspace
import androidx.xr.compose.testing.SubspaceSemanticsMatcher
import androidx.xr.compose.testing.onSubspaceNode

// Construct custom semantics matchers using factory methods
val hasTestTag =
    SubspaceSemanticsMatcher.expectValue(SemanticsProperties.TestTag, "customPanel")
val hasContentDescription =
    SubspaceSemanticsMatcher.keyIsDefined(SemanticsProperties.ContentDescription)

// Combine matchers using infix functions and logical operators
val complexMatcher = hasTestTag and hasContentDescription

// Use the combined matcher to locate and assert existence of the spatial node
composeTestRule.onSubspaceNode(complexMatcher).assertExists()
Parameters
other: SubspaceSemanticsMatcher

The second SubspaceSemanticsMatcher to satisfy.

matches

Added in 1.0.0-alpha16
fun matches(node: SubspaceSemanticsInfo): Boolean

Returns whether the given node is matched by this matcher.

Parameters
node: SubspaceSemanticsInfo

The target SubspaceSemanticsInfo to evaluate.

Returns
Boolean

true if the node satisfies the predicate; false otherwise.

matchesAny

fun matchesAny(nodes: Iterable<SubspaceSemanticsInfo>): Boolean

Returns whether at least one of the given nodes is matched by this matcher.

Edge Cases: If the provided nodes iterable is empty, this evaluation returns false.

Parameters
nodes: Iterable<SubspaceSemanticsInfo>

An iterable collection of SubspaceSemanticsInfo instances to evaluate.

Returns
Boolean

true if at least one node satisfies the predicate; false otherwise.

not

Added in 1.0.0-alpha16
operator fun not(): SubspaceSemanticsMatcher

Inverts the evaluation logic of this matcher using a logical NOT.

Evaluates to true if the underlying matcher evaluates to false.

import androidx.compose.ui.semantics.SemanticsProperties
import androidx.xr.compose.spatial.Subspace
import androidx.xr.compose.testing.SubspaceSemanticsMatcher
import androidx.xr.compose.testing.onSubspaceNode

// Construct custom semantics matchers using factory methods
val hasTestTag =
    SubspaceSemanticsMatcher.expectValue(SemanticsProperties.TestTag, "customPanel")
val hasContentDescription =
    SubspaceSemanticsMatcher.keyIsDefined(SemanticsProperties.ContentDescription)

// Combine matchers using infix functions and logical operators
val complexMatcher = hasTestTag and hasContentDescription

// Use the combined matcher to locate and assert existence of the spatial node
composeTestRule.onSubspaceNode(complexMatcher).assertExists()

or

Added in 1.0.0-alpha16
infix fun or(other: SubspaceSemanticsMatcher): SubspaceSemanticsMatcher

Combines this matcher with other using a short-circuiting logical OR.

The resulting matcher evaluates to true if either this or the other matcher succeeds on a given node.

import androidx.compose.ui.semantics.SemanticsProperties
import androidx.xr.compose.spatial.Subspace
import androidx.xr.compose.testing.SubspaceSemanticsMatcher
import androidx.xr.compose.testing.onSubspaceNode

// Construct custom semantics matchers using factory methods
val hasTestTag =
    SubspaceSemanticsMatcher.expectValue(SemanticsProperties.TestTag, "customPanel")
val hasContentDescription =
    SubspaceSemanticsMatcher.keyIsDefined(SemanticsProperties.ContentDescription)

// Combine matchers using infix functions and logical operators
val complexMatcher = hasTestTag and hasContentDescription

// Use the combined matcher to locate and assert existence of the spatial node
composeTestRule.onSubspaceNode(complexMatcher).assertExists()
Parameters
other: SubspaceSemanticsMatcher

The alternative SubspaceSemanticsMatcher to satisfy.

Public properties

description

Added in 1.0.0-alpha16
val descriptionString

A human-readable explanation of the condition being tested, used in test failure messages.