Skip to content

Commit

Permalink
Merge pull request #735 from android/ben/google_maps
Browse files Browse the repository at this point in the history
[Crane] Update Crane to use new Google Maps library
  • Loading branch information
bentrengrove authored Feb 23, 2022
2 parents e9c7668 + e24c8f7 commit 304f0db
Show file tree
Hide file tree
Showing 8 changed files with 282 additions and 247 deletions.
2 changes: 2 additions & 0 deletions .github/workflows/Crane.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -109,6 +109,8 @@ jobs:

- name: Run instrumentation tests
uses: reactivecircus/android-emulator-runner@v2
env:
GOOGLE_MAPS_KEY: ${{ secrets.GOOGLE_MAPS_KEY }}
with:
api-level: ${{ matrix.api-level }}
target: google_apis
Expand Down
9 changes: 7 additions & 2 deletions Crane/app/build.gradle
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,11 @@ if (rootProject.file("local.properties").exists()) {
properties.load(rootProject.file("local.properties").newDataInputStream())
}

// For testing on CI, a key can also be provided via an environment variable.
// The local.properties key takes precedence
String systemGoogleMapsKey = System.getenv("GOOGLE_MAPS_KEY") ?: ""
String googleMapsKey = properties.getProperty("google.maps.key", systemGoogleMapsKey)

android {
compileSdkVersion 31
defaultConfig {
Expand All @@ -46,7 +51,7 @@ android {
}
}

manifestPlaceholders = [ googleMapsKey : properties.getProperty("google.maps.key", "") ]
manifestPlaceholders = [ googleMapsKey : googleMapsKey ]
}

signingConfigs {
Expand Down Expand Up @@ -106,7 +111,7 @@ dependencies {
implementation Libs.Kotlin.stdlib
implementation Libs.Kotlin.Coroutines.android
implementation Libs.GoogleMaps.maps
implementation Libs.GoogleMaps.mapsKtx
implementation Libs.GoogleMaps.composeMaps
constraints {
// Volley is a transitive dependency of maps
implementation(Libs.Volley.volley) {
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,131 @@
/*
* Copyright 2022 The Android Open Source Project
*
* 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
*
* https://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 androidx.compose.samples.crane.details

import androidx.compose.foundation.layout.Column
import androidx.compose.samples.crane.data.DestinationsRepository
import androidx.compose.samples.crane.data.ExploreModel
import androidx.compose.samples.crane.data.MADRID
import androidx.compose.samples.crane.home.MainActivity
import androidx.compose.samples.crane.ui.CraneTheme
import androidx.compose.ui.test.assertIsDisplayed
import androidx.compose.ui.test.junit4.createAndroidComposeRule
import androidx.compose.ui.test.onNodeWithText
import androidx.compose.ui.test.performClick
import com.google.android.gms.maps.model.LatLng
import com.google.maps.android.compose.CameraPositionState
import dagger.hilt.android.testing.HiltAndroidRule
import dagger.hilt.android.testing.HiltAndroidTest
import junit.framework.TestCase.assertEquals
import junit.framework.TestCase.assertTrue
import org.junit.Before
import org.junit.Rule
import org.junit.Test
import java.util.concurrent.CountDownLatch
import java.util.concurrent.TimeUnit
import javax.inject.Inject
import kotlin.math.pow

@HiltAndroidTest
class CityMapViewTests {
@Inject
lateinit var destinationsRepository: DestinationsRepository

private lateinit var cityDetails: ExploreModel

private val city = MADRID
private val testExploreModel = ExploreModel(city, "description", "imageUrl")

@get:Rule(order = 0)
var hiltRule = HiltAndroidRule(this)

@get:Rule(order = 1)
// Using MainActivity so we can initialise Hilt but not have to populate savedstate for
// unused viewmodels.
val composeTestRule = createAndroidComposeRule<MainActivity>()

private lateinit var mapState: CameraPositionState
private lateinit var zoomLatch: CountDownLatch

@Before
fun setUp() {
hiltRule.inject()

cityDetails = destinationsRepository.getDestination(MADRID.name)!!

val countDownLatch = CountDownLatch(1)
zoomLatch = CountDownLatch(1)

composeTestRule.setContent {
CraneTheme {
Column {
CityMapView(
latitude = testExploreModel.city.latitude,
longitude = testExploreModel.city.longitude,
onMapLoadedWithCameraState = { cameraPositionState ->
mapState = cameraPositionState
countDownLatch.countDown()
},
onZoomChanged = { zoomLatch.countDown() }
)
}
}
}

assertTrue("Map failed to load in time.", countDownLatch.await(30, TimeUnit.SECONDS))
}

@Test
fun mapView_cameraPositioned() {
val expected = LatLng(
testExploreModel.city.latitude.toDouble(),
testExploreModel.city.longitude.toDouble()
)

assertEquals(expected.latitude, mapState.position.target.latitude.round(6))
assertEquals(expected.longitude, mapState.position.target.longitude.round(6))
}

@Test
fun mapView_zoomIn() {
val zoomBefore = mapState.position.zoom
composeTestRule.onNodeWithText("+")
.assertIsDisplayed()
.performClick()

// Wait for the animation to happen
assertTrue("Zoom timed out", zoomLatch.await(30, TimeUnit.SECONDS))

assertTrue(zoomBefore < mapState.position.zoom)
}

@Test
fun mapView_zoomOut() {
val zoomBefore = mapState.position.zoom
composeTestRule.onNodeWithText("-")
.assertIsDisplayed()
.performClick()

// Wait for the animation to happen
assertTrue("Zoom timed out", zoomLatch.await(30, TimeUnit.SECONDS))

assertTrue(zoomBefore > mapState.position.zoom)
}
}

private fun Double.round(decimals: Int = 2): Double =
kotlin.math.round(this * 10f.pow(decimals)) / 10f.pow(decimals)

This file was deleted.

Original file line number Diff line number Diff line change
@@ -0,0 +1,56 @@
/*
* Copyright 2022 The Android Open Source Project
*
* 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
*
* https://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 androidx.compose.samples.crane.details

import androidx.compose.material.Surface
import androidx.compose.samples.crane.data.ExploreModel
import androidx.compose.samples.crane.data.MADRID
import androidx.compose.samples.crane.ui.CraneTheme
import androidx.compose.ui.test.assertIsDisplayed
import androidx.compose.ui.test.junit4.createComposeRule
import androidx.compose.ui.test.onNodeWithText
import androidx.test.ext.junit.runners.AndroidJUnit4
import org.junit.Before
import org.junit.Rule
import org.junit.Test
import org.junit.runner.RunWith

@RunWith(AndroidJUnit4::class)
class DetailsContentTests {
private val city = MADRID
private val testExploreModel = ExploreModel(city, "description", "imageUrl")

@get:Rule
val composeTestRule = createComposeRule()

@Before
fun setUp() {
composeTestRule.setContent {
CraneTheme {
Surface {
DetailsContent(exploreModel = testExploreModel)
}
}
}
}

@Test
fun detailsScreen_detailsDisplayed() {
composeTestRule.onNodeWithText(city.nameToDisplay).assertIsDisplayed()
composeTestRule.onNodeWithText(testExploreModel.description).assertIsDisplayed()
}
}
Loading

0 comments on commit 304f0db

Please sign in to comment.