Skip to content

Commit

Permalink
UN trace tool compose test framework and cursory test case. (#561)
Browse files Browse the repository at this point in the history
* UN trace tool compose test framework and cursory test case.

* change name of test to be more descriptive. remove unnecessary annotation.

* use TraceState in tests, not anonymous object

* remove unnecessary function

---------

Co-authored-by: Soren Roth <sor10874@esri.com>
  • Loading branch information
2 people authored and puneet-pdx committed Nov 6, 2024
1 parent ab9e034 commit cb82461
Show file tree
Hide file tree
Showing 7 changed files with 168 additions and 98 deletions.
26 changes: 17 additions & 9 deletions toolkit/utilitynetworks/build.gradle.kts
Original file line number Diff line number Diff line change
Expand Up @@ -16,14 +16,19 @@
*
*/


plugins {
alias(libs.plugins.binary.compatibility.validator) apply true
id("com.android.library")
id("org.jetbrains.kotlin.android")
id("org.jetbrains.kotlin.plugin.compose")
id("artifact-deploy")
id("com.google.android.libraries.mapsplatform.secrets-gradle-plugin")
alias(libs.plugins.binary.compatibility.validator) apply true
}

secrets {
defaultPropertiesFileName = "secrets.defaults.properties"
}

android {
namespace = "com.arcgismaps.toolkit.utilitynetworks"
compileSdk = libs.versions.compileSdk.get().toInt()
Expand All @@ -50,14 +55,15 @@ android {
}
buildFeatures {
compose = true
buildConfig = true
}

kotlin {
compilerOptions {
if ("Test" !in this.moduleName.get()) {
freeCompilerArgs.add("-Xexplicit-api=strict")
}

// If this were not an android project, we would just write `explicitApi()` in the Kotlin scope.
// but as an android project could write `freeCompilerArgs = listOf("-Xexplicit-api=strict")`
// in the kotlinOptions above, but that would enforce api rules on the test code, which we don't want.
tasks.withType<org.jetbrains.kotlin.gradle.tasks.KotlinCompile> {
if ("Test" !in name) {
kotlinOptions.freeCompilerArgs += "-Xexplicit-api=strict"
}
}

Expand Down Expand Up @@ -100,6 +106,8 @@ dependencies {
implementation(libs.androidx.activity.compose)
implementation(libs.androidx.compose.navigation)
testImplementation(libs.bundles.unitTest)
androidTestImplementation(libs.truth)
androidTestImplementation(platform(libs.androidx.compose.bom))
androidTestImplementation(libs.bundles.composeTest)
debugImplementation(libs.bundles.debug)
}

This file was deleted.

Original file line number Diff line number Diff line change
@@ -0,0 +1,70 @@
/*
* Copyright 2024 Esri
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/

package com.arcgismaps.toolkit.utilitynetworks

import com.arcgismaps.ArcGISEnvironment
import com.arcgismaps.httpcore.authentication.TokenCredential
import com.arcgismaps.mapping.ArcGISMap
import com.arcgismaps.mapping.PortalItem
import com.arcgismaps.portal.Portal
import kotlinx.coroutines.test.TestScope
import kotlinx.coroutines.test.runTest
import org.junit.Before

/**
* A test runner for utility network tests. This class is responsible for loading the map with the
* given [url] and the first UtilityNetwork
* If the map fails to load or the UtilityNetwork is not found, the test will fail.
*
* @property url The URL of the web map.
* @property itemId the item id on agol to load as a webmap
* @since 200.6.0
*/
open class TraceToolTestRunner(
private val url: String,
private val itemId: String
) {
/**
* The trace tool TraceState object
*/
private var _traceState: TraceState? = null
internal val traceState: TraceState
get() = _traceState ?: throw IllegalStateException("trace state is not initialized")

@Before
fun setup(): Unit = runTest {
// If the utility network is already initialized, return
if (_traceState != null) return@runTest
// Set the authentication challenge handler
val tokenCred =
TokenCredential.create(
url,
username = BuildConfig.traceToolUser,
password = BuildConfig.traceToolPassword
).getOrThrow()

ArcGISEnvironment.authenticationManager.arcGISCredentialStore.add(tokenCred)

val map = ArcGISMap(
PortalItem(
Portal.arcGISOnline(connection = Portal.Connection.Anonymous),
itemId
)
)
_traceState = TraceState(map, coroutineScope = TestScope())
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,65 @@
/*
*
* Copyright 2024 Esri
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*
*/

package com.arcgismaps.toolkit.utilitynetworks

import androidx.compose.ui.test.junit4.createComposeRule
import androidx.compose.ui.test.onNodeWithContentDescription
import androidx.test.ext.junit.runners.AndroidJUnit4
import kotlinx.coroutines.test.runTest
import org.junit.Before
import org.junit.Rule
import org.junit.Test
import org.junit.runner.RunWith

/**
* Instrumented test, which will execute on an Android device.
*
* See [testing documentation](http://d.android.com/tools/testing).
*/
@RunWith(AndroidJUnit4::class)
class TraceToolTests : TraceToolTestRunner(
url = "https://sampleserver7.arcgisonline.com/portal/sharing/rest",
itemId = "471eb0bf37074b1fbb972b1da70fb310"
) {

@get:Rule
val composeTestRule = createComposeRule()

@Before
fun setContent() = runTest {
composeTestRule.setContent {
Trace(
traceState = traceState
)
}
}

/**
* Given a Trace composable
* When it is rendered
* Then the top level Surface exists
*
* @since 200.6.0
*/
@Test
fun testTraceToolSurface() {
val surface = composeTestRule.onNodeWithContentDescription(traceSurfaceContentDescription)
surface.assertExists("the base surface of the Trace tool composable does not exist")
}
}
2 changes: 1 addition & 1 deletion toolkit/utilitynetworks/src/main/AndroidManifest.xml
Original file line number Diff line number Diff line change
Expand Up @@ -18,5 +18,5 @@
-->

<manifest xmlns:android="http://schemas.android.com/apk/res/android">

<uses-permission android:name="android.permission.INTERNET"/>
</manifest>
Original file line number Diff line number Diff line change
Expand Up @@ -25,11 +25,15 @@ import androidx.compose.material3.Surface
import androidx.compose.runtime.Composable
import androidx.compose.ui.Alignment
import androidx.compose.ui.Modifier
import androidx.compose.ui.semantics.contentDescription
import androidx.compose.ui.semantics.semantics
import androidx.compose.ui.unit.dp
import androidx.lifecycle.compose.collectAsStateWithLifecycle
import androidx.navigation.compose.rememberNavController
import com.arcgismaps.toolkit.utilitynetworks.ui.TraceNavHost

internal const val traceSurfaceContentDescription: String = "trace component surface"

/**
* A composable UI component to set up and run a [com.arcgismaps.utilitynetworks.UtilityNetwork.trace]
* on a [com.arcgismaps.toolkit.geoviewcompose.MapView].
Expand All @@ -40,29 +44,26 @@ import com.arcgismaps.toolkit.utilitynetworks.ui.TraceNavHost
public fun Trace(
traceState: TraceState,
@Suppress("unused_parameter")
modifier: Modifier = Modifier,
modifier: Modifier = Modifier
) {
val configs = traceState.traceConfigurations.collectAsStateWithLifecycle()
// if the traceConfigurations are not available, that means the traceState is not ready so return
if (configs.value == null) {
Surface(modifier = Modifier.fillMaxSize()) {

Surface(
color = MaterialTheme.colorScheme.surface,
modifier = Modifier
.fillMaxSize()
.semantics { contentDescription = traceSurfaceContentDescription }
) {
if (configs.value == null) {
Box(
modifier = Modifier
.size(100.dp),
contentAlignment = Alignment.Center
) {
CircularProgressIndicator()
}
}
} else {

val navController = rememberNavController()

Surface(
color = MaterialTheme.colorScheme.surface,
modifier = Modifier
.fillMaxSize()
) {
} else {
val navController = rememberNavController()
TraceNavHost(navController, traceState)
}
}
Expand Down

This file was deleted.

0 comments on commit cb82461

Please sign in to comment.