Skip to content

Commit 779cb53

Browse files
committed
chore: added screenshot testing
1 parent 188ffa8 commit 779cb53

File tree

8 files changed

+129
-8
lines changed

8 files changed

+129
-8
lines changed

app/build.gradle.kts

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@ plugins {
33
id("kotlin-android")
44
id("com.google.android.libraries.mapsplatform.secrets-gradle-plugin")
55
alias(libs.plugins.compose.compiler)
6+
alias(libs.plugins.screenshot)
67
}
78

89
android {
@@ -46,6 +47,8 @@ android {
4647
jvmTarget = "1.8"
4748
freeCompilerArgs += "-Xopt-in=kotlin.RequiresOptIn"
4849
}
50+
51+
experimentalProperties["android.experimental.enableScreenshotTest"] = true
4952
}
5053

5154
dependencies {
@@ -68,6 +71,8 @@ dependencies {
6871
androidTestImplementation(libs.androidx.test.compose.ui)
6972
androidTestImplementation(libs.kotlinx.coroutines.test)
7073

74+
screenshotTestImplementation(libs.androidx.compose.ui.tooling)
75+
7176
// Instead of the lines below, regular apps would load these libraries from Maven according to
7277
// the README installation instructions
7378
implementation(project(":maps-compose"))
2.77 KB
Loading

app/src/main/java/com/google/maps/android/compose/ScaleBarActivity.kt

Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -31,13 +31,18 @@ import androidx.compose.foundation.layout.systemBarsPadding
3131
import androidx.compose.foundation.layout.wrapContentSize
3232
import androidx.compose.material.CircularProgressIndicator
3333
import androidx.compose.material.MaterialTheme
34+
import androidx.compose.runtime.Composable
3435
import androidx.compose.runtime.getValue
3536
import androidx.compose.runtime.mutableStateOf
3637
import androidx.compose.runtime.remember
3738
import androidx.compose.runtime.setValue
3839
import androidx.compose.ui.Alignment
3940
import androidx.compose.ui.Modifier
41+
import androidx.compose.ui.tooling.preview.Preview
4042
import androidx.compose.ui.unit.dp
43+
import com.google.android.gms.maps.model.CameraPosition
44+
import com.google.android.gms.maps.model.LatLng
45+
import com.google.maps.android.compose.theme.MapsComposeSampleTheme
4146
import com.google.maps.android.compose.widgets.DarkGray
4247
import com.google.maps.android.compose.widgets.DisappearingScaleBar
4348
import com.google.maps.android.compose.widgets.ScaleBar
@@ -126,4 +131,26 @@ class ScaleBarActivity : ComponentActivity() {
126131
}
127132
}
128133
}
134+
}
135+
136+
@Preview
137+
@Composable
138+
fun PreviewScaleBar() {
139+
val cameraPositionState = remember {
140+
CameraPositionState(
141+
position = CameraPosition(
142+
LatLng(48.137154, 11.576124), // Example coordinates: Munich, Germany
143+
12f,
144+
0f,
145+
0f
146+
)
147+
)
148+
}
149+
150+
MapsComposeSampleTheme {
151+
ScaleBar(
152+
modifier = Modifier.padding(end = 4.dp),
153+
cameraPositionState = cameraPositionState
154+
)
155+
}
129156
}

app/src/main/java/com/google/maps/android/compose/markerexamples/MarkerClusteringActivity.kt

