Skip to content

Commit

Permalink
feat/Tests for specifying push resources by name
Browse files Browse the repository at this point in the history
  • Loading branch information
michaela-dev committed Jul 12, 2021
1 parent 52583b0 commit e4c12a6
Show file tree
Hide file tree
Showing 4 changed files with 116 additions and 21 deletions.
53 changes: 35 additions & 18 deletions android/src/main/java/com/exponea/ConfigurationParser.kt
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ import com.exponea.sdk.models.EventType
import com.exponea.sdk.models.ExponeaConfiguration
import com.exponea.sdk.models.ExponeaProject
import com.facebook.react.bridge.ReadableMap
import java.lang.NumberFormatException

internal class ConfigurationParser(private val readableMap: ReadableMap) {
private val configuration = ExponeaConfiguration()
Expand Down Expand Up @@ -63,7 +64,7 @@ internal class ConfigurationParser(private val readableMap: ReadableMap) {
}
}

fun parse(context: Context?): ExponeaConfiguration {
fun parse(context: Context? = null): ExponeaConfiguration {
val map = readableMap.toHashMapRecursively()
requireProjectAndAuthorization(map)
map.forEach { entry ->
Expand Down Expand Up @@ -95,7 +96,10 @@ internal class ConfigurationParser(private val readableMap: ReadableMap) {
"sessionTimeout" ->
configuration.sessionTimeout = map.getSafely("sessionTimeout", Double::class)
"automaticSessionTracking" ->
configuration.automaticSessionTracking = map.getSafely("automaticSessionTracking", Boolean::class)
configuration.automaticSessionTracking = map.getSafely(
"automaticSessionTracking",
Boolean::class
)
"pushTokenTrackingFrequency" -> {
try {
val stringValue = map.getSafely("pushTokenTrackingFrequency", String::class)
Expand Down Expand Up @@ -127,11 +131,14 @@ internal class ConfigurationParser(private val readableMap: ReadableMap) {
map.getSafely("automaticPushNotifications", Boolean::class)
"pushIconResourceName" -> {
val resourceName = map.getSafely("pushIconResourceName", String::class)
var id: Int? = context?.resources?.getIdentifier(resourceName, "drawable", context.packageName)
var id: Int? = context?.resources?.getIdentifier(
resourceName,
"drawable",
context.packageName
)
if (id == null || id == 0) {
//try to find resource in mipmap if not present in drawable folder
// try to find resource in mipmap if not present in drawable folder
id = context?.resources?.getIdentifier(resourceName, "mipmap", context.packageName)

}
if (id != null && id > 0) {
configuration.pushIcon = id
Expand All @@ -142,20 +149,31 @@ internal class ConfigurationParser(private val readableMap: ReadableMap) {
"pushAccentColor" ->
configuration.pushAccentColor = map.getSafely("pushAccentColor", Double::class).toInt()
"pushAccentColorRGBA" -> {
val channels = parseRGBA(map.getSafely("pushAccentColorRGBA", String::class))
if (channels.size == 4) {
configuration.pushAccentColor = Color.argb(channels[3], channels[0], channels[0], channels[2])
} else throw ExponeaModule.ExponeaDataException(
"Incorrect value '${entry.value}' for key ${entry.key}."
)
try {
val channels = parseRGBA(map.getSafely("pushAccentColorRGBA", String::class))
if (channels.size == 4) {
configuration.pushAccentColor = Color.argb(
channels[3],
channels[0],
channels[1],
channels[2]
)
} else throw ExponeaModule.ExponeaDataException(
"Incorrect value '${entry.value}' for key ${entry.key}."
)
} catch (ex: NumberFormatException) {
throw ExponeaModule.ExponeaDataException(
"Incorrect value '${entry.value}' for key ${entry.key}."
)
}
}
"pushAccentColorName" -> {
val colorName = map.getSafely("pushAccentColorName", String::class)
val resources = context?.resources
val id: Int? = resources?.getIdentifier(colorName, "color", context.packageName)
if (id != null && id > 0) {
configuration.pushAccentColor = ResourcesCompat.getColor(resources, id, null)
}
val colorName = map.getSafely("pushAccentColorName", String::class)
val resources = context?.resources
val id: Int? = resources?.getIdentifier(colorName, "color", context.packageName)
if (id != null && id > 0) {
configuration.pushAccentColor = ResourcesCompat.getColor(resources, id, null)
}
}
"pushChannelName" ->
configuration.pushChannelName = map.getSafely("pushChannelName", String::class)
Expand Down Expand Up @@ -195,6 +213,5 @@ internal class ConfigurationParser(private val readableMap: ReadableMap) {
val channel = it.trim()
channel.toInt()
}

}
}
70 changes: 70 additions & 0 deletions android/src/test/java/com/exponea/ConfigurationParserTest.kt
Original file line number Diff line number Diff line change
@@ -1,16 +1,26 @@
package com.exponea

import android.app.NotificationManager
import android.graphics.Color
import androidx.test.core.app.ApplicationProvider
import com.exponea.sdk.models.EventType
import com.exponea.sdk.models.ExponeaConfiguration
import com.exponea.sdk.models.ExponeaProject
import com.facebook.react.bridge.JavaOnlyMap
import com.facebook.react.bridge.ReadableMap
import io.mockk.every
import io.mockk.mockkStatic
import java.io.File
import org.junit.Assert.assertEquals
import org.junit.Assert.assertNull
import org.junit.Assert.fail
import org.junit.Test
import org.junit.runner.RunWith
import org.robolectric.RobolectricTestRunner
import org.robolectric.annotation.Config

@RunWith(RobolectricTestRunner::class)
@Config(manifest = Config.NONE)
internal class ConfigurationParserTest {
@Test
fun `should parse minimal configuration`() {
Expand Down Expand Up @@ -82,4 +92,64 @@ internal class ConfigurationParserTest {
assertEquals("Incorrect type for key 'projectToken'. Expected String got Double", e.message)
}
}

@Test
fun `should figure out color from RGBA channels correctly`() {
val data = JavaOnlyMap.of(
"projectToken", "mock-project-token",
"authorizationToken", "mock-authorization-token",
"baseUrl", "http://mock-base-url.xxx",
"android", JavaOnlyMap.of("pushAccentColorRGBA", "100, 100, 90, 150"))

mockkStatic("android.graphics.Color")
every { Color.argb(150, 100, 100, 90) } returns 123

assertEquals(
ExponeaConfiguration(
projectToken = "mock-project-token",
authorization = "Token mock-authorization-token",
baseURL = "http://mock-base-url.xxx",
pushAccentColor = 123
),
ConfigurationParser(data as ReadableMap).parse()
)
}

@Test
fun `should provide error on wrong color format`() {
val data = JavaOnlyMap.of(
"projectToken", "mock-project-token",
"authorizationToken", "mock-authorization-token",
"baseUrl", "http://mock-base-url.xxx",
"android", JavaOnlyMap.of("pushAccentColorRGBA", "100, text, 90, 150, &"))
try {
mockkStatic("android.graphics.Color")
ConfigurationParser(data as ReadableMap).parse()
fail("Should throw exception")
} catch (e: Exception) {
assertEquals("Incorrect value '100, text, 90, 150, &' for key pushAccentColorRGBA.", e.message)
}
}

@Test
fun `should not fail when color not found in resources`() {
val data = JavaOnlyMap.of(
"projectToken", "mock-project-token",
"authorizationToken", "mock-authorization-token",
"baseUrl", "http://mock-base-url.xxx",
"android", JavaOnlyMap.of("pushAccentColorName", "my_color"))
val config = ConfigurationParser(data as ReadableMap).parse(ApplicationProvider.getApplicationContext())
assertNull(config.pushAccentColor)
}

@Test
fun `should not fail when icon not found in resources`() {
val data = JavaOnlyMap.of(
"projectToken", "mock-project-token",
"authorizationToken", "mock-authorization-token",
"baseUrl", "http://mock-base-url.xxx",
"android", JavaOnlyMap.of("pushIconResourceName", "my_icon"))
val config = ConfigurationParser(data as ReadableMap).parse(ApplicationProvider.getApplicationContext())
assertNull(config.pushIcon)
}
}
10 changes: 9 additions & 1 deletion documentation/CONFIGURATION.md
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@

# Configuration
Before using most of the SDK functionality, you'll need to configure Exponea to connect it to backend application.

Expand Down Expand Up @@ -74,7 +75,14 @@ You can see the Typescript definition for Configuration object at [src/Configura

* **pushIcon** Android resource id of the icon to be used for push notifications.

* **pushAccentColor** Accent color of push notification icon and buttons
* **pushIconResourceName** Android resource name of the icon to be used for push notifications. For example, if file `push_icon.png` is placed in your drawable of mipmap resources folder, use the filename without extension as a value.

* **pushAccentColor** Accent color of push notification icon and buttons, specified as Color ARGB integer

* **pushAccentColorRGBA** Accent color of push notification icon and buttons, specified by RGBA channels separated by comma. For example, to use the colour blue, the string `"0, 0, 255, 255"` should be entered.

* **pushAccentColorName** Accent color of push notification icon and buttons, specified by resource name. Any color defined in R class can be used. For example, if you defined your color as a resource
`<color name="push_accent_color">#0000ff</color>`, use `push_accent_color` as a value for this parameter.

* **pushChannelName?** Channel name for push notifications. Only for API level 26+

Expand Down
4 changes: 2 additions & 2 deletions example/src/App.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -86,8 +86,8 @@ export default class App extends React.Component<{}, AppState> {
},
android: {
pushIconResourceName: 'push_icon',
pushAccentColorRGBA: '161, 226, 200, 220'
}
pushAccentColorRGBA: '161, 226, 200, 220',
},
})
.then(() => {
this.setState({sdkConfigured: true});
Expand Down

0 comments on commit e4c12a6

Please sign in to comment.