Skip to content

Commit

Permalink
add more tests
Browse files Browse the repository at this point in the history
  • Loading branch information
marandaneto committed Oct 2, 2023
1 parent b73c4b3 commit c52f885
Show file tree
Hide file tree
Showing 7 changed files with 280 additions and 19 deletions.
2 changes: 1 addition & 1 deletion posthog/api/posthog.api
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
public final class com/posthog/PostHog : com/posthog/PostHogInterface {
public static final field Companion Lcom/posthog/PostHog$Companion;
public synthetic fun <init> (Ljava/util/concurrent/ExecutorService;Lkotlin/jvm/internal/DefaultConstructorMarker;)V
public synthetic fun <init> (Ljava/util/concurrent/ExecutorService;Ljava/util/concurrent/ExecutorService;Lkotlin/jvm/internal/DefaultConstructorMarker;)V
public fun alias (Ljava/lang/String;Ljava/util/Map;)V
public fun capture (Ljava/lang/String;Ljava/lang/String;Ljava/util/Map;Ljava/util/Map;Ljava/util/Map;Ljava/util/Map;)V
public fun close ()V
Expand Down
11 changes: 8 additions & 3 deletions posthog/src/main/java/com/posthog/PostHog.kt
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,9 @@ public class PostHog private constructor(
private val queueExecutor: ExecutorService = Executors.newSingleThreadScheduledExecutor(
PostHogThreadFactory("PostHogQueueThread"),
),
private val featureFlagsExecutor: ExecutorService = Executors.newSingleThreadScheduledExecutor(
PostHogThreadFactory("PostHogFeatureFlagsThread"),
),
) : PostHogInterface {
@Volatile
private var enabled = false
Expand Down Expand Up @@ -48,7 +51,7 @@ public class PostHog private constructor(
val dateProvider = PostHogCalendarDateProvider()
val api = PostHogApi(config, serializer, dateProvider)
val queue = PostHogQueue(config, api, serializer, dateProvider, queueExecutor)
val featureFlags = PostHogFeatureFlags(config, api)
val featureFlags = PostHogFeatureFlags(config, api, featureFlagsExecutor)

// no need to lock optOut here since the setup is locked already
val optOut = config.cachePreferences?.getValue(
Expand Down Expand Up @@ -390,10 +393,11 @@ public class PostHog private constructor(
newGroups.putAll(it)
}
newGroups[type] = key
memoryPreferences.setValue("\$groups", newGroups)

capture("\$groupidentify", properties = props)

memoryPreferences.setValue("\$groups", newGroups)

if (reloadFeatureFlags) {
loadFeatureFlagsRequest(null)
}
Expand Down Expand Up @@ -522,8 +526,9 @@ public class PostHog private constructor(
internal fun <T : PostHogConfig> withInternal(
config: T,
queueExecutor: ExecutorService,
featureFlagsExecutor: ExecutorService,
): PostHogInterface {
val instance = PostHog(queueExecutor)
val instance = PostHog(queueExecutor, featureFlagsExecutor)
instance.setup(config)
return instance
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,6 @@ package com.posthog.internal
import com.posthog.PostHogConfig
import com.posthog.PostHogOnFeatureFlags
import java.util.concurrent.ExecutorService
import java.util.concurrent.Executors
import java.util.concurrent.atomic.AtomicBoolean

/**
Expand All @@ -15,7 +14,7 @@ import java.util.concurrent.atomic.AtomicBoolean
internal class PostHogFeatureFlags(
private val config: PostHogConfig,
private val api: PostHogApi,
private val executor: ExecutorService = Executors.newSingleThreadScheduledExecutor(PostHogThreadFactory("PostHogFeatureFlagsThread")),
private val executor: ExecutorService,
) {

private var isLoadingFeatureFlags = AtomicBoolean(false)
Expand Down
261 changes: 259 additions & 2 deletions posthog/src/test/java/com/posthog/PostHogTest.kt
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ package com.posthog
import com.posthog.internal.PostHogBatchEvent
import com.posthog.internal.PostHogSerializer
import com.posthog.internal.PostHogThreadFactory
import okhttp3.mockwebserver.MockResponse
import org.junit.Rule
import org.junit.rules.TemporaryFolder
import java.util.concurrent.Executors
Expand All @@ -11,14 +12,16 @@ import kotlin.test.Test
import kotlin.test.assertEquals
import kotlin.test.assertFalse
import kotlin.test.assertNotNull
import kotlin.test.assertNull
import kotlin.test.assertTrue

internal class PostHogTest {

@get:Rule
val tmpDir = TemporaryFolder()

private val queueExecutor = Executors.newSingleThreadScheduledExecutor(PostHogThreadFactory("queueExecutor"))
private val queueExecutor = Executors.newSingleThreadScheduledExecutor(PostHogThreadFactory("TestQueue"))
private val featureFlagsExecutor = Executors.newSingleThreadScheduledExecutor(PostHogThreadFactory("TestFeatureFlags"))
private val serializer = PostHogSerializer(PostHogConfig(apiKey))

fun getSut(
Expand All @@ -34,7 +37,7 @@ internal class PostHogTest {
this.optOut = optOut
this.preloadFeatureFlags = preloadFeatureFlags
}
return PostHog.withInternal(config, queueExecutor)
return PostHog.withInternal(config, queueExecutor, featureFlagsExecutor)
}

@AfterTest
Expand All @@ -60,6 +63,70 @@ internal class PostHogTest {
sut.close()
}

@Test
fun `does not capture any event if optOut`() {
val http = mockHttp()
val url = http.url("/")

val sut = getSut(url.toString(), preloadFeatureFlags = false)

sut.optOut()

sut.capture(
event,
distinctId,
props,
userProperties = userProps,
userPropertiesSetOnce = userPropsOnce,
groupProperties = groupProps,
)

queueExecutor.shutdownAndAwaitTermination()

assertEquals(0, http.requestCount)

sut.close()
}

@Test
fun `captures an event if optIn back again`() {
val http = mockHttp()
val url = http.url("/")

val sut = getSut(url.toString(), preloadFeatureFlags = false)

sut.optOut()

sut.capture(
event,
distinctId,
props,
userProperties = userProps,
userPropertiesSetOnce = userPropsOnce,
groupProperties = groupProps,
)

// do not use extension to not shutdown the executor
queueExecutor.submit {}.get()

sut.optIn()

sut.capture(
event,
distinctId,
props,
userProperties = userProps,
userPropertiesSetOnce = userPropsOnce,
groupProperties = groupProps,
)

queueExecutor.shutdownAndAwaitTermination()

assertEquals(1, http.requestCount)

sut.close()
}

@Test
fun `captures an event`() {
val http = mockHttp()
Expand Down Expand Up @@ -96,5 +163,195 @@ internal class PostHogTest {
assertEquals(userProps, theEvent.properties!!["\$set"])
assertEquals(userPropsOnce, theEvent.properties!!["\$set_once"])
assertEquals(groupProps, theEvent.properties!!["\$groups"])

sut.close()
}

@Test
fun `capture uses generated distinctId if not given`() {
val http = mockHttp()
val url = http.url("/")

val sut = getSut(url.toString(), preloadFeatureFlags = false)

sut.capture(
event,
properties = props,
userProperties = userProps,
userPropertiesSetOnce = userPropsOnce,
groupProperties = groupProps,
)

queueExecutor.shutdownAndAwaitTermination()

val request = http.takeRequest()

val content = request.body.unGzip()
val batch = serializer.deserialize<PostHogBatchEvent>(content.reader())

val theEvent = batch.batch.first()

assertNotNull(theEvent.distinctId)

sut.close()
}

@Test
fun `captures an identify event`() {
val http = mockHttp()
val url = http.url("/")

val sut = getSut(url.toString(), preloadFeatureFlags = false)

// identify triggers reloading feature flags because distinctId does not match
http.enqueue(MockResponse().setBody(responseDecideApi))
sut.identify(
distinctId,
props,
userProperties = userProps,
userPropertiesSetOnce = userPropsOnce,
)

queueExecutor.shutdownAndAwaitTermination()
featureFlagsExecutor.shutdownAndAwaitTermination()

val request = http.takeRequest()

// counting also decide api call
assertEquals(2, http.requestCount)
val content = request.body.unGzip()
val batch = serializer.deserialize<PostHogBatchEvent>(content.reader())

val theEvent = batch.batch.first()
assertEquals("\$identify", theEvent.event)
assertEquals(distinctId, theEvent.distinctId)
assertEquals("value", theEvent.properties!!["prop"] as String)
assertNotNull(theEvent.properties!!["\$anon_distinct_id"])
assertEquals(userProps, theEvent.properties!!["\$set"])
assertEquals(userPropsOnce, theEvent.properties!!["\$set_once"])

sut.close()
}

@Test
fun `captures an alias event`() {
val http = mockHttp()
val url = http.url("/")

val sut = getSut(url.toString(), preloadFeatureFlags = false)

sut.alias(
"theAlias",
props,
)

queueExecutor.shutdownAndAwaitTermination()

val request = http.takeRequest()

val content = request.body.unGzip()
val batch = serializer.deserialize<PostHogBatchEvent>(content.reader())

val theEvent = batch.batch.first()
assertEquals("\$create_alias", theEvent.event)
assertNotNull(theEvent.distinctId)
assertEquals("theAlias", theEvent.properties!!["alias"] as String)
assertEquals("value", theEvent.properties!!["prop"] as String)

sut.close()
}

@Test
fun `creates a group`() {
val http = mockHttp()
val url = http.url("/")

val sut = getSut(url.toString(), preloadFeatureFlags = false)

sut.group("theType", "theKey", groupProps)

queueExecutor.shutdownAndAwaitTermination()

val request = http.takeRequest()

val content = request.body.unGzip()
val batch = serializer.deserialize<PostHogBatchEvent>(content.reader())

val theEvent = batch.batch.first()
assertEquals("\$groupidentify", theEvent.event)
assertNotNull(theEvent.distinctId)
assertEquals("theType", theEvent.properties!!["\$group_type"] as String)
assertEquals("theKey", theEvent.properties!!["\$group_key"] as String)
assertEquals(groupProps, theEvent.properties!!["\$group_set"])
// since theres no cached groups yet
assertNull(theEvent.properties!!["\$groups"])

sut.close()
}

@Test
fun `registers a property for the next events`() {
val http = mockHttp()
val url = http.url("/")

val sut = getSut(url.toString(), preloadFeatureFlags = false)

sut.register("newRegister", true)

sut.capture(
event,
distinctId,
props,
userProperties = userProps,
userPropertiesSetOnce = userPropsOnce,
groupProperties = groupProps,
)

queueExecutor.shutdownAndAwaitTermination()

val request = http.takeRequest()

val content = request.body.unGzip()
val batch = serializer.deserialize<PostHogBatchEvent>(content.reader())

val theEvent = batch.batch.first()

assertTrue(theEvent.properties!!["newRegister"] as Boolean)

sut.close()
}

@Test
fun `unregister removes property`() {
val http = mockHttp()
val url = http.url("/")

val sut = getSut(url.toString(), preloadFeatureFlags = false)

sut.register("newRegister", true)

sut.unregister("newRegister")

sut.capture(
event,
distinctId,
props,
userProperties = userProps,
userPropertiesSetOnce = userPropsOnce,
groupProperties = groupProps,
)

queueExecutor.shutdownAndAwaitTermination()

val request = http.takeRequest()

val content = request.body.unGzip()
val batch = serializer.deserialize<PostHogBatchEvent>(content.reader())

val theEvent = batch.batch.first()

assertNull(theEvent.properties!!["newRegister"])

sut.close()
}
}
2 changes: 1 addition & 1 deletion posthog/src/test/java/com/posthog/Utils.kt
Original file line number Diff line number Diff line change
Expand Up @@ -59,7 +59,7 @@ public fun generateEvent(eventName: String? = null): PostHogEvent {
)
}

public const val responseApi: String = """
public const val responseDecideApi: String = """
{
"autocaptureExceptions": false,
"toolbarParams": {},
Expand Down
4 changes: 2 additions & 2 deletions posthog/src/test/java/com/posthog/internal/PostHogApiTest.kt
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ import com.posthog.PostHogConfig
import com.posthog.apiKey
import com.posthog.generateEvent
import com.posthog.mockHttp
import com.posthog.responseApi
import com.posthog.responseDecideApi
import okhttp3.mockwebserver.MockResponse
import org.junit.Assert.assertThrows
import kotlin.test.Test
Expand Down Expand Up @@ -67,7 +67,7 @@ internal class PostHogApiTest {
val http = mockHttp(
response =
MockResponse()
.setBody(responseApi),
.setBody(responseDecideApi),
)
val url = http.url("/")

Expand Down
Loading

0 comments on commit c52f885

Please sign in to comment.