Skip to content

Commit 8a0f973

Browse files
committed
add in projected unit tests
1 parent 16115b7 commit 8a0f973

3 files changed

Lines changed: 98 additions & 0 deletions

File tree

gradle/libs.versions.toml

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -45,6 +45,7 @@ coil = "2.7.0"
4545
compileSdk = "36"
4646
compose-latest = "1.10.5"
4747
composeUiTooling = "1.5.6"
48+
coreKtx = "1.6.1"
4849
coreSplashscreen = "1.2.0"
4950
coroutines = "1.10.2"
5051
dataStore = "1.2.1"
@@ -74,6 +75,7 @@ material3-adaptive = "1.2.0"
7475
material3-adaptive-navigation-suite = "1.4.0"
7576
media3 = "1.9.2"
7677
media3Ui = "1.9.2"
78+
mockitoKotlin = "4.1.0"
7779
# @keep
7880
minSdk = "36"
7981
okHttp = "5.3.2"
@@ -91,6 +93,7 @@ spotless = "8.3.0"
9193
targetSdk = "36"
9294
tiles = "1.5.0"
9395
tracing = "1.3.0"
96+
truth = "1.4.4"
9497
tvComposeMaterial3 = "1.1.0-beta01"
9598
validatorPush = "1.0.0-alpha09"
9699
version-catalog-update = "1.1.0"
@@ -221,12 +224,14 @@ androidx-xr-arcore-play-services = { module = "androidx.xr.arcore:arcore-play-se
221224
androidx-xr-compose = { module = "androidx.xr.compose:compose", version.ref = "androidx-xr-compose" }
222225
androidx-xr-glimmer = { module = "androidx.xr.glimmer:glimmer", version.ref = "androidx-xr-glimmer" }
223226
androidx-xr-projected = { module = "androidx.xr.projected:projected", version.ref = "androidx-xr-projected" }
227+
androidx-xr-projected-testing = { module = "androidx.xr.projected:projected-testing", version.ref = "androidx-xr-projected" }
224228
androidx-xr-scenecore = { module = "androidx.xr.scenecore:scenecore", version.ref = "androidx-xr-scenecore" }
225229
appcompat = { module = "androidx.appcompat:appcompat", version.ref = "appcompat" }
226230
billing = { module = "com.android.billingclient:billing", version.ref = "playbilling" }
227231
coil-kt-compose = { module = "io.coil-kt:coil-compose", version.ref = "coil" }
228232
compose-foundation = { module = "androidx.wear.compose:compose-foundation", version.ref = "wearComposeFoundation" }
229233
compose-ui-tooling = { module = "androidx.wear.compose:compose-ui-tooling", version.ref = "composeUiTooling" }
234+
core-ktx = { module = "androidx.test:core-ktx", version.ref = "coreKtx" }
230235
firebase-ai = { module = "com.google.firebase:firebase-ai" }
231236
firebase-bom = { module = "com.google.firebase:firebase-bom", version.ref = "firebase-bom" }
232237
glide-compose = { module = "com.github.bumptech.glide:compose", version.ref = "glide" }
@@ -253,6 +258,7 @@ kotlinx-coroutines-play-services = { module = "org.jetbrains.kotlinx:kotlinx-cor
253258
kotlinx-coroutines-test = { module = "org.jetbrains.kotlinx:kotlinx-coroutines-test", version.ref = "coroutines" }
254259
kotlinx-metadata-jvm = { module = "org.jetbrains.kotlin:kotlin-metadata-jvm", version.ref = "kotlin" }
255260
kotlinx-serialization-json = { module = "org.jetbrains.kotlinx:kotlinx-serialization-json", version.ref = "kotlinxSerializationJson" }
261+
mockito-kotlin = { module = "org.mockito.kotlin:mockito-kotlin", version.ref = "mockitoKotlin" }
256262
okhttp = { module = "com.squareup.okhttp3:okhttp", version.ref = "okHttp" }
257263
play-services-wearable = { module = "com.google.android.gms:play-services-wearable", version.ref = "playServicesWearable" }
258264
reactive-streams = { module = "org.reactivestreams:reactive-streams", version.ref = "reactive-streams" }
@@ -261,6 +267,7 @@ roborazzi = { module = "io.github.takahirom.roborazzi:roborazzi", version.ref =
261267
roborazzi-compose = { module = "io.github.takahirom.roborazzi:roborazzi-compose", version.ref = "roborazzi" }
262268
roborazzi-rule = { module = "io.github.takahirom.roborazzi:roborazzi-junit-rule", version.ref = "roborazzi" }
263269
tv-compose-material = { module = "androidx.tv:tv-material", version.ref = "tvComposeMaterial3" }
270+
truth = { module = "com.google.truth:truth", version.ref = "truth" }
264271
validator-push = { module = "com.google.android.wearable.watchface.validator:validator-push", version.ref = "validatorPush" }
265272
wear-compose-material = { module = "androidx.wear.compose:compose-material", version.ref = "wearComposeMaterial" }
266273
wear-compose-material3 = { module = "androidx.wear.compose:compose-material3", version.ref = "wearComposeMaterial3" }

xr/build.gradle.kts

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -70,4 +70,12 @@ dependencies {
7070

7171
implementation(libs.androidx.activity.compose)
7272
implementation(libs.androidx.appcompat)
73+
74+
testImplementation(libs.junit)
75+
testImplementation(libs.androidx.test.ext.junit)
76+
testImplementation(libs.androidx.xr.projected.testing)
77+
testImplementation(libs.truth)
78+
testImplementation(libs.robolectric)
79+
testImplementation(libs.core.ktx)
80+
testImplementation(libs.mockito.kotlin)
7381
}
Lines changed: 83 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,83 @@
1+
/*
2+
* Copyright 2025 The Android Open Source Project
3+
*
4+
* Licensed under the Apache License, Version 2.0 (the "License");
5+
* you may not use this file except in compliance with the License.
6+
* You may obtain a copy of the License at
7+
*
8+
* https://www.apache.org/licenses/LICENSE-2.0
9+
*
10+
* Unless required by applicable law or agreed to in writing, software
11+
* distributed under the License is distributed on an "AS IS" BASIS,
12+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13+
* See the License for the specific language governing permissions and
14+
* limitations under the License.
15+
*/
16+
17+
package com.example.xr.projected
18+
19+
import android.content.Context
20+
import android.os.Build
21+
import androidx.test.core.app.ApplicationProvider
22+
import androidx.test.ext.junit.runners.AndroidJUnit4
23+
import androidx.xr.projected.ProjectedContext
24+
import androidx.xr.projected.ProjectedDeviceController
25+
import androidx.xr.projected.experimental.ExperimentalProjectedApi
26+
import androidx.xr.projected.testing.ProjectedTestRule
27+
import com.google.common.truth.Truth.assertThat
28+
import kotlinx.coroutines.runBlocking
29+
import org.junit.Assert.assertThrows
30+
import org.junit.Rule
31+
import org.junit.Test
32+
import org.junit.runner.RunWith
33+
import org.robolectric.annotation.Config
34+
35+
@RunWith(AndroidJUnit4::class)
36+
@Config(sdk = [Build.VERSION_CODES.UPSIDE_DOWN_CAKE])
37+
@OptIn(ExperimentalProjectedApi::class)
38+
class ProjectedFeatureTest {
39+
// [START androidxr_projected_test_basic_setup]
40+
41+
@get:Rule
42+
val projectedTestRule = ProjectedTestRule()
43+
44+
private val context: Context
45+
get() = ApplicationProvider.getApplicationContext()
46+
47+
@Test
48+
fun testWithConnectedDevice() {
49+
val projectedContext = ProjectedContext.createProjectedDeviceContext(context)
50+
51+
assertThat(projectedContext).isNotNull()
52+
}
53+
54+
// [END androidxr_projected_test_basic_setup]
55+
56+
// [START androidxr_projected_test_device_disconnection]
57+
@Test
58+
fun testDeviceDisconnection() {
59+
// manually disconnect the device via the rule
60+
projectedTestRule.isDeviceConnected = false
61+
62+
assertThrows(IllegalStateException::class.java) {
63+
ProjectedContext.createProjectedDeviceContext(context)
64+
}
65+
}
66+
// [END androidxr_projected_test_device_disconnection]
67+
68+
// [START androidxr_projected_test_device_capabilities]
69+
@Test
70+
fun testAppBehaviorWithEmptyCapabilities() = projectedTestRule.launchTestProjectedDeviceActivity { activity ->
71+
// disable all capabilities
72+
projectedTestRule.capabilities = setOf()
73+
74+
runBlocking {
75+
// create the controller
76+
val controller = ProjectedDeviceController.create(activity)
77+
78+
// verify the app recognizes the lack of Visual UI support
79+
assertThat(controller.capabilities).doesNotContain(ProjectedDeviceController.Capability.CAPABILITY_VISUAL_UI)
80+
}
81+
}
82+
// [END androidxr_projected_test_device_capabilities]
83+
}

0 commit comments

Comments
 (0)