Skip to content

Commit

Permalink
add tests to Api
Browse files Browse the repository at this point in the history
  • Loading branch information
marandaneto committed Oct 2, 2023
1 parent 037e851 commit ff14687
Show file tree
Hide file tree
Showing 11 changed files with 204 additions and 82 deletions.
2 changes: 1 addition & 1 deletion posthog/src/main/java/com/posthog/PostHog.kt
Original file line number Diff line number Diff line change
Expand Up @@ -381,7 +381,7 @@ public class PostHog private constructor() : PostHogInterface {
@Suppress("UNCHECKED_CAST")
val groups = memoryPreferences.getValue("\$groups") as? Map<String, Any>

featureFlags?.loadFeatureFlags(distinctId, anonymousId, groups = groups, onFeatureFlags)
featureFlags?.loadFeatureFlags(distinctId, anonymousId, groups, onFeatureFlags)
}

public override fun isFeatureEnabled(key: String, defaultValue: Boolean): Boolean {
Expand Down
29 changes: 20 additions & 9 deletions posthog/src/main/java/com/posthog/internal/PostHogApi.kt
Original file line number Diff line number Diff line change
Expand Up @@ -11,12 +11,14 @@ import java.io.IOException
import java.io.OutputStream
import java.util.Date

/**
* The class that calls the PostHog API
* @property config the Config
* @property serializer the JSON Serializer
*/
internal class PostHogApi(
private val config: PostHogConfig,
private val serializer: PostHogSerializer,
private val client: OkHttpClient = OkHttpClient.Builder()
.addInterceptor(GzipRequestInterceptor(config))
.build(),
) {
private val mediaType by lazy {
try {
Expand All @@ -27,17 +29,26 @@ internal class PostHogApi(
}
}

private val client: OkHttpClient = OkHttpClient.Builder()
.addInterceptor(GzipRequestInterceptor(config))
.build()

private val theHost: String
get() {
return if (config.host.endsWith("/")) config.host.substring(0, config.host.length - 1) else config.host
}

@Throws(PostHogApiError::class, IOException::class)
fun batch(events: List<PostHogEvent>) {
val batch = PostHogBatchEvent(config.apiKey, events)

val request = makeRequest("${config.host}/batch") {
val request = makeRequest("$theHost/batch") {
batch.sentAt = Date()
serializer.serialize(batch, it.bufferedWriter())
}

client.newCall(request).execute().use {
if (!it.isSuccessful) throw PostHogApiError(it.code, it.message, body = it.body)
if (!it.isSuccessful) throw PostHogApiError(it.code, it.message, it.body)
}
}

Expand All @@ -61,16 +72,16 @@ internal class PostHogApi(
fun decide(
distinctId: String,
anonymousId: String,
groups: Map<String, Any>? = null,
groups: Map<String, Any>?,
): PostHogDecideResponse? {
val decideRequest = PostHogDecideRequest(config.apiKey, distinctId, anonymousId, groups = groups)
val decideRequest = PostHogDecideRequest(config.apiKey, distinctId, anonymousId, groups)

val request = makeRequest("${config.host}/decide/?v=3") {
val request = makeRequest("$theHost/decide/?v=3") {
serializer.serialize(decideRequest, it.bufferedWriter())
}

client.newCall(request).execute().use {
if (!it.isSuccessful) throw PostHogApiError(it.code, it.message, body = it.body)
if (!it.isSuccessful) throw PostHogApiError(it.code, it.message, it.body)

it.body?.let { body ->
return serializer.deserialize(body.charStream().buffered())
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -6,5 +6,5 @@ import java.lang.RuntimeException
internal class PostHogApiError(
val statusCode: Int,
override val message: String,
val body: ResponseBody? = null,
val body: ResponseBody?,
) : RuntimeException(message)
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ internal class PostHogDecideRequest(
apiKey: String,
distinctId: String,
anonymousId: String,
groups: Map<String, Any>? = null,
groups: Map<String, Any>?,
// add person_properties, group_properties
) : HashMap<String, Any>() {
init {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,7 @@ internal class PostHogFeatureFlags(
fun loadFeatureFlags(
distinctId: String,
anonymousId: String,
groups: Map<String, Any>? = null,
groups: Map<String, Any>?,
onFeatureFlags: PostHogOnFeatureFlags?,
) {
executor.executeSafely {
Expand All @@ -40,7 +40,7 @@ internal class PostHogFeatureFlags(
}

try {
val response = api.decide(distinctId, anonymousId, groups = groups)
val response = api.decide(distinctId, anonymousId, groups)

response?.let {
synchronized(featureFlagsLock) {
Expand Down
54 changes: 54 additions & 0 deletions posthog/src/test/java/com/posthog/Utils.kt
Original file line number Diff line number Diff line change
@@ -1,6 +1,10 @@
package com.posthog

import com.google.gson.internal.bind.util.ISO8601Utils
import java.lang.RuntimeException
import java.text.ParsePosition
import java.util.Date
import java.util.UUID
import java.util.concurrent.ExecutorService
import java.util.concurrent.TimeUnit

Expand Down Expand Up @@ -28,3 +32,53 @@ public fun ExecutorService.shutdownAndAwaitTermination() {
Thread.currentThread().interrupt()
}
}

public val date: Date = ISO8601Utils.parse("2023-09-20T11:58:49.000Z", ParsePosition(0))
public const val event: String = "event"
public const val distinctId: String = "distinctId"
public val props: Map<String, Any> = mapOf<String, Any>("prop" to "value")
public val uuid: UUID = UUID.fromString("8c04e5c1-8f6e-4002-96fd-1804799b6ffe")

public fun generateEvent(): PostHogEvent {
return PostHogEvent(
event,
distinctId = distinctId,
properties = props,
timestamp = date,
uuid = uuid,
)
}

public const val responseApi: String = """
{
"autocaptureExceptions": false,
"toolbarParams": {},
"errorsWhileComputingFlags": false,
"capturePerformance": true,
"autocapture_opt_out": false,
"isAuthenticated": false,
"supportedCompression": [
"gzip",
"gzip-js"
],
"config": {
"enable_collect_everything": true
},
"featureFlagPayloads": {
"thePayload": true
},
"featureFlags": {
"4535-funnel-bar-viz": true
},
"sessionRecording": false,
"siteApps": [
{
"id": 21039.0,
"url": "/site_app/21039/EOsOSePYNyTzHkZ3f4mjrjUap8Hy8o2vUTAc6v1ZMFP/576ac89bc8aed72a21d9b19221c2c626/"
}
],
"editorParams": {
}
}
"""
111 changes: 111 additions & 0 deletions posthog/src/test/java/com/posthog/internal/PostHogApiTest.kt
Original file line number Diff line number Diff line change
@@ -0,0 +1,111 @@
package com.posthog.internal

import com.posthog.PostHogConfig
import com.posthog.apiKey
import com.posthog.generateEvent
import com.posthog.responseApi
import okhttp3.mockwebserver.MockResponse
import okhttp3.mockwebserver.MockWebServer
import org.junit.Assert.assertThrows
import org.junit.Test
import kotlin.test.assertEquals
import kotlin.test.assertNotNull

internal class PostHogApiTest {

private fun getSut(
host: String = "https://app.posthog.com",
): PostHogApi {
val config = PostHogConfig(apiKey, host)
val serializer = PostHogSerializer(config)
return PostHogApi(config, serializer)
}

private fun mockHttp(
response: MockResponse = MockResponse()
.setBody(""),
): MockWebServer {
val mock = MockWebServer()
mock.start()
mock.enqueue(response)
return mock
}

@Test
fun `batch returns successful response`() {
val http = mockHttp()
val url = http.url("/")

val sut = getSut(host = url.toString())

val event = generateEvent()
val events = listOf(event)

sut.batch(events)

val request = http.takeRequest()

assertEquals("posthog-java/${BuildConfig.VERSION_NAME}", request.headers["User-Agent"])
assertEquals("POST", request.method)
assertEquals("/batch", request.path)
assertEquals("gzip", request.headers["Content-Encoding"])
assertEquals("gzip", request.headers["Accept-Encoding"])
assertEquals("application/json; charset=utf-8", request.headers["Content-Type"])
}

@Test
fun `batch throws if not successful`() {
val http = mockHttp(MockResponse().setResponseCode(400).setBody("error"))
val url = http.url("/")

val sut = getSut(host = url.toString())

val event = generateEvent()
val events = listOf(event)

val exc = assertThrows(PostHogApiError::class.java) {
sut.batch(events)
}
assertEquals(400, exc.statusCode)
assertEquals("Client Error", exc.message)
assertNotNull(exc.body)
}

@Test
fun `decide returns successful response`() {
val http = mockHttp(
MockResponse()
.setBody(responseApi),
)
val url = http.url("/")

val sut = getSut(host = url.toString())

val response = sut.decide("distinctId", "anonId", emptyMap())

val request = http.takeRequest()

assertNotNull(response)
assertEquals("posthog-java/${BuildConfig.VERSION_NAME}", request.headers["User-Agent"])
assertEquals("POST", request.method)
assertEquals("/decide/?v=3", request.path)
assertEquals("gzip", request.headers["Content-Encoding"])
assertEquals("gzip", request.headers["Accept-Encoding"])
assertEquals("application/json; charset=utf-8", request.headers["Content-Type"])
}

@Test
fun `decide throws if not successful`() {
val http = mockHttp(MockResponse().setResponseCode(400).setBody("error"))
val url = http.url("/")

val sut = getSut(host = url.toString())

val exc = assertThrows(PostHogApiError::class.java) {
sut.decide("distinctId", "anonId", emptyMap())
}
assertEquals(400, exc.statusCode)
assertEquals("Client Error", exc.message)
assertNotNull(exc.body)
}
}
Loading

0 comments on commit ff14687

Please sign in to comment.