Skip to content

Commit

Permalink
feat(Geo): Add Kotlin Geo Facade (#2155)
Browse files Browse the repository at this point in the history
* Add Kotlin Geo Facade

* Add return docs to the function comments

* Add tests to verify options are passed
  • Loading branch information
mattcreaser committed Dec 7, 2022
1 parent ba2fc74 commit d3c3025
Show file tree
Hide file tree
Showing 5 changed files with 353 additions and 0 deletions.
11 changes: 11 additions & 0 deletions .idea/codeStyles/Project.xml

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

Expand Up @@ -24,6 +24,7 @@ import com.amplifyframework.core.plugin.Plugin
import com.amplifyframework.kotlin.api.KotlinApiFacade
import com.amplifyframework.kotlin.auth.KotlinAuthFacade
import com.amplifyframework.kotlin.datastore.KotlinDataStoreFacade
import com.amplifyframework.kotlin.geo.KotlinGeoFacade
import com.amplifyframework.kotlin.hub.KotlinHubFacade
import com.amplifyframework.kotlin.predictions.KotlinPredictionsFacade
import com.amplifyframework.kotlin.storage.KotlinStorageFacade
Expand All @@ -41,6 +42,7 @@ class Amplify {
val Analytics = AnalyticsCategory()
val API = KotlinApiFacade()
val Auth = KotlinAuthFacade()
val Geo = KotlinGeoFacade()
val Logging = LoggingCategory()
val Storage = KotlinStorageFacade()
val Hub = KotlinHubFacade()
Expand Down
74 changes: 74 additions & 0 deletions core-kotlin/src/main/java/com/amplifyframework/kotlin/geo/Geo.kt
@@ -0,0 +1,74 @@
/*
* Copyright 2022 Amazon.com, Inc. or its affiliates. All Rights Reserved.
*
* Licensed under the Apache License, Version 2.0 (the "License").
* You may not use this file except in compliance with the License.
* A copy of the License is located at
*
* http://aws.amazon.com/apache2.0
*
* or in the "license" file accompanying this file. This file 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.amplifyframework.kotlin.geo

import com.amplifyframework.geo.models.Coordinates
import com.amplifyframework.geo.models.MapStyle
import com.amplifyframework.geo.models.MapStyleDescriptor
import com.amplifyframework.geo.options.GeoSearchByCoordinatesOptions
import com.amplifyframework.geo.options.GeoSearchByTextOptions
import com.amplifyframework.geo.options.GetMapStyleDescriptorOptions
import com.amplifyframework.geo.result.GeoSearchResult

interface Geo {
/**
* Gets a collection of maps and their corresponding styles.
*
* @return A collection of all available [MapStyle].
*/
suspend fun getAvailableMaps(): Collection<MapStyle>

/**
* Gets the default map and style from available maps.
*
* @return The default [MapStyle].
*/
suspend fun getDefaultMap(): MapStyle

/**
* Uses given options to get map style descriptor JSON.
*
* @param options Options to specify for this operation.
* @return The [MapStyleDescriptor] matching the given options.
*/
suspend fun getMapStyleDescriptor(
options: GetMapStyleDescriptorOptions = GetMapStyleDescriptorOptions.defaults()
): MapStyleDescriptor

/**
* Searches for locations that match text query.
*
* @param query Search query text.
* @param options Search options to use.
* @return The [GeoSearchResult] for the query and options.
*/
suspend fun searchByText(
query: String,
options: GeoSearchByTextOptions = GeoSearchByTextOptions.defaults()
): GeoSearchResult

/**
* Searches for location with given set of coordinates.
*
* @param position Coordinates to look-up.
* @param options Search options to use.
* @return The [GeoSearchResult] for the position and options.
*/
suspend fun searchByCoordinates(
position: Coordinates,
options: GeoSearchByCoordinatesOptions = GeoSearchByCoordinatesOptions.defaults()
): GeoSearchResult
}
@@ -0,0 +1,76 @@
/*
* Copyright 2022 Amazon.com, Inc. or its affiliates. All Rights Reserved.
*
* Licensed under the Apache License, Version 2.0 (the "License").
* You may not use this file except in compliance with the License.
* A copy of the License is located at
*
* http://aws.amazon.com/apache2.0
*
* or in the "license" file accompanying this file. This file 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.amplifyframework.kotlin.geo

import com.amplifyframework.core.Amplify
import com.amplifyframework.geo.GeoCategoryBehavior
import com.amplifyframework.geo.models.Coordinates
import com.amplifyframework.geo.models.MapStyle
import com.amplifyframework.geo.options.GeoSearchByCoordinatesOptions
import com.amplifyframework.geo.options.GeoSearchByTextOptions
import com.amplifyframework.geo.options.GetMapStyleDescriptorOptions
import kotlin.coroutines.resume
import kotlin.coroutines.resumeWithException
import kotlin.coroutines.suspendCoroutine

class KotlinGeoFacade(private val delegate: GeoCategoryBehavior = Amplify.Geo) : Geo {
override suspend fun getAvailableMaps(): Collection<MapStyle> = suspendCoroutine { continuation ->
delegate.getAvailableMaps(
{ continuation.resume(it) },
{ continuation.resumeWithException(it) }
)
}

override suspend fun getDefaultMap() = suspendCoroutine { continuation ->
delegate.getDefaultMap(
{ continuation.resume(it) },
{ continuation.resumeWithException(it) }
)
}

override suspend fun getMapStyleDescriptor(options: GetMapStyleDescriptorOptions) =
suspendCoroutine { continuation ->
delegate.getMapStyleDescriptor(
options,
{ continuation.resume(it) },
{ continuation.resumeWithException(it) }
)
}

override suspend fun searchByText(
query: String,
options: GeoSearchByTextOptions
) = suspendCoroutine { continuation ->
delegate.searchByText(
query,
options,
{ continuation.resume(it) },
{ continuation.resumeWithException(it) }
)
}

override suspend fun searchByCoordinates(
position: Coordinates,
options: GeoSearchByCoordinatesOptions
) = suspendCoroutine { continuation ->
delegate.searchByCoordinates(
position,
options,
{ continuation.resume(it) },
{ continuation.resumeWithException(it) }
)
}
}
@@ -0,0 +1,190 @@
/*
* Copyright 2022 Amazon.com, Inc. or its affiliates. All Rights Reserved.
*
* Licensed under the Apache License, Version 2.0 (the "License").
* You may not use this file except in compliance with the License.
* A copy of the License is located at
*
* http://aws.amazon.com/apache2.0
*
* or in the "license" file accompanying this file. This file 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.amplifyframework.kotlin.geo

import com.amplifyframework.core.Consumer
import com.amplifyframework.geo.GeoCategoryBehavior
import com.amplifyframework.geo.GeoException
import com.amplifyframework.geo.models.Coordinates
import com.amplifyframework.geo.models.MapStyle
import com.amplifyframework.geo.models.MapStyleDescriptor
import com.amplifyframework.geo.options.GeoSearchByCoordinatesOptions
import com.amplifyframework.geo.options.GeoSearchByTextOptions
import com.amplifyframework.geo.options.GetMapStyleDescriptorOptions
import com.amplifyframework.geo.result.GeoSearchResult
import io.mockk.every
import io.mockk.mockk
import junit.framework.Assert.assertSame
import kotlinx.coroutines.runBlocking
import org.junit.Test

/**
* Unit tests for the [KotlinGeoFacade] class.
*/
internal class KotlinGeoFacadeTest {
private val delegate = mockk<GeoCategoryBehavior>()
private val geo = KotlinGeoFacade(delegate)

@Test
fun `gets available maps`() = runBlocking {
val maps = listOf(
MapStyle("a", "b"),
MapStyle("c", "d")
)
every { delegate.getAvailableMaps(any(), any()) } answers {
val callback = firstArg<Consumer<Collection<MapStyle>>>()
callback.accept(maps)
}
val result = geo.getAvailableMaps()
assertSame(maps, result)
}

@Test(expected = GeoException::class)
fun `throws available map error`(): Unit = runBlocking {
val error = GeoException("message", "suggestion")
every { delegate.getAvailableMaps(any(), any()) } answers {
val callback = secondArg<Consumer<GeoException>>()
callback.accept(error)
}
geo.getAvailableMaps()
}

@Test
fun `gets default map`() = runBlocking {
val map = MapStyle("name", "style")
every { delegate.getDefaultMap(any(), any()) } answers {
val callback = firstArg<Consumer<MapStyle>>()
callback.accept(map)
}
val result = geo.getDefaultMap()
assertSame(map, result)
}

@Test(expected = GeoException::class)
fun `throws default map error`(): Unit = runBlocking {
val error = GeoException("message", "suggestion")
every { delegate.getDefaultMap(any(), any()) } answers {
val callback = secondArg<Consumer<GeoException>>()
callback.accept(error)
}
geo.getDefaultMap()
}

@Test
fun `returns map style descriptor`() = runBlocking {
val descriptor = MapStyleDescriptor("")
every { delegate.getMapStyleDescriptor(any(), any(), any()) } answers {
val callback = secondArg<Consumer<MapStyleDescriptor>>()
callback.accept(descriptor)
}
val result = geo.getMapStyleDescriptor()
assertSame(descriptor, result)
}

@Test
fun `returns map style descriptor with options`() = runBlocking {
val descriptor = MapStyleDescriptor("")
val options = GetMapStyleDescriptorOptions.builder().mapName("map").build()
every { delegate.getMapStyleDescriptor(options, any(), any()) } answers {
val callback = secondArg<Consumer<MapStyleDescriptor>>()
callback.accept(descriptor)
}
val result = geo.getMapStyleDescriptor(options)
assertSame(descriptor, result)
}

@Test(expected = GeoException::class)
fun `throws map style descriptor error`(): Unit = runBlocking {
val error = GeoException("message", "suggestion")
every { delegate.getMapStyleDescriptor(any(), any(), any()) } answers {
val callback = lastArg<Consumer<GeoException>>()
callback.accept(error)
}
geo.getMapStyleDescriptor()
}

@Test
fun `returns search by text result`() = runBlocking {
val query = "query"
val searchResult = GeoSearchResult.withPlaces(emptyList())
every { delegate.searchByText(query, any(), any(), any()) } answers {
val callback = thirdArg<Consumer<GeoSearchResult>>()
callback.accept(searchResult)
}
val result = geo.searchByText(query)
assertSame(searchResult, result)
}

@Test
fun `returns search by text result with options`() = runBlocking {
val query = "query"
val options = GeoSearchByTextOptions.builder().maxResults(4).build()
val searchResult = GeoSearchResult.withPlaces(emptyList())
every { delegate.searchByText(query, options, any(), any()) } answers {
val callback = thirdArg<Consumer<GeoSearchResult>>()
callback.accept(searchResult)
}
val result = geo.searchByText(query, options)
assertSame(searchResult, result)
}

@Test(expected = GeoException::class)
fun `throws search by text error`(): Unit = runBlocking {
val query = "query"
val error = GeoException("message", "suggestion")
every { delegate.searchByText(query, any(), any(), any()) } answers {
val callback = lastArg<Consumer<GeoException>>()
callback.accept(error)
}
geo.searchByText(query)
}

@Test
fun `returns search by coordinates result`() = runBlocking {
val position = Coordinates()
val searchResult = GeoSearchResult.withPlaces(emptyList())
every { delegate.searchByCoordinates(position, any(), any(), any()) } answers {
val callback = thirdArg<Consumer<GeoSearchResult>>()
callback.accept(searchResult)
}
val result = geo.searchByCoordinates(position)
assertSame(searchResult, result)
}

@Test
fun `returns search by coordinates result with options`() = runBlocking {
val position = Coordinates()
val options = GeoSearchByCoordinatesOptions.builder().maxResults(3).build()
val searchResult = GeoSearchResult.withPlaces(emptyList())
every { delegate.searchByCoordinates(position, options, any(), any()) } answers {
val callback = thirdArg<Consumer<GeoSearchResult>>()
callback.accept(searchResult)
}
val result = geo.searchByCoordinates(position, options)
assertSame(searchResult, result)
}

@Test(expected = GeoException::class)
fun `throws search by coordinates error`(): Unit = runBlocking {
val position = Coordinates()
val error = GeoException("message", "suggestion")
every { delegate.searchByCoordinates(position, any(), any(), any()) } answers {
val callback = lastArg<Consumer<GeoException>>()
callback.accept(error)
}
geo.searchByCoordinates(position)
}
}

0 comments on commit d3c3025

Please sign in to comment.