diff --git a/.changeset/fresh-keys-bow.md b/.changeset/fresh-keys-bow.md new file mode 100644 index 00000000..8d03268e --- /dev/null +++ b/.changeset/fresh-keys-bow.md @@ -0,0 +1,6 @@ +--- +"posthog": patch +"posthog-android": patch +--- + +No-op SDK setup when the API key is null, empty, or whitespace after trimming. diff --git a/posthog-android/src/main/java/com/posthog/android/PostHogAndroid.kt b/posthog-android/src/main/java/com/posthog/android/PostHogAndroid.kt index 2505fb13..cf65f686 100644 --- a/posthog-android/src/main/java/com/posthog/android/PostHogAndroid.kt +++ b/posthog-android/src/main/java/com/posthog/android/PostHogAndroid.kt @@ -47,6 +47,11 @@ public class PostHogAndroid private constructor() { config: T, ) { synchronized(lock) { + if (config.apiKey.isEmpty()) { + PostHog.setup(config) + return + } + setAndroidConfig(context.appContext(), config) PostHog.setup(config) @@ -69,6 +74,10 @@ public class PostHogAndroid private constructor() { context: Context, config: T, ): PostHogInterface { + if (config.apiKey.isEmpty()) { + return PostHog.with(config) + } + setAndroidConfig(context.appContext(), config) return PostHog.with(config) } diff --git a/posthog-android/src/main/java/com/posthog/android/PostHogAndroidConfig.kt b/posthog-android/src/main/java/com/posthog/android/PostHogAndroidConfig.kt index f2302f5c..614930df 100644 --- a/posthog-android/src/main/java/com/posthog/android/PostHogAndroidConfig.kt +++ b/posthog-android/src/main/java/com/posthog/android/PostHogAndroidConfig.kt @@ -13,7 +13,7 @@ import com.posthog.android.replay.PostHogSessionReplayConfig public open class PostHogAndroidConfig @JvmOverloads constructor( - apiKey: String, + apiKey: String?, host: String = DEFAULT_HOST, public var captureApplicationLifecycleEvents: Boolean = true, public var captureDeepLinks: Boolean = true, diff --git a/posthog-android/src/test/java/com/posthog/android/PostHogAndroidConfigJavaTest.java b/posthog-android/src/test/java/com/posthog/android/PostHogAndroidConfigJavaTest.java new file mode 100644 index 00000000..c5efc48f --- /dev/null +++ b/posthog-android/src/test/java/com/posthog/android/PostHogAndroidConfigJavaTest.java @@ -0,0 +1,14 @@ +package com.posthog.android; + +import org.junit.Test; + +import static org.junit.Assert.assertEquals; + +public class PostHogAndroidConfigJavaTest { + @Test + public void nullApiKeyFromJavaDefaultsToEmptyString() { + PostHogAndroidConfig config = new PostHogAndroidConfig(null); + + assertEquals("", config.getApiKey()); + } +} diff --git a/posthog-android/src/test/java/com/posthog/android/PostHogAndroidConfigTest.kt b/posthog-android/src/test/java/com/posthog/android/PostHogAndroidConfigTest.kt index 122ba641..c2af8c12 100644 --- a/posthog-android/src/test/java/com/posthog/android/PostHogAndroidConfigTest.kt +++ b/posthog-android/src/test/java/com/posthog/android/PostHogAndroidConfigTest.kt @@ -12,6 +12,13 @@ internal class PostHogAndroidConfigTest { assertEquals(API_KEY, config.apiKey) } + @Test + fun `defaults null api key to empty string`() { + val config = PostHogAndroidConfig(null) + + assertEquals("", config.apiKey) + } + @Test fun `captureApplicationLifecycleEvents should be enabled by default`() { assertTrue(config.captureApplicationLifecycleEvents) diff --git a/posthog-android/src/test/java/com/posthog/android/PostHogAndroidTest.kt b/posthog-android/src/test/java/com/posthog/android/PostHogAndroidTest.kt index e4ab9f59..8c62fda6 100644 --- a/posthog-android/src/test/java/com/posthog/android/PostHogAndroidTest.kt +++ b/posthog-android/src/test/java/com/posthog/android/PostHogAndroidTest.kt @@ -39,6 +39,26 @@ internal class PostHogAndroidTest { tmpDir.root.deleteRecursively() } + @Test + fun `setup no-ops for null api key`() { + val config = PostHogAndroidConfig(null) + + PostHogAndroid.setup(context, config) + + assertNull(config.cachePreferences) + assertTrue(config.integrations.isEmpty()) + } + + @Test + fun `setup no-ops for empty trimmed api key`() { + val config = PostHogAndroidConfig(" \n\t ") + + PostHogAndroid.setup(context, config) + + assertNull(config.cachePreferences) + assertTrue(config.integrations.isEmpty()) + } + @Test fun `sets Android Logger if System logger`() { val config = PostHogAndroidConfig(API_KEY) diff --git a/posthog/src/main/java/com/posthog/PostHog.kt b/posthog/src/main/java/com/posthog/PostHog.kt index 82c6a68c..8994d9bb 100644 --- a/posthog/src/main/java/com/posthog/PostHog.kt +++ b/posthog/src/main/java/com/posthog/PostHog.kt @@ -101,6 +101,7 @@ public class PostHog private constructor( if (config.apiKey.isEmpty()) { config.logger.log("apiKey is empty after trimming whitespace; check your project API key") + return } if (!apiKeys.add(config.apiKey)) { diff --git a/posthog/src/main/java/com/posthog/PostHogConfig.kt b/posthog/src/main/java/com/posthog/PostHogConfig.kt index 5f6f4e61..fe57b995 100644 --- a/posthog/src/main/java/com/posthog/PostHogConfig.kt +++ b/posthog/src/main/java/com/posthog/PostHogConfig.kt @@ -31,7 +31,7 @@ public open class PostHogConfig( /** * The PostHog API Key */ - apiKey: String, + apiKey: String?, /** * The PostHog Host * Defaults to https://us.i.posthog.com @@ -328,7 +328,7 @@ public open class PostHogConfig( /** * The PostHog API Key */ - public val apiKey: String = apiKey.trim() + public val apiKey: String = apiKey?.trim().orEmpty() /** * The PostHog Host diff --git a/posthog/src/main/java/com/posthog/PostHogStateless.kt b/posthog/src/main/java/com/posthog/PostHogStateless.kt index 313163d7..ecf9e369 100644 --- a/posthog/src/main/java/com/posthog/PostHogStateless.kt +++ b/posthog/src/main/java/com/posthog/PostHogStateless.kt @@ -55,6 +55,7 @@ public open class PostHogStateless protected constructor( if (config.apiKey.isEmpty()) { config.logger.log("apiKey is empty after trimming whitespace; check your project API key") + return } if (!apiKeys.add(config.apiKey)) { diff --git a/posthog/src/test/java/com/posthog/PostHogConfigTest.kt b/posthog/src/test/java/com/posthog/PostHogConfigTest.kt index 86bd00ef..6d5f8199 100644 --- a/posthog/src/test/java/com/posthog/PostHogConfigTest.kt +++ b/posthog/src/test/java/com/posthog/PostHogConfigTest.kt @@ -23,6 +23,13 @@ internal class PostHogConfigTest { assertEquals("https://eu.i.posthog.com/", config.host) } + @Test + fun `defaults null api key to empty string`() { + val config = PostHogConfig(null, "https://api.posthog.com") + + assertEquals("", config.apiKey) + } + @Test fun `defaults a blank host after trimming whitespace`() { val config = PostHogConfig(API_KEY, " \n\t ") diff --git a/posthog/src/test/java/com/posthog/PostHogStatelessTest.kt b/posthog/src/test/java/com/posthog/PostHogStatelessTest.kt index 98f6355c..f39da0eb 100644 --- a/posthog/src/test/java/com/posthog/PostHogStatelessTest.kt +++ b/posthog/src/test/java/com/posthog/PostHogStatelessTest.kt @@ -237,13 +237,14 @@ internal class PostHogStatelessTest { } @Test - fun `setup logs empty trimmed api key after logger initialization`() { + fun `setup no-ops for empty trimmed api key after logger initialization`() { sut = createStatelessInstance() val mockLogger = MockLogger() config = PostHogConfig(" \n\t ", "https://api.posthog.com").apply { logger = mockLogger } sut.setup(config) + assertFalse(sut.isEnabledPublic()) assertTrue(mockLogger.messages.any { it.contains("apiKey is empty after trimming whitespace") }) } diff --git a/posthog/src/test/java/com/posthog/PostHogTest.kt b/posthog/src/test/java/com/posthog/PostHogTest.kt index 79b6052e..4809311a 100644 --- a/posthog/src/test/java/com/posthog/PostHogTest.kt +++ b/posthog/src/test/java/com/posthog/PostHogTest.kt @@ -126,6 +126,25 @@ internal class PostHogTest { sut.close() } + @Test + fun `setup no-ops for empty trimmed api key`() { + val config = PostHogConfig(" \n\t ", "https://api.posthog.com") + val sut = + PostHog.withInternal( + config, + queueExecutor, + replayQueueExecutor, + remoteConfigExecutor, + cachedEventsExecutor, + reloadFeatureFlags = true, + ) + + assertTrue(config.integrations.isEmpty()) + assertNull(config.cachePreferences) + + sut.close() + } + @Test fun `setup adds integration by default`() { val http = mockHttp()