Skip to content

Commit 4cbbd0e

Browse files
committed
fixup! feat: sendFeatureFlags config is respected
1 parent 26fda12 commit 4cbbd0e

File tree

3 files changed

+111
-4
lines changed

3 files changed

+111
-4
lines changed

posthog-server/src/main/java/com/posthog/server/PostHog.kt

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -49,8 +49,12 @@ public class PostHog : PostHogInterface {
4949
timestamp: java.util.Date?,
5050
sendFeatureFlags: PostHogSendFeatureFlagOptions?,
5151
) {
52-
val updatedProperties = mutableMapOf<String, Any>().apply {
53-
putAll(properties ?: emptyMap())
52+
val updatedProperties = if (sendFeatureFlags == null && properties == null) {
53+
null
54+
} else {
55+
mutableMapOf<String, Any>().apply {
56+
putAll(properties ?: emptyMap())
57+
}
5458
}
5559
featureFlags?.appendFlagEventProperties(distinctId, updatedProperties, groups, sendFeatureFlags)
5660
instance?.captureStateless(

posthog-server/src/main/java/com/posthog/server/internal/PostHogFeatureFlags.kt

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -555,9 +555,9 @@ internal class PostHogFeatureFlags(
555555

556556
val activeFeatureFlags = mutableListOf<String>()
557557

558-
for (featureFlag in featureFlags?.values ?: emptyList()) {
558+
for (featureFlag in featureFlags.values) {
559559
val flagValue = featureFlag.variant ?: featureFlag.enabled
560-
properties.put("\$feature/${featureFlag.key}", flagValue )
560+
properties.put("\$feature/${featureFlag.key}", flagValue)
561561
if (flagValue != false) {
562562
activeFeatureFlags.add(featureFlag.key)
563563
}

posthog-server/src/test/java/com/posthog/server/PostHogTest.kt

Lines changed: 103 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
package com.posthog.server
22

33
import com.posthog.PostHogStatelessInterface
4+
import okhttp3.mockwebserver.MockResponse
45
import org.mockito.kotlin.mock
56
import org.mockito.kotlin.verify
67
import org.mockito.kotlin.whenever
@@ -493,6 +494,108 @@ internal class PostHogTest {
493494
)
494495
}
495496

497+
@Test
498+
fun `capture with sendFeatureFlags appends flags to event properties`() {
499+
val flagsResponse =
500+
"""
501+
{
502+
"flags": {
503+
"flag1": {
504+
"key": "flag1",
505+
"enabled": true,
506+
"variant": "variant_a",
507+
"metadata": { "version": 1, "payload": null, "id": 1 },
508+
"reason": { "kind": "condition_match", "condition_match_type": "Test", "condition_index": 0 }
509+
},
510+
"flag2": {
511+
"key": "flag2",
512+
"enabled": true,
513+
"variant": null,
514+
"metadata": { "version": 1, "payload": null, "id": 2 },
515+
"reason": { "kind": "condition_match", "condition_match_type": "Test", "condition_index": 0 }
516+
},
517+
"flag3": {
518+
"key": "flag3",
519+
"enabled": false,
520+
"variant": null,
521+
"metadata": { "version": 1, "payload": null, "id": 3 },
522+
"reason": { "kind": "condition_match", "condition_match_type": "Test", "condition_index": 0 }
523+
}
524+
}
525+
}
526+
""".trimIndent()
527+
528+
val mockServer =
529+
createMockHttp(
530+
jsonResponse(flagsResponse),
531+
MockResponse().setResponseCode(200).setBody("{}"),
532+
)
533+
val url = mockServer.url("/")
534+
535+
val config = PostHogConfig(apiKey = TEST_API_KEY, host = url.toString())
536+
val postHog = PostHog()
537+
postHog.setup(config)
538+
539+
// Capture with sendFeatureFlags
540+
val sendFeatureFlagOptions =
541+
PostHogSendFeatureFlagOptions.builder()
542+
.personProperty("email", "[email protected]")
543+
.build()
544+
545+
postHog.capture(
546+
distinctId = "user123",
547+
event = "test_event",
548+
properties = mapOf("prop" to "value"),
549+
userProperties = null,
550+
userPropertiesSetOnce = null,
551+
groups = null,
552+
timestamp = null,
553+
sendFeatureFlags = sendFeatureFlagOptions,
554+
)
555+
556+
postHog.flush()
557+
558+
mockServer.takeRequest() // flags request
559+
val batchRequest = mockServer.takeRequest()
560+
561+
// Decompress the batch body if gzipped
562+
val batchBody =
563+
if (batchRequest.getHeader("Content-Encoding") == "gzip") {
564+
batchRequest.body.unGzip()
565+
} else {
566+
batchRequest.body.readUtf8()
567+
}
568+
569+
// Parse the batch request JSON
570+
val gson = com.google.gson.Gson()
571+
@Suppress("UNCHECKED_CAST")
572+
val batchData = gson.fromJson(batchBody, Map::class.java) as Map<String, Any>
573+
@Suppress("UNCHECKED_CAST")
574+
val batch = batchData["batch"] as List<Map<String, Any>>
575+
576+
assertEquals(1, batch.size)
577+
578+
val event = batch[0]
579+
assertEquals("test_event", event["event"])
580+
assertEquals("user123", event["distinct_id"])
581+
582+
@Suppress("UNCHECKED_CAST")
583+
val properties = event["properties"] as Map<String, Any>
584+
assertEquals("value", properties["prop"])
585+
assertEquals("variant_a", properties["\$feature/flag1"])
586+
assertEquals(true, properties["\$feature/flag2"])
587+
assertEquals(false, properties["\$feature/flag3"])
588+
589+
@Suppress("UNCHECKED_CAST")
590+
val activeFlags = properties["\$active_feature_flags"] as? List<String>
591+
assertEquals(2, activeFlags?.size)
592+
assertEquals(true, activeFlags?.contains("flag1"))
593+
assertEquals(true, activeFlags?.contains("flag2"))
594+
595+
mockServer.shutdown()
596+
postHog.close()
597+
}
598+
496599
@Test
497600
fun `isFeatureEnabled propagates parameters as expected`() {
498601
val mockInstance = createMockStateless()

0 commit comments

Comments
 (0)