Skip to content
This repository has been archived by the owner on Oct 14, 2022. It is now read-only.

Commit

Permalink
PMA-8087 - Add test mode that fakes HTTP calls to the Everlytic API
Browse files Browse the repository at this point in the history
  • Loading branch information
jasondantuma committed Mar 12, 2019
1 parent 1f986d2 commit 4c537ba
Show file tree
Hide file tree
Showing 19 changed files with 223 additions and 42 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -5,9 +5,13 @@ import android.util.Log
object EvLogger {

fun d(tag: String, message: String? = null, throwable: Throwable? = null) {
if (BuildConfig.DEBUG) {
// if (BuildConfig.DEBUG) {
Log.d(tag, message, throwable)
}
// }
}

fun i(tag: String, message: String? = null, throwable: Throwable? = null) {
Log.i(tag, message, throwable)
}

fun w(tag: String, message: String? = null, throwable: Throwable? = null) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -16,12 +16,14 @@ import com.everlytic.android.pushnotificationsdk.models.EverlyticNotification
/**
* Everlytic Push Notifications SDK
* */
@Suppress("unused")
public object EverlyticPush {
private const val TAG = "EverlyticPush"

@SuppressLint("StaticFieldLeak")
internal var instance: PushSdk? = null

var isInTestMode: Boolean = false
private set

/**
* Initialises the Everlytic Push EvNotification SDK
* @param context [Application] instance
Expand Down Expand Up @@ -55,7 +57,7 @@ public object EverlyticPush {
throw newInvalidSdkConfigurationException(META_PUSH_PROJECT_ID)
}

instance = PushSdk(context.applicationContext, settingsBag)
instance = PushSdk(context.applicationContext, settingsBag, testMode = isInTestMode)
}

/**
Expand Down Expand Up @@ -145,6 +147,12 @@ public object EverlyticPush {
} ?: throw newNotInitialisedException()
}

@JvmStatic
fun setInTestMode(mode: Boolean): EverlyticPush {
isInTestMode = mode
return this
}

private fun newNotInitialisedException() =
EverlyticPushNotInitialisedException(
"""
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -47,11 +47,21 @@ fun Any.logd(message: String? = null, throwable: Throwable? = null) {
EvLogger.d(this::class.java.simpleName, message, throwable)
}

@JvmOverloads
fun Any.logi(message: String? = null, throwable: Throwable? = null) {
EvLogger.i(this::class.java.simpleName, message, throwable)
}

@JvmOverloads
fun Any.logw(message: String? = null, throwable: Throwable? = null) {
EvLogger.w(this::class.java.simpleName, message, throwable)
}

@JvmOverloads
fun Any.loge(message: String? = null, throwable: Throwable? = null) {
EvLogger.e(this::class.java.simpleName, message, throwable)
}

fun Intent.isEverlyticEventIntent(): Boolean {
return this.hasExtra(EvIntentExtras.EVERLYTIC_DATA) || this.hasExtra(EvIntentExtras.ANDROID_NOTIFICATION_ID)
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@ import com.everlytic.android.pushnotificationsdk.repositories.NotificationLogRep
import com.everlytic.android.pushnotificationsdk.repositories.SdkRepository
import com.everlytic.android.pushnotificationsdk.eventreceivers.ResubscribeContactOnNetworkChangeReceiver
import com.everlytic.android.pushnotificationsdk.exceptions.EverlyticSubscriptionDelayedException
import java.net.UnknownHostException
import com.everlytic.android.pushnotificationsdk.facades.TokenResult
import java.util.*

internal class PushSdk @JvmOverloads constructor(
Expand All @@ -28,7 +28,8 @@ internal class PushSdk @JvmOverloads constructor(
)
),
private val firebaseInstanceId: FirebaseInstanceIdFacade = FirebaseInstanceIdFacade.getDefaultInstance(),
private val sdkRepository: SdkRepository = SdkRepository(context)
private val sdkRepository: SdkRepository = SdkRepository(context),
private val testMode: Boolean = false
) {

init {
Expand All @@ -45,22 +46,24 @@ internal class PushSdk @JvmOverloads constructor(
ResubscribeContactOnNetworkChangeReceiver(),
IntentFilter("android.net.conn.CONNECTIVITY_CHANGE")
)

if (testMode) {
logi("Everlytic Push SDK initialized with testMode=$testMode")
}
}

fun subscribeContact(email: String, onComplete: (EvResult) -> Unit) {
logd("::subscribeContact() email=$email onComplete=$onComplete")
val deviceType = if (context.resources.getBoolean(R.bool.isTablet)) "tablet" else "handset"
val device = DeviceData(sdkRepository.getDeviceId()!!, type = deviceType)
firebaseInstanceId.getInstanceId { tokenResult ->
logd("::subscribeContact() firebaseInstanceId->tokenResult=$tokenResult")
if (tokenResult.success) {
val contactData = ContactData(email, tokenResult.value!!)
val subscription = SubscriptionEvent(settingsBag.listId.toString(), contactData, device = device)

if (tokenResult.success && !tokenResult.value.isNullOrBlank()) {
val subscription = createSubscriptionEvent(email, tokenResult.value)

logd("::subscribeContact() subscription=$subscription")

if (isDeviceOnline(context)) {
api.subscribe(subscription, object : EverlyticHttp.ResponseHandler {
val responseHandler = object : EverlyticHttp.ResponseHandler {
override fun onSuccess(response: ApiResponse?) {
logd("::onSuccess() response=$response")
val responseObject = JSONAdapter.decodeAs(ApiSubscription::class.java, response!!.data)
Expand All @@ -78,7 +81,15 @@ internal class PushSdk @JvmOverloads constructor(
)
)
}
})
}

if (testMode) {
logi("Push Notification Token: ${tokenResult.value}")
responseHandler.onSuccess(Testing_ApiResponses.subscribeSuccess(sdkRepository.getDeviceId()!!))
} else {
api.subscribe(subscription, responseHandler)
}

} else {
sdkRepository.setContactEmail(email)
sdkRepository.setNewFcmToken(tokenResult.value)
Expand All @@ -93,14 +104,11 @@ internal class PushSdk @JvmOverloads constructor(

internal fun resubscribeUserWithToken(email: String, token: String, onComplete: (EvResult) -> Unit) {
logd("::resubscribeUserWithToken() email=$email token=$token onComplete=$onComplete")
val deviceType = if (context.resources.getBoolean(R.bool.isTablet)) "tablet" else "handset"
val device = DeviceData(sdkRepository.getDeviceId()!!, type = deviceType)
val contactData = ContactData(email, token)
val subscription = SubscriptionEvent(settingsBag.listId.toString(), contactData, device = device)
val subscription = createSubscriptionEvent(email, token)

logd("::resubscribeUserWithToken() subscription=$subscription")

api.subscribe(subscription, object : EverlyticHttp.ResponseHandler {
val responseHandler = object : EverlyticHttp.ResponseHandler {
override fun onSuccess(response: ApiResponse?) {
logd("::onSuccess() response=$response")
val responseObject = JSONAdapter.decodeAs(ApiSubscription::class.java, response!!.data)
Expand All @@ -119,7 +127,13 @@ internal class PushSdk @JvmOverloads constructor(
)
)
}
})
}

if (testMode) {
responseHandler.onSuccess(Testing_ApiResponses.subscribeSuccess(sdkRepository.getDeviceId()!!))
} else {
api.subscribe(subscription, responseHandler)
}
}

internal fun resubscribeIfRequired() {
Expand All @@ -145,7 +159,7 @@ internal class PushSdk @JvmOverloads constructor(
deviceId?.let { deviceId ->
subscriptionId?.let { subscriptionId ->
val unsubscribeEvent = UnsubscribeEvent(subscriptionId, deviceId)
api.unsubscribe(unsubscribeEvent, object : EverlyticHttp.ResponseHandler {
val responseHandler = object : EverlyticHttp.ResponseHandler {
override fun onSuccess(response: ApiResponse?) {
sdkRepository.removeContactSubscription()
onComplete?.invoke(EvResult(true))
Expand All @@ -154,7 +168,12 @@ internal class PushSdk @JvmOverloads constructor(
override fun onFailure(code: Int, response: String?, throwable: Throwable?) {
onComplete?.invoke(EvResult(false, throwable ?: Exception("An API Exception occurred")))
}
})
}
if (testMode) {
responseHandler.onSuccess(Testing_ApiResponses.unsubscribeSuccess())
} else {
api.unsubscribe(unsubscribeEvent, responseHandler)
}
} ?: onComplete?.invoke(EvResult(false, EverlyticNotSubscribedException("No subscription to unsubscribe.")))
} ?: onComplete?.invoke(EvResult(false, Exception("No device ID set.")))

Expand All @@ -177,6 +196,16 @@ internal class PushSdk @JvmOverloads constructor(
}

internal fun isContactSubscribed(): Boolean {
return sdkRepository.getSubscriptionId() != null && sdkRepository.getContactId() != null
return sdkRepository.getHasSubscription()
}

private fun createSubscriptionEvent(
email: String,
token: String
): SubscriptionEvent {
val deviceType = if (context.resources.getBoolean(R.bool.isTablet)) "tablet" else "handset"
val device = DeviceData(sdkRepository.getDeviceId()!!, type = deviceType)
val contactData = ContactData(email, token)
return SubscriptionEvent(settingsBag.listId.toString(), contactData, device = device)
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,6 @@ internal object SdkSettings {
.packageManager
.getApplicationInfo(context.packageName, PackageManager.GET_META_DATA)


return SdkSettingsBag(
appInfo.metaData.getString(SdkSettings.META_API_INSTALL_URL),
appInfo.metaData.getString(SdkSettings.META_API_USERNAME_PATH),
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
package com.everlytic.android.pushnotificationsdk

import com.everlytic.android.pushnotificationsdk.models.ApiResponse
import com.everlytic.android.pushnotificationsdk.models.ApiSubscription
import com.everlytic.android.pushnotificationsdk.models.jsonadapters.JSONAdapter
import org.json.JSONObject
import java.security.SecureRandom

object Testing_ApiResponses {

private fun randId() = SecureRandom().nextInt(10000).toString()

fun subscribeSuccess(deviceId: String) : ApiResponse {
val sub = ApiSubscription(
randId(),
randId(),
randId(),
randId(),
deviceId
)
return ApiResponse("success", JSONAdapter.encode(sub))
}

fun unsubscribeSuccess() : ApiResponse {
return ApiResponse("success", JSONObject())
}

}
Original file line number Diff line number Diff line change
Expand Up @@ -38,8 +38,7 @@ class EvDbHelper(context: Context) : SQLiteOpenHelper(context, DB_NAME, null, DB
)

val SQL_INDEXES_CREATE = arrayOf(
EvDbContract.NotificationEventsLogTable.INDEX_CREATE_EVENT_TYPE,
EvDbContract.NotificationEventsLogTable.INDEX_CREATE_IS_UPLOADED_EVENT_TYPE
EvDbContract.NotificationEventsLogTable.INDEX_CREATE_EVENT_TYPE
)

var instance: EvDbHelper? = null
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -6,13 +6,15 @@ import android.content.Intent
import com.everlytic.android.pushnotificationsdk.EverlyticPush
import com.everlytic.android.pushnotificationsdk.isDeviceOnline
import com.everlytic.android.pushnotificationsdk.logd
import com.everlytic.android.pushnotificationsdk.workers.UploadMessageEventsService

class ResubscribeContactOnNetworkChangeReceiver : BroadcastReceiver() {
override fun onReceive(context: Context, intent: Intent) {
logd("::onReceive() activeNetwork.isConnected=${isDeviceOnline(context)}")

if (isDeviceOnline(context)) {
EverlyticPush.instance?.resubscribeIfRequired()
UploadMessageEventsService.enqueue(context)
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -3,22 +3,30 @@ package com.everlytic.android.pushnotificationsdk.workers
import android.content.ComponentName
import android.content.Context
import android.content.Intent
import com.everlytic.android.pushnotificationsdk.EverlyticPush
import com.everlytic.android.pushnotificationsdk.SdkSettings
import com.everlytic.android.pushnotificationsdk.database.EvDbHelper
import com.everlytic.android.pushnotificationsdk.database.NotificationEventType
import com.everlytic.android.pushnotificationsdk.isDeviceOnline
import com.everlytic.android.pushnotificationsdk.logw
import com.everlytic.android.pushnotificationsdk.models.ApiResponse
import com.everlytic.android.pushnotificationsdk.models.NotificationEvent
import com.everlytic.android.pushnotificationsdk.network.EverlyticApi
import com.everlytic.android.pushnotificationsdk.network.EverlyticHttp
import com.everlytic.android.pushnotificationsdk.repositories.NotificationEventRepository
import com.everlytic.android.pushnotificationsdk.repositories.SdkRepository
import org.json.JSONObject

class UploadMessageEventsService : JobIntentService() {
private lateinit var repository: NotificationEventRepository
private lateinit var api: EverlyticApi

override fun onHandleWork(intent: Intent) {

if (! isDeviceOnline(applicationContext)) {
return
}

val sdkSettings = SdkSettings.getSettings(applicationContext)

repository = NotificationEventRepository(
Expand Down Expand Up @@ -62,6 +70,12 @@ class UploadMessageEventsService : JobIntentService() {
event: NotificationEvent,
responseHandler: EverlyticHttp.ResponseHandler
) {

if (EverlyticPush.isInTestMode) {
responseHandler.onSuccess(ApiResponse("success", JSONObject()))
return
}

return when (eventType) {
NotificationEventType.CLICK -> api.recordClickEvent(event, responseHandler)
NotificationEventType.DELIVERY -> api.recordDeliveryEvent(event, responseHandler)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -192,16 +192,14 @@ class PushSdkTest {
)

assertTrue { sdk.isContactSubscribed() }
verify { mockSdkRepo.getSubscriptionId() }
verify { mockSdkRepo.getContactId() }
verify { mockSdkRepo.getHasSubscription() }
}

@Test
fun testIsContactSubscribed_NullSubscriptionId_ReturnsFalse() {

val mockSdkRepo = mockSdkRepository().apply {
every { getSubscriptionId() } returns null
every { getContactId() } returns 10
every { getHasSubscription() } returns false
}

val sdk = spyk(
Expand All @@ -215,14 +213,13 @@ class PushSdkTest {
)

assertFalse { sdk.isContactSubscribed() }
verify { mockSdkRepo.getSubscriptionId() }
verify { mockSdkRepo.getHasSubscription() }
}

@Test
fun testIsContactSubscribed_NullContactId_ReturnsFalse() {
val mockSdkRepo = mockSdkRepository().apply {
every { getSubscriptionId() } returns 1
every { getContactId() } returns null
every { getHasSubscription() } returns false
}

val sdk = spyk(
Expand All @@ -236,7 +233,6 @@ class PushSdkTest {
)

assertFalse { sdk.isContactSubscribed() }
verify { mockSdkRepo.getContactId() }
}

private fun mockContext(): Context {
Expand Down
3 changes: 2 additions & 1 deletion sandboxapp/build.gradle
Original file line number Diff line number Diff line change
Expand Up @@ -38,9 +38,10 @@ dependencies {

// implementation 'com.google.firebase:firebase-core:16.0.5'

implementation 'com.android.support:design:27.1.1'
testImplementation 'junit:junit:4.12'
androidTestImplementation 'androidx.test:runner:1.1.1-alpha01'
androidTestImplementation 'androidx.test.espresso:espresso-core:3.1.1-alpha01'
}

apply plugin: 'com.google.gms.google-services'
apply plugin: 'com.google.gms.google-services'
Loading

0 comments on commit 4c537ba

Please sign in to comment.