Lines changed: 8 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -42,6 +42,7 @@ import com.google.android.gms.maps.model.CameraPosition
4242
import com.google.android.gms.maps.model.LatLng
4343
import com.google.maps.android.clustering.ClusterItem
4444
import com.google.maps.android.clustering.algo.NonHierarchicalViewBasedAlgorithm
45+
import com.google.maps.android.clustering.view.DefaultClusterRenderer
4546
import com.google.maps.android.compose.GoogleMap
4647
import com.google.maps.android.compose.MapsComposeExperimentalApi
4748
import com.google.maps.android.compose.MarkerInfoWindow
@@ -79,7 +80,8 @@ fun GoogleMapClustering() {
7980
}
8081
}
8182
Box(
82-
modifier = Modifier.fillMaxSize()
83+
modifier = Modifier
84+
.fillMaxSize()
8385
.systemBarsPadding()
8486
) {
8587
GoogleMapClustering(items = items)
@@ -158,6 +160,7 @@ private fun DefaultClustering(items: List<MyItem>) {
158160
@OptIn(MapsComposeExperimentalApi::class)
159161
@Composable
160162
private fun CustomUiClustering(items: List<MyItem>) {
163+
Log.i("","Clusteringggg")
161164
Clustering(
162165
items = items,
163166
// Optional: Handle clicks on clusters, cluster items, and cluster item info windows
@@ -181,7 +184,9 @@ private fun CustomUiClustering(items: List<MyItem>) {
181184
)
182185
},
183186
// Optional: Custom rendering for non-clustered items
184-
clusterItemContent = null
187+
clusterItemContent = null,
188+
// Optional: Customization hook for clusterManager and renderer when they're ready
189+
185190
)
186191
}
187192

@@ -218,6 +223,7 @@ fun CustomRendererClustering(items: List<MyItem>) {
218223
},
219224
clusterManager = clusterManager,
220225
)
226+
221227
SideEffect {
222228
clusterManager ?: return@SideEffect
223229
clusterManager.setOnClusterClickListener {
Lines changed: 37 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,37 @@
1+
package com.google.maps.android.compose
2+
3+
import androidx.compose.foundation.layout.padding
4+
import androidx.compose.runtime.Composable
5+
import androidx.compose.runtime.remember
6+
import androidx.compose.ui.Modifier
7+
import androidx.compose.ui.tooling.preview.Preview
8+
import androidx.compose.ui.unit.dp
9+
import com.google.android.gms.maps.model.CameraPosition
10+
import com.google.android.gms.maps.model.LatLng
11+
import com.google.maps.android.compose.theme.MapsComposeSampleTheme
12+
import com.google.maps.android.compose.widgets.ScaleBar
13+
14+
15+
class ScaleBarTest() {
16+
@Preview
17+
@Composable
18+
fun PreviewScaleBar() {
19+
val cameraPositionState = remember {
20+
CameraPositionState(
21+
position = CameraPosition(
22+
LatLng(48.137154, 11.576124), // Example coordinates: Munich, Germany
23+
12f,
24+
0f,
25+
0f
26+
)
27+
)
28+
}
29+
30+
MapsComposeSampleTheme {
31+
ScaleBar(
32+
modifier = Modifier.padding(end = 4.dp),
33+
cameraPositionState = cameraPositionState
34+
)
35+
}
36+
}
37+
}

gradle.properties

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -31,4 +31,6 @@ sonatypeToken=
3131
sonatypeTokenPassword=
3232

3333
android.nonTransitiveRClass=false
34-
android.nonFinalResIds=false
34+
android.nonFinalResIds=false
35+
36+
android.experimental.enableScreenshotTest=true

gradle/libs.versions.toml

Lines changed: 8 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,9 @@
11
[versions]
22
activitycompose = "1.9.3"
33
agp = "8.7.2"
4-
androidxtest = "1.6.1"
5-
compose-bom = "2024.10.01"
4+
androidxtest = "1.6.2"
5+
androidCore = "1.6.1"
6+
compose-bom = "2024.11.00"
67
dokka = "1.9.20"
78
espresso = "3.6.1"
89
jacoco-plugin = "0.2.1"
@@ -14,6 +15,7 @@ mapsktx = "5.1.1"
1415
mapsecrets = "2.0.1"
1516
org-jacoco-core = "0.8.11"
1617
androidx-core = "1.15.0"
18+
screenshot = "0.0.1-alpha07"
1719

1820
[libraries]
1921
android-gradle-plugin = { module = "com.android.tools.build:gradle", version.ref = "agp" }
@@ -26,10 +28,10 @@ androidx-compose-ui-preview-tooling = { module = "androidx.compose.ui:ui-tooling
2628
androidx-compose-ui-tooling = { module = "androidx.compose.ui:ui-tooling" }
2729
androidx-core = { module = "androidx.core:core-ktx", version.ref = "androidx-core" }
2830
androidx-test-compose-ui = { module = "androidx.compose.ui:ui-test-junit4" }
29-
androidx-test-core = { module = "androidx.test:core", version.ref = "androidxtest" }
31+
androidx-test-core = { module = "androidx.test:core", version.ref = "androidCore" }
3032
androidx-test-espresso = { module = "androidx.test.espresso:espresso-core", version.ref = "espresso" }
3133
androidx-test-junit-ktx = { module = "androidx.test.ext:junit-ktx", version.ref = "junitktx" }
32-
androidx-test-rules = { module = "androidx.test:rules", version.ref = "androidxtest" }
34+
androidx-test-rules = { module = "androidx.test:rules", version.ref = "androidCore" }
3335
androidx-test-runner = { module = "androidx.test:runner", version.ref = "androidxtest" }
3436
dokka-plugin = { module = "org.jetbrains.dokka:dokka-gradle-plugin", version.ref = "dokka" }
3537
jacoco-android-plugin = { module = "com.mxalbert.gradle:jacoco-android", version.ref = "jacoco-plugin", version.require = "0.2.1" }
@@ -45,4 +47,5 @@ test-junit = { module = "junit:junit", version.ref = "junit" }
4547

4648
[plugins]
4749
dokka = { id = "org.jetbrains.dokka", version.ref = "dokka" }
48-
compose-compiler = { id = "org.jetbrains.kotlin.plugin.compose", version.ref = "kotlin" }
50+
compose-compiler = { id = "org.jetbrains.kotlin.plugin.compose", version.ref = "kotlin" }
51+
screenshot = { id = "com.android.compose.screenshot", version.ref = "screenshot"}

maps-compose-utils/src/main/java/com/google/maps/android/compose/clustering/Clustering.kt

Lines changed: 41 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -126,6 +126,46 @@ public fun <T : ClusterItem> Clustering(
126126
onClusterItemInfoWindowLongClick: (T) -> Unit = { },
127127
clusterContent: @[UiComposable Composable] ((Cluster<T>) -> Unit)? = null,
128128
clusterItemContent: @[UiComposable Composable] ((T) -> Unit)? = null,
129+
) {
130+
Clustering(
131+
items = items,
132+
onClusterClick = onClusterClick,
133+
onClusterItemClick = onClusterItemClick,
134+
onClusterItemInfoWindowClick = onClusterItemInfoWindowClick,
135+
onClusterItemInfoWindowLongClick = onClusterItemInfoWindowLongClick,
136+
clusterContent = clusterContent,
137+
clusterItemContent = clusterItemContent,
138+
onClusterManager = null,
139+
)
140+
}
141+
142+
/**
143+
* Groups many items on a map based on zoom level.
144+
*
145+
* @param items all items to show
146+
* @param onClusterClick a lambda invoked when the user clicks a cluster of items
147+
* @param onClusterItemClick a lambda invoked when the user clicks a non-clustered item
148+
* @param onClusterItemInfoWindowClick a lambda invoked when the user clicks the info window of a
149+
* non-clustered item
150+
* @param onClusterItemInfoWindowLongClick a lambda invoked when the user long-clicks the info
151+
* window of a non-clustered item
152+
* @param clusterContent an optional Composable that is rendered for each [Cluster].
153+
* @param clusterItemContent an optional Composable that is rendered for each non-clustered item.
154+
* @param onClusterManager an optional lambda invoked with the clusterManager as a param when both
155+
* the clusterManager and renderer are set up, allowing callers a customization hook.
156+
*/
157+
@Composable
158+
@GoogleMapComposable
159+
@MapsComposeExperimentalApi
160+
public fun <T : ClusterItem> Clustering(
161+
items: Collection<T>,
162+
onClusterClick: (Cluster<T>) -> Boolean = { false },
163+
onClusterItemClick: (T) -> Boolean = { false },
164+
onClusterItemInfoWindowClick: (T) -> Unit = { },
165+
onClusterItemInfoWindowLongClick: (T) -> Unit = { },
166+
clusterContent: @[UiComposable Composable] ((Cluster<T>) -> Unit)? = null,
167+
clusterItemContent: @[UiComposable Composable] ((T) -> Unit)? = null,
168+
onClusterManager: ((ClusterManager<T>) -> Unit)? = null,
129169
) {
130170
val clusterManager = rememberClusterManager<T>()
131171
val renderer = rememberClusterRenderer(clusterContent, clusterItemContent, clusterManager)
@@ -142,6 +182,7 @@ public fun <T : ClusterItem> Clustering(
142182
clusterManager.setOnClusterItemClickListener(onClusterItemClick)
143183
clusterManager.setOnClusterItemInfoWindowClickListener(onClusterItemInfoWindowClick)
144184
clusterManager.setOnClusterItemInfoWindowLongClickListener(onClusterItemInfoWindowLongClick)
185+
onClusterManager?.invoke(clusterManager)
145186
}
146187

147188
if (clusterManager != null && renderer != null) {

0 commit comments

Comments
 (0)