From f944b6e74cecf1b79fcf038624b99edf36afa445 Mon Sep 17 00:00:00 2001 From: novakzaballa Date: Tue, 13 Aug 2024 15:08:45 -0400 Subject: [PATCH 01/21] feat: Support transient identities and traits --- .../src/main/java/com/flagsmith/Flagsmith.kt | 18 ++++--- .../flagsmith/entities/IdentityAndTraits.kt | 3 +- .../entities/IdentityFlagsAndTraits.kt | 3 +- .../main/java/com/flagsmith/entities/Trait.kt | 36 +++++++------ .../internal/FlagsmithRetrofitService.kt | 2 +- .../com/flagsmith/SynchronousFlagsmith.kt | 8 +-- .../test/java/com/flagsmith/TraitsTests.kt | 54 ++++++++++++++++--- .../flagsmith/entities/TraitEntityTests.kt | 8 +-- .../flagsmith/mockResponses/MockResponses.kt | 50 +++++++++++++++++ .../IdentityFlagsAndTraitsEndpoint.kt | 4 +- .../mockResponses/endpoints/TraitsEndpoint.kt | 5 +- 11 files changed, 145 insertions(+), 46 deletions(-) diff --git a/FlagsmithClient/src/main/java/com/flagsmith/Flagsmith.kt b/FlagsmithClient/src/main/java/com/flagsmith/Flagsmith.kt index 47cc4b3..d51f703 100644 --- a/FlagsmithClient/src/main/java/com/flagsmith/Flagsmith.kt +++ b/FlagsmithClient/src/main/java/com/flagsmith/Flagsmith.kt @@ -149,30 +149,32 @@ class Flagsmith constructor( result(res.map { it.traits }) }.also { lastUsedIdentity = identity } - fun setTrait(trait: Trait, identity: String, result: (Result) -> Unit) = - retrofit.postTraits(IdentityAndTraits(identity, listOf(trait))) + fun setTrait(trait: Trait, identity: String, transient: Boolean = false, result: (Result) -> Unit) = + retrofit.postTraits(IdentityAndTraits(identity, listOf(trait), transient)) .enqueueWithResult(result = { result(it.map { response -> TraitWithIdentity( key = response.traits.first().key, traitValue = response.traits.first().traitValue, - identity = Identity(identity) + identity = Identity(identity), + transient = response.traits.first().transient )}) }) - fun setTraits(traits: List, identity: String, result: (Result>) -> Unit) { - retrofit.postTraits(IdentityAndTraits(identity, traits)).enqueueWithResult(result = { + fun setTraits(traits: List, identity: String, transient: Boolean, result: (Result>) -> Unit) { + retrofit.postTraits(IdentityAndTraits(identity, traits, transient)).enqueueWithResult(result = { result(it.map { response -> response.traits.map { trait -> TraitWithIdentity( key = trait.key, traitValue = trait.traitValue, - identity = Identity(identity) + identity = Identity(identity), + transient = trait.transient ) }}) }) } - fun getIdentity(identity: String, result: (Result) -> Unit) = - retrofit.getIdentityFlagsAndTraits(identity).enqueueWithResult(defaults = null, result = result) + fun getIdentity(identity: String, transient: Boolean, result: (Result) -> Unit) = + retrofit.getIdentityFlagsAndTraits(identity, transient).enqueueWithResult(defaults = null, result = result) .also { lastUsedIdentity = identity } fun clearCache() { diff --git a/FlagsmithClient/src/main/java/com/flagsmith/entities/IdentityAndTraits.kt b/FlagsmithClient/src/main/java/com/flagsmith/entities/IdentityAndTraits.kt index c626f5b..b2bf68a 100644 --- a/FlagsmithClient/src/main/java/com/flagsmith/entities/IdentityAndTraits.kt +++ b/FlagsmithClient/src/main/java/com/flagsmith/entities/IdentityAndTraits.kt @@ -4,5 +4,6 @@ import com.google.gson.annotations.SerializedName data class IdentityAndTraits( @SerializedName(value = "identifier") val identifier: String, - @SerializedName(value = "traits") val traits: List + @SerializedName(value = "traits") val traits: List, + val transient: Boolean = false ) \ No newline at end of file diff --git a/FlagsmithClient/src/main/java/com/flagsmith/entities/IdentityFlagsAndTraits.kt b/FlagsmithClient/src/main/java/com/flagsmith/entities/IdentityFlagsAndTraits.kt index 365ccdf..fd107f6 100644 --- a/FlagsmithClient/src/main/java/com/flagsmith/entities/IdentityFlagsAndTraits.kt +++ b/FlagsmithClient/src/main/java/com/flagsmith/entities/IdentityFlagsAndTraits.kt @@ -2,5 +2,6 @@ package com.flagsmith.entities data class IdentityFlagsAndTraits( val flags: ArrayList, - val traits: ArrayList + val traits: ArrayList, + val transient: Boolean = false ) \ No newline at end of file diff --git a/FlagsmithClient/src/main/java/com/flagsmith/entities/Trait.kt b/FlagsmithClient/src/main/java/com/flagsmith/entities/Trait.kt index f03c2c8..d71e289 100644 --- a/FlagsmithClient/src/main/java/com/flagsmith/entities/Trait.kt +++ b/FlagsmithClient/src/main/java/com/flagsmith/entities/Trait.kt @@ -6,20 +6,21 @@ import com.google.gson.annotations.SerializedName data class Trait ( val identifier: String? = null, @SerializedName(value = "trait_key") val key: String, - @SerializedName(value = "trait_value") val traitValue: Any + @SerializedName(value = "trait_value") val traitValue: Any, + val transient: Boolean = false, ) { - constructor(key: String, value: String) - : this(key = key, traitValue = value) + constructor(key: String, value: String, transient: Boolean) + : this(key = key, traitValue = value, transient = transient) - constructor(key: String, value: Int) - : this(key = key, traitValue = value) + constructor(key: String, value: Int, transient: Boolean) + : this(key = key, traitValue = value, transient = transient) - constructor(key: String, value: Double) - : this(key = key, traitValue = value) + constructor(key: String, value: Double, transient: Boolean) + : this(key = key, traitValue = value, transient = transient) - constructor(key: String, value: Boolean) - : this(key = key, traitValue = value) + constructor(key: String, value: Boolean, transient: Boolean) + : this(key = key, traitValue = value, transient = transient) @Deprecated("Use traitValue instead or one of the type-safe getters", ReplaceWith("traitValue")) val value: String @@ -49,18 +50,19 @@ data class TraitWithIdentity ( @SerializedName(value = "trait_key") val key: String, @SerializedName(value = "trait_value") val traitValue: Any, val identity: Identity, + val transient: Boolean = false, ) { - constructor(key: String, value: String, identity: Identity) - : this(key = key, traitValue = value, identity = identity) + constructor(key: String, value: String, transient: Boolean, identity: Identity) + : this(key = key, traitValue = value, transient = transient, identity = identity) - constructor(key: String, value: Int, identity: Identity) - : this(key = key, traitValue = value, identity = identity) + constructor(key: String, value: Int, transient: Boolean, identity: Identity) + : this(key = key, traitValue = value, transient = transient, identity = identity) - constructor(key: String, value: Double, identity: Identity) - : this(key = key, traitValue = value, identity = identity) + constructor(key: String, value: Double, transient: Boolean, identity: Identity) + : this(key = key, traitValue = value, transient = transient, identity = identity) - constructor(key: String, value: Boolean, identity: Identity) - : this(key = key, traitValue = value, identity = identity) + constructor(key: String, value: Boolean, transient: Boolean, identity: Identity) + : this(key = key, traitValue = value, transient = transient, identity = identity) @Deprecated("Use traitValue instead or one of the type-safe getters", ReplaceWith("traitValue")) val value: String diff --git a/FlagsmithClient/src/main/java/com/flagsmith/internal/FlagsmithRetrofitService.kt b/FlagsmithClient/src/main/java/com/flagsmith/internal/FlagsmithRetrofitService.kt index 9337d73..3826af8 100644 --- a/FlagsmithClient/src/main/java/com/flagsmith/internal/FlagsmithRetrofitService.kt +++ b/FlagsmithClient/src/main/java/com/flagsmith/internal/FlagsmithRetrofitService.kt @@ -19,7 +19,7 @@ import retrofit2.http.Query interface FlagsmithRetrofitService { @GET("identities/") - fun getIdentityFlagsAndTraits(@Query("identifier") identity: String) : Call + fun getIdentityFlagsAndTraits(@Query("identifier") identity: String, @Query("transient") transient: Boolean = false) : Call @GET("flags/") fun getFlags() : Call> diff --git a/FlagsmithClient/src/test/java/com/flagsmith/SynchronousFlagsmith.kt b/FlagsmithClient/src/test/java/com/flagsmith/SynchronousFlagsmith.kt index 06c024d..b9f0d73 100644 --- a/FlagsmithClient/src/test/java/com/flagsmith/SynchronousFlagsmith.kt +++ b/FlagsmithClient/src/test/java/com/flagsmith/SynchronousFlagsmith.kt @@ -25,9 +25,9 @@ suspend fun Flagsmith.getTraitSync(id: String, identity: String): Result suspend fun Flagsmith.setTraitSync(trait: Trait, identity: String) : Result = suspendCoroutine { cont -> this.setTrait(trait, identity) { cont.resume(it) } } -suspend fun Flagsmith.setTraitsSync(traits: List, identity: String) : Result> - = suspendCoroutine { cont -> this.setTraits(traits, identity) { cont.resume(it) } } +suspend fun Flagsmith.setTraitsSync(traits: List, identity: String, transient: Boolean = false) : Result> + = suspendCoroutine { cont -> this.setTraits(traits, identity, transient) { cont.resume(it) } } -suspend fun Flagsmith.getIdentitySync(identity: String): Result - = suspendCoroutine { cont -> this.getIdentity(identity) { cont.resume(it) } } +suspend fun Flagsmith.getIdentitySync(identity: String, transient: Boolean = false): Result + = suspendCoroutine { cont -> this.getIdentity(identity, transient) { cont.resume(it) } } diff --git a/FlagsmithClient/src/test/java/com/flagsmith/TraitsTests.kt b/FlagsmithClient/src/test/java/com/flagsmith/TraitsTests.kt index 962c0c8..ceaef2a 100644 --- a/FlagsmithClient/src/test/java/com/flagsmith/TraitsTests.kt +++ b/FlagsmithClient/src/test/java/com/flagsmith/TraitsTests.kt @@ -83,7 +83,7 @@ class TraitsTests { mockServer.mockResponseFor(MockEndpoint.SET_TRAIT) runBlocking { val result = - flagsmith.setTraitSync(Trait(key = "set-from-client", value = "12345"), "person") + flagsmith.setTraitSync(Trait(key = "set-from-client", traitValue = "12345"), "person") assertTrue(result.isSuccess) assertEquals("set-from-client", result.getOrThrow().key) assertEquals("12345", result.getOrThrow().stringValue) @@ -96,7 +96,7 @@ class TraitsTests { mockServer.mockResponseFor(MockEndpoint.SET_TRAITS) runBlocking { val result = - flagsmith.setTraitsSync(listOf(Trait(key = "set-from-client", value = "12345")), "person") + flagsmith.setTraitsSync(listOf(Trait(key = "set-from-client", traitValue = "12345")), "person") assertTrue(result.isSuccess) assertEquals("set-from-client", result.getOrThrow().first().key) assertEquals("12345", result.getOrThrow().first().stringValue) @@ -104,12 +104,38 @@ class TraitsTests { } } + @Test + fun testSetTraitsWithTransient() { + mockServer.mockResponseFor(MockEndpoint.SET_TRANSIENT_TRAITS) + runBlocking { + val result = + flagsmith.setTraitsSync( + listOf( + Trait( + key = "trait-one-with-transient", + traitValue = "transient-trait-one", + transient = true + ), + Trait( + key = "trait-two-with-transient", + traitValue = "transient-trait-two", + transient= false + ), + ), "identity-with-transient-traits") + assertTrue(result.isSuccess) + assertEquals("trait-one-with-transient", result.getOrThrow().first().key) + assertEquals("transient-trait-one", result.getOrThrow().first().stringValue) + assertEquals("identity-with-transient-traits", result.getOrThrow().first().identity.identifier) + assertTrue(result.getOrThrow().first().transient) + } + } + @Test fun testSetTraitInteger() { mockServer.mockResponseFor(MockEndpoint.SET_TRAIT_INTEGER) runBlocking { val result = - flagsmith.setTraitSync(Trait(key = "set-from-client", value = 5), "person") + flagsmith.setTraitSync(Trait(key = "set-from-client", traitValue = 5), "person") assertTrue(result.isSuccess) assertEquals("set-from-client", result.getOrThrow().key) assertEquals(5, result.getOrThrow().intValue) @@ -122,7 +148,7 @@ class TraitsTests { mockServer.mockResponseFor(MockEndpoint.SET_TRAIT_DOUBLE) runBlocking { val result = - flagsmith.setTraitSync(Trait(key = "set-from-client", value = 0.5), "person") + flagsmith.setTraitSync(Trait(key = "set-from-client", traitValue = 0.5), "person") assertTrue(result.isSuccess) assertEquals("set-from-client", result.getOrThrow().key) assertEquals(0.5, result.getOrThrow().doubleValue) @@ -135,7 +161,7 @@ class TraitsTests { mockServer.mockResponseFor(MockEndpoint.SET_TRAIT_BOOLEAN) runBlocking { val result = - flagsmith.setTraitSync(Trait(key = "set-from-client", value = true), "person") + flagsmith.setTraitSync(Trait(key = "set-from-client", traitValue = true), "person") assertTrue(result.isSuccess) assertEquals("set-from-client", result.getOrThrow().key) assertEquals(true, result.getOrThrow().booleanValue) @@ -157,4 +183,20 @@ class TraitsTests { ) } } -} \ No newline at end of file + + @Test + fun testGetTransientIdentity() { + mockServer.mockResponseFor(MockEndpoint.GET_TRANSIENT_IDENTITIES) + runBlocking { + val result = flagsmith.getIdentitySync("transient-identity") + assertTrue(result.isSuccess) + assertTrue(result.getOrThrow().traits.isNotEmpty()) + assertTrue(result.getOrThrow().flags.isNotEmpty()) + assertEquals( + "electric pink", + result.getOrThrow().traits.find { trait -> trait.key == "favourite-colour" }?.stringValue + ) + assertTrue(result.getOrThrow().traits.find { trait -> trait.transient == true }?.transient == true) + } + } +} diff --git a/FlagsmithClient/src/test/java/com/flagsmith/entities/TraitEntityTests.kt b/FlagsmithClient/src/test/java/com/flagsmith/entities/TraitEntityTests.kt index 742b17a..1358e07 100644 --- a/FlagsmithClient/src/test/java/com/flagsmith/entities/TraitEntityTests.kt +++ b/FlagsmithClient/src/test/java/com/flagsmith/entities/TraitEntityTests.kt @@ -77,7 +77,7 @@ class TraitEntityTests { @Test fun testTraitConstructorStringType() { - val trait = Trait( "string-key", "string-value") + val trait = Trait( "string-key", "string-value", false) Assert.assertEquals("string-value", trait.traitValue) Assert.assertEquals("string-value", trait.stringValue) Assert.assertNull(trait.intValue) @@ -90,7 +90,7 @@ class TraitEntityTests { @Test fun testTraitConstructorIntType() { - val trait = Trait("string-key", 1) + val trait = Trait("string-key", 1, false) Assert.assertEquals(1, trait.traitValue) Assert.assertEquals(1, trait.intValue) Assert.assertNull("Can't convert an int to a double", trait.doubleValue) @@ -109,7 +109,7 @@ class TraitEntityTests { @Test fun testTraitConstructorDoubleType() { - val trait = Trait("string-key", 1.0) + val trait = Trait("string-key", 1.0, false) Assert.assertEquals(1.0, trait.traitValue) Assert.assertEquals(1.0, trait.doubleValue) Assert.assertEquals("JS ints are actually doubles so we should handle this", @@ -130,7 +130,7 @@ class TraitEntityTests { @Test fun testTraitConstructorBooleanType() { - val trait = Trait("string-key", true) + val trait = Trait("string-key", true, false) Assert.assertEquals(true, trait.traitValue) Assert.assertEquals(true, trait.booleanValue) Assert.assertNull(trait.intValue) diff --git a/FlagsmithClient/src/test/java/com/flagsmith/mockResponses/MockResponses.kt b/FlagsmithClient/src/test/java/com/flagsmith/mockResponses/MockResponses.kt index 9dc70e7..faf6e26 100644 --- a/FlagsmithClient/src/test/java/com/flagsmith/mockResponses/MockResponses.kt +++ b/FlagsmithClient/src/test/java/com/flagsmith/mockResponses/MockResponses.kt @@ -18,6 +18,8 @@ enum class MockEndpoint(val path: String, val body: String) { GET_FLAGS(FlagsEndpoint.path, MockResponses.getFlags), SET_TRAIT(TraitsEndpoint(Trait(key = "", traitValue = ""), "").path, MockResponses.setTrait), SET_TRAITS(TraitsBulkEndpoint(listOf(Trait(key = "", traitValue = "")), "").path, MockResponses.setTraits), + SET_TRANSIENT_TRAITS(TraitsBulkEndpoint(listOf(Trait(key = "", traitValue = "")), "").path, MockResponses.setTransientTraits), + GET_TRANSIENT_IDENTITIES(IdentityFlagsAndTraitsEndpoint("").path, MockResponses.getTransientIdentities), SET_TRAIT_INTEGER(TraitsEndpoint(Trait(key = "", traitValue = ""), "").path, MockResponses.setTraitInteger), SET_TRAIT_DOUBLE(TraitsEndpoint(Trait(key = "", traitValue = ""), "").path, MockResponses.setTraitDouble), SET_TRAIT_BOOLEAN(TraitsEndpoint(Trait(key = "", traitValue = ""), "").path, MockResponses.setTraitBoolean), @@ -126,6 +128,35 @@ object MockResponses { } """.trimIndent() + val getTransientIdentities = """ + { + "flags": [ + { + "feature_state_value": null, + "feature": { + "type": "STANDARD", + "name": "no-value", + "id": 35506 + }, + "enabled": true + } + ], + "traits": [ + { + "trait_value": "12345", + "trait_key": "set-from-client", + "transient": false + }, + { + "trait_value": "electric pink", + "trait_key": "favourite-colour", + "transient": true + } + ], + "transient": true + } + """.trimIndent() + val getFlags = """ [ { @@ -171,6 +202,25 @@ object MockResponses { } """.trimIndent() + val setTransientTraits = """ + { + "identifier": "identity-with-transient-traits", + "flags": [], + "traits": [ + { + "trait_value": "transient-trait-one", + "trait_key": "trait-one-with-transient", + "transient": true + }, + { + "trait_value": "transient-trait-two", + "trait_key": "trait-two-with-transient", + "transient": false + } + ] + } + """.trimIndent() + val setTraits = """ { "identifier": "person", diff --git a/FlagsmithClient/src/test/java/com/flagsmith/mockResponses/endpoints/IdentityFlagsAndTraitsEndpoint.kt b/FlagsmithClient/src/test/java/com/flagsmith/mockResponses/endpoints/IdentityFlagsAndTraitsEndpoint.kt index ce62a5c..d5372f1 100644 --- a/FlagsmithClient/src/test/java/com/flagsmith/mockResponses/endpoints/IdentityFlagsAndTraitsEndpoint.kt +++ b/FlagsmithClient/src/test/java/com/flagsmith/mockResponses/endpoints/IdentityFlagsAndTraitsEndpoint.kt @@ -2,8 +2,8 @@ package com.flagsmith.mockResponses.endpoints import com.flagsmith.entities.IdentityFlagsAndTraits -data class IdentityFlagsAndTraitsEndpoint(private val identity: String) : +data class IdentityFlagsAndTraitsEndpoint(private val identity: String, private val transient: Boolean = false) : GetEndpoint( path = "/identities/", - params = listOf("identifier" to identity), + params = listOf("identifier" to identity, "transient" to transient), ) \ No newline at end of file diff --git a/FlagsmithClient/src/test/java/com/flagsmith/mockResponses/endpoints/TraitsEndpoint.kt b/FlagsmithClient/src/test/java/com/flagsmith/mockResponses/endpoints/TraitsEndpoint.kt index ab371b3..db46ebc 100644 --- a/FlagsmithClient/src/test/java/com/flagsmith/mockResponses/endpoints/TraitsEndpoint.kt +++ b/FlagsmithClient/src/test/java/com/flagsmith/mockResponses/endpoints/TraitsEndpoint.kt @@ -5,13 +5,14 @@ import com.flagsmith.entities.Trait import com.flagsmith.entities.TraitWithIdentity import com.google.gson.Gson -data class TraitsEndpoint(private val trait: Trait, private val identity: String) : +data class TraitsEndpoint(private val trait: Trait, private val identity: String, private val transient: Boolean = false) : PostEndpoint( path = "/identities/", body = Gson().toJson( IdentityAndTraits( identifier = identity, - traits = listOf(trait) + traits = listOf(trait), + transient = transient, ) ), ) \ No newline at end of file From fb26329cbaac9470ea82fb42b16d66ded57b5eca Mon Sep 17 00:00:00 2001 From: Novak Zaballa Date: Thu, 22 Aug 2024 11:06:21 -0400 Subject: [PATCH 02/21] New changes transient --- .../src/main/java/com/flagsmith/Flagsmith.kt | 74 ++++++++++++++----- .../java/com/flagsmith/entities/Identity.kt | 3 +- .../flagsmith/entities/IdentityAndTraits.kt | 2 +- .../entities/IdentityFlagsAndTraits.kt | 1 - .../main/java/com/flagsmith/entities/Trait.kt | 44 ++++++----- .../test/java/com/flagsmith/TraitsTests.kt | 2 +- 6 files changed, 87 insertions(+), 39 deletions(-) diff --git a/FlagsmithClient/src/main/java/com/flagsmith/Flagsmith.kt b/FlagsmithClient/src/main/java/com/flagsmith/Flagsmith.kt index d51f703..0b42cdd 100644 --- a/FlagsmithClient/src/main/java/com/flagsmith/Flagsmith.kt +++ b/FlagsmithClient/src/main/java/com/flagsmith/Flagsmith.kt @@ -149,32 +149,72 @@ class Flagsmith constructor( result(res.map { it.traits }) }.also { lastUsedIdentity = identity } - fun setTrait(trait: Trait, identity: String, transient: Boolean = false, result: (Result) -> Unit) = - retrofit.postTraits(IdentityAndTraits(identity, listOf(trait), transient)) - .enqueueWithResult(result = { - result(it.map { response -> TraitWithIdentity( - key = response.traits.first().key, - traitValue = response.traits.first().traitValue, - identity = Identity(identity), - transient = response.traits.first().transient - )}) - }) + fun setTrait(trait: Trait, identity: String, result: (Result) -> Unit) { + if (trait.isTransient) { + handleTransientTrait(trait) + result(Result.success(TraitWithIdentity(trait.key, trait.traitValue, Identity(identity)))) + } else { + retrofit.postTraits(IdentityAndTraits(identity, listOf(trait))) + .enqueueWithResult(result = { + result(it.map { response -> TraitWithIdentity( + key = response.traits.first().key, + traitValue = response.traits.first().traitValue, + identity = Identity(identity) + )}) + }) + } +} fun setTraits(traits: List, identity: String, transient: Boolean, result: (Result>) -> Unit) { retrofit.postTraits(IdentityAndTraits(identity, traits, transient)).enqueueWithResult(result = { result(it.map { response -> response.traits.map { trait -> - TraitWithIdentity( - key = trait.key, - traitValue = trait.traitValue, - identity = Identity(identity), - transient = trait.transient - ) + if (trait.transient) { + TraitWithIdentity( + key = trait.key, + traitValue = trait.traitValue, + transient = trait.transient, + identity = if (transient) Identity(identity, transient) else Identity(identity) + ) + } else { + TraitWithIdentity( + key = trait.key, + traitValue = trait.traitValue, + identity = if (transient) Identity(identity, transient) else Identity(identity) + ) + } }}) }) } + // fun setTraits(traits: List, identity: String, transient: Boolean?, result: (Result>) -> Unit) { + // val (transientTraits, persistentTraits) = traits.partition { it.isTransient } + // transientTraits.forEach { handleTransientTrait(it) } + // if (persistentTraits.isNotEmpty()) { + // retrofit.postTraits(IdentityAndTraits(identity, persistentTraits)).enqueueWithResult(result = { + // result(it.map { response -> response.traits.map { trait -> + // if (trait.transient) { + // TraitWithIdentity( + // key = trait.key, + // traitValue = trait.traitValue, + // transient = trait.transient, + // identity = if (transient) Identity(identity, transient) else Identity(identity) + // ) + // } else { + // TraitWithIdentity( + // key = trait.key, + // traitValue = trait.traitValue, + // identity = if (transient) Identity(identity, transient) else Identity(identity) + // ) + // } + // }}) + // }) + // } else { + // result(Result.success(emptyList())) + // } + // } + fun getIdentity(identity: String, transient: Boolean, result: (Result) -> Unit) = - retrofit.getIdentityFlagsAndTraits(identity, transient).enqueueWithResult(defaults = null, result = result) + retrofit.getIdentityFlagsAndTraits(identity).enqueueWithResult(defaults = null, result = result) .also { lastUsedIdentity = identity } fun clearCache() { diff --git a/FlagsmithClient/src/main/java/com/flagsmith/entities/Identity.kt b/FlagsmithClient/src/main/java/com/flagsmith/entities/Identity.kt index 93e81f6..da7fef5 100644 --- a/FlagsmithClient/src/main/java/com/flagsmith/entities/Identity.kt +++ b/FlagsmithClient/src/main/java/com/flagsmith/entities/Identity.kt @@ -1,5 +1,6 @@ package com.flagsmith.entities data class Identity( - val identifier: String + val identifier: String, + val transient: Boolean? = false ) \ No newline at end of file diff --git a/FlagsmithClient/src/main/java/com/flagsmith/entities/IdentityAndTraits.kt b/FlagsmithClient/src/main/java/com/flagsmith/entities/IdentityAndTraits.kt index b2bf68a..5f2dbb8 100644 --- a/FlagsmithClient/src/main/java/com/flagsmith/entities/IdentityAndTraits.kt +++ b/FlagsmithClient/src/main/java/com/flagsmith/entities/IdentityAndTraits.kt @@ -5,5 +5,5 @@ import com.google.gson.annotations.SerializedName data class IdentityAndTraits( @SerializedName(value = "identifier") val identifier: String, @SerializedName(value = "traits") val traits: List, - val transient: Boolean = false + val transient: Boolean? = false ) \ No newline at end of file diff --git a/FlagsmithClient/src/main/java/com/flagsmith/entities/IdentityFlagsAndTraits.kt b/FlagsmithClient/src/main/java/com/flagsmith/entities/IdentityFlagsAndTraits.kt index fd107f6..2305a6f 100644 --- a/FlagsmithClient/src/main/java/com/flagsmith/entities/IdentityFlagsAndTraits.kt +++ b/FlagsmithClient/src/main/java/com/flagsmith/entities/IdentityFlagsAndTraits.kt @@ -3,5 +3,4 @@ package com.flagsmith.entities data class IdentityFlagsAndTraits( val flags: ArrayList, val traits: ArrayList, - val transient: Boolean = false ) \ No newline at end of file diff --git a/FlagsmithClient/src/main/java/com/flagsmith/entities/Trait.kt b/FlagsmithClient/src/main/java/com/flagsmith/entities/Trait.kt index d71e289..82f5450 100644 --- a/FlagsmithClient/src/main/java/com/flagsmith/entities/Trait.kt +++ b/FlagsmithClient/src/main/java/com/flagsmith/entities/Trait.kt @@ -3,24 +3,32 @@ package com.flagsmith.entities import com.google.gson.annotations.SerializedName +data class TraitConfig( + val value: TraitValue, + val transient: Boolean? = false, +) + data class Trait ( val identifier: String? = null, @SerializedName(value = "trait_key") val key: String, @SerializedName(value = "trait_value") val traitValue: Any, - val transient: Boolean = false, + val transient: Boolean? = false, ) { - constructor(key: String, value: String, transient: Boolean) - : this(key = key, traitValue = value, transient = transient) + constructor(key: String, value: String) + : this(key = key, traitValue = value) + + constructor(key: String, value: Int) + : this(key = key, traitValue = value) - constructor(key: String, value: Int, transient: Boolean) - : this(key = key, traitValue = value, transient = transient) + constructor(key: String, value: Double) + : this(key = key, traitValue = value) - constructor(key: String, value: Double, transient: Boolean) - : this(key = key, traitValue = value, transient = transient) + constructor(key: String, value: Boolean) + : this(key = key, traitValue = value) - constructor(key: String, value: Boolean, transient: Boolean) - : this(key = key, traitValue = value, transient = transient) + // constructor(key: String, value: TrairConfig) + // : this(key = key, traitValue = value) @Deprecated("Use traitValue instead or one of the type-safe getters", ReplaceWith("traitValue")) val value: String @@ -50,19 +58,19 @@ data class TraitWithIdentity ( @SerializedName(value = "trait_key") val key: String, @SerializedName(value = "trait_value") val traitValue: Any, val identity: Identity, - val transient: Boolean = false, + val transient: Boolean? = false, ) { - constructor(key: String, value: String, transient: Boolean, identity: Identity) - : this(key = key, traitValue = value, transient = transient, identity = identity) + constructor(key: String, value: String, identity: Identity) + : this(key = key, traitValue = value, identity = identity) - constructor(key: String, value: Int, transient: Boolean, identity: Identity) - : this(key = key, traitValue = value, transient = transient, identity = identity) + constructor(key: String, value: Int, identity: Identity) + : this(key = key, traitValue = value, identity = identity) - constructor(key: String, value: Double, transient: Boolean, identity: Identity) - : this(key = key, traitValue = value, transient = transient, identity = identity) + constructor(key: String, value: Double, identity: Identity) + : this(key = key, traitValue = value, identity = identity) - constructor(key: String, value: Boolean, transient: Boolean, identity: Identity) - : this(key = key, traitValue = value, transient = transient, identity = identity) + constructor(key: String, value: Boolean, identity: Identity) + : this(key = key, traitValue = value, identity = identity) @Deprecated("Use traitValue instead or one of the type-safe getters", ReplaceWith("traitValue")) val value: String diff --git a/FlagsmithClient/src/test/java/com/flagsmith/TraitsTests.kt b/FlagsmithClient/src/test/java/com/flagsmith/TraitsTests.kt index ceaef2a..c217a29 100644 --- a/FlagsmithClient/src/test/java/com/flagsmith/TraitsTests.kt +++ b/FlagsmithClient/src/test/java/com/flagsmith/TraitsTests.kt @@ -119,7 +119,7 @@ class TraitsTests { Trait( key = "trait-two-with-transient", traitValue = "transient-trait-two", - transient= false + transient = false ), ), "identity-with-transient-traits") assertTrue(result.isSuccess) From cedfb8c2e49ea145523f0571309516f6e2ea3dce Mon Sep 17 00:00:00 2001 From: Novak Zaballa Date: Fri, 23 Aug 2024 10:52:03 -0400 Subject: [PATCH 03/21] Refact transient traits/identities --- .../src/main/java/com/flagsmith/Flagsmith.kt | 126 +++++++++--------- .../java/com/flagsmith/entities/Identity.kt | 2 +- .../flagsmith/entities/IdentityAndTraits.kt | 2 +- .../main/java/com/flagsmith/entities/Trait.kt | 4 +- .../internal/FlagsmithRetrofitService.kt | 2 +- .../test/java/com/flagsmith/TraitsTests.kt | 12 +- .../flagsmith/entities/TraitEntityTests.kt | 8 +- .../mockResponses/endpoints/TraitsEndpoint.kt | 2 +- 8 files changed, 77 insertions(+), 81 deletions(-) diff --git a/FlagsmithClient/src/main/java/com/flagsmith/Flagsmith.kt b/FlagsmithClient/src/main/java/com/flagsmith/Flagsmith.kt index 0b42cdd..7439acd 100644 --- a/FlagsmithClient/src/main/java/com/flagsmith/Flagsmith.kt +++ b/FlagsmithClient/src/main/java/com/flagsmith/Flagsmith.kt @@ -106,12 +106,12 @@ class Flagsmith constructor( const val DEFAULT_ANALYTICS_FLUSH_PERIOD_SECONDS = 10 } - fun getFeatureFlags(identity: String? = null, result: (Result>) -> Unit) { + fun getFeatureFlags(identity: String? = null, transient: Boolean? = null, result: (Result>) -> Unit) { // Save the last used identity as we'll refresh with this if we get update events lastUsedIdentity = identity if (identity != null) { - retrofit.getIdentityFlagsAndTraits(identity).enqueueWithResult { res -> + retrofit.getIdentityFlagsAndTraits(identity, transient).enqueueWithResult { res -> flagUpdateFlow.tryEmit(res.getOrNull()?.flags ?: emptyList()) result(res.map { it.flags }) } @@ -139,82 +139,78 @@ class Flagsmith constructor( result(res.map { flag -> flag?.featureStateValue }) } - fun getTrait(id: String, identity: String, result: (Result) -> Unit) = - retrofit.getIdentityFlagsAndTraits(identity).enqueueWithResult { res -> + fun getTrait( + id: String, + identity: String, + transient: Boolean? = null, + result: (Result) -> Unit + ) { + retrofit.getIdentityFlagsAndTraits(identity, transient).enqueueWithResult { res -> result(res.map { value -> value.traits.find { it.key == id } }) }.also { lastUsedIdentity = identity } + } - fun getTraits(identity: String, result: (Result>) -> Unit) = - retrofit.getIdentityFlagsAndTraits(identity).enqueueWithResult { res -> + fun getTraits( + identity: String, + transient: Boolean? = null, + result: (Result>) -> Unit + ) { + retrofit.getIdentityFlagsAndTraits(identity, transient).enqueueWithResult { res -> result(res.map { it.traits }) }.also { lastUsedIdentity = identity } - - fun setTrait(trait: Trait, identity: String, result: (Result) -> Unit) { - if (trait.isTransient) { - handleTransientTrait(trait) - result(Result.success(TraitWithIdentity(trait.key, trait.traitValue, Identity(identity)))) + } + fun setTrait( + trait: Trait, + identity: String, + transient: Boolean? = null, + result: (Result) -> Unit + ) { + val identityAndTraits = if (transient != null) { + IdentityAndTraits(identity, listOf(trait), transient) } else { - retrofit.postTraits(IdentityAndTraits(identity, listOf(trait))) - .enqueueWithResult(result = { - result(it.map { response -> TraitWithIdentity( + IdentityAndTraits(identity, listOf(trait)) + } + retrofit.postTraits(identityAndTraits) + .enqueueWithResult { result -> + result(it.map { response -> + TraitWithIdentity( key = response.traits.first().key, traitValue = response.traits.first().traitValue, identity = Identity(identity) - )}) + transient = response.traits.first().traitValue, + ) }) - } -} + } + } - fun setTraits(traits: List, identity: String, transient: Boolean, result: (Result>) -> Unit) { - retrofit.postTraits(IdentityAndTraits(identity, traits, transient)).enqueueWithResult(result = { - result(it.map { response -> response.traits.map { trait -> - if (trait.transient) { - TraitWithIdentity( - key = trait.key, - traitValue = trait.traitValue, - transient = trait.transient, - identity = if (transient) Identity(identity, transient) else Identity(identity) - ) - } else { - TraitWithIdentity( - key = trait.key, - traitValue = trait.traitValue, - identity = if (transient) Identity(identity, transient) else Identity(identity) - ) - } - }}) - }) + fun setTraits( + traits: List, + identity: String, + transient: Boolean? = null, + result: (Result>) -> Unit + ) { + val identityAndTraits = if (transient != null) { + IdentityAndTraits(identity, traits, transient) + } else { + IdentityAndTraits(identity, traits) + } + retrofit.postTraits(identityAndTraits) + .enqueueWithResult { result -> + result(it.map { response -> + response.traits.map { trait -> + TraitWithIdentity( + key = trait.key, + traitValue = trait.traitValue, + identity = Identity(identity) + transient = trait.transient, + ) + } + }) + } } - // fun setTraits(traits: List, identity: String, transient: Boolean?, result: (Result>) -> Unit) { - // val (transientTraits, persistentTraits) = traits.partition { it.isTransient } - // transientTraits.forEach { handleTransientTrait(it) } - // if (persistentTraits.isNotEmpty()) { - // retrofit.postTraits(IdentityAndTraits(identity, persistentTraits)).enqueueWithResult(result = { - // result(it.map { response -> response.traits.map { trait -> - // if (trait.transient) { - // TraitWithIdentity( - // key = trait.key, - // traitValue = trait.traitValue, - // transient = trait.transient, - // identity = if (transient) Identity(identity, transient) else Identity(identity) - // ) - // } else { - // TraitWithIdentity( - // key = trait.key, - // traitValue = trait.traitValue, - // identity = if (transient) Identity(identity, transient) else Identity(identity) - // ) - // } - // }}) - // }) - // } else { - // result(Result.success(emptyList())) - // } - // } - - fun getIdentity(identity: String, transient: Boolean, result: (Result) -> Unit) = - retrofit.getIdentityFlagsAndTraits(identity).enqueueWithResult(defaults = null, result = result) + fun getIdentity(identity: String, transient: Boolean? = null, result: (Result) -> Unit) = + retrofit.getIdentityFlagsAndTraits(identity, transient).enqueueWithResult(defaults = null, result = result) .also { lastUsedIdentity = identity } fun clearCache() { diff --git a/FlagsmithClient/src/main/java/com/flagsmith/entities/Identity.kt b/FlagsmithClient/src/main/java/com/flagsmith/entities/Identity.kt index da7fef5..80a95f7 100644 --- a/FlagsmithClient/src/main/java/com/flagsmith/entities/Identity.kt +++ b/FlagsmithClient/src/main/java/com/flagsmith/entities/Identity.kt @@ -2,5 +2,5 @@ package com.flagsmith.entities data class Identity( val identifier: String, - val transient: Boolean? = false + val transient: Boolean? ) \ No newline at end of file diff --git a/FlagsmithClient/src/main/java/com/flagsmith/entities/IdentityAndTraits.kt b/FlagsmithClient/src/main/java/com/flagsmith/entities/IdentityAndTraits.kt index 5f2dbb8..49f28d2 100644 --- a/FlagsmithClient/src/main/java/com/flagsmith/entities/IdentityAndTraits.kt +++ b/FlagsmithClient/src/main/java/com/flagsmith/entities/IdentityAndTraits.kt @@ -5,5 +5,5 @@ import com.google.gson.annotations.SerializedName data class IdentityAndTraits( @SerializedName(value = "identifier") val identifier: String, @SerializedName(value = "traits") val traits: List, - val transient: Boolean? = false + @SerializedName(value = "transient") val transient: Boolean? = null ) \ No newline at end of file diff --git a/FlagsmithClient/src/main/java/com/flagsmith/entities/Trait.kt b/FlagsmithClient/src/main/java/com/flagsmith/entities/Trait.kt index 82f5450..7b3eef0 100644 --- a/FlagsmithClient/src/main/java/com/flagsmith/entities/Trait.kt +++ b/FlagsmithClient/src/main/java/com/flagsmith/entities/Trait.kt @@ -12,7 +12,7 @@ data class Trait ( val identifier: String? = null, @SerializedName(value = "trait_key") val key: String, @SerializedName(value = "trait_value") val traitValue: Any, - val transient: Boolean? = false, + @SerializedName(value = "transient") val transient: Boolean? = null ) { constructor(key: String, value: String) @@ -58,7 +58,7 @@ data class TraitWithIdentity ( @SerializedName(value = "trait_key") val key: String, @SerializedName(value = "trait_value") val traitValue: Any, val identity: Identity, - val transient: Boolean? = false, + @SerializedName(value = "transient") val transient: Boolean? = null ) { constructor(key: String, value: String, identity: Identity) : this(key = key, traitValue = value, identity = identity) diff --git a/FlagsmithClient/src/main/java/com/flagsmith/internal/FlagsmithRetrofitService.kt b/FlagsmithClient/src/main/java/com/flagsmith/internal/FlagsmithRetrofitService.kt index 3826af8..ba7b5c1 100644 --- a/FlagsmithClient/src/main/java/com/flagsmith/internal/FlagsmithRetrofitService.kt +++ b/FlagsmithClient/src/main/java/com/flagsmith/internal/FlagsmithRetrofitService.kt @@ -19,7 +19,7 @@ import retrofit2.http.Query interface FlagsmithRetrofitService { @GET("identities/") - fun getIdentityFlagsAndTraits(@Query("identifier") identity: String, @Query("transient") transient: Boolean = false) : Call + fun getIdentityFlagsAndTraits(@Query("identifier") identity: String, @Query("transient") transient: Boolean? = null) : Call @GET("flags/") fun getFlags() : Call> diff --git a/FlagsmithClient/src/test/java/com/flagsmith/TraitsTests.kt b/FlagsmithClient/src/test/java/com/flagsmith/TraitsTests.kt index c217a29..0122325 100644 --- a/FlagsmithClient/src/test/java/com/flagsmith/TraitsTests.kt +++ b/FlagsmithClient/src/test/java/com/flagsmith/TraitsTests.kt @@ -83,7 +83,7 @@ class TraitsTests { mockServer.mockResponseFor(MockEndpoint.SET_TRAIT) runBlocking { val result = - flagsmith.setTraitSync(Trait(key = "set-from-client", traitValue = "12345"), "person") + flagsmith.setTraitSync(Trait(key = "set-from-client", value = "12345"), "person") assertTrue(result.isSuccess) assertEquals("set-from-client", result.getOrThrow().key) assertEquals("12345", result.getOrThrow().stringValue) @@ -96,7 +96,7 @@ class TraitsTests { mockServer.mockResponseFor(MockEndpoint.SET_TRAITS) runBlocking { val result = - flagsmith.setTraitsSync(listOf(Trait(key = "set-from-client", traitValue = "12345")), "person") + flagsmith.setTraitsSync(listOf(Trait(key = "set-from-client", value = "12345")), "person") assertTrue(result.isSuccess) assertEquals("set-from-client", result.getOrThrow().first().key) assertEquals("12345", result.getOrThrow().first().stringValue) @@ -113,12 +113,12 @@ class TraitsTests { listOf( Trait( key = "trait-one-with-transient", - traitValue = "transient-trait-one", + value = "transient-trait-one", transient = true ), Trait( - key = "trait-two-with-transient", - traitValue = "transient-trait-two", + key = "trait-two", + value = "trait-two-value", transient = false ), ), "identity-with-transient-traits") @@ -135,7 +135,7 @@ class TraitsTests { mockServer.mockResponseFor(MockEndpoint.SET_TRAIT_INTEGER) runBlocking { val result = - flagsmith.setTraitSync(Trait(key = "set-from-client", traitValue = 5), "person") + flagsmith.setTraitSync(Trait(key = "set-from-client", value = 5), "person") assertTrue(result.isSuccess) assertEquals("set-from-client", result.getOrThrow().key) assertEquals(5, result.getOrThrow().intValue) diff --git a/FlagsmithClient/src/test/java/com/flagsmith/entities/TraitEntityTests.kt b/FlagsmithClient/src/test/java/com/flagsmith/entities/TraitEntityTests.kt index 1358e07..742b17a 100644 --- a/FlagsmithClient/src/test/java/com/flagsmith/entities/TraitEntityTests.kt +++ b/FlagsmithClient/src/test/java/com/flagsmith/entities/TraitEntityTests.kt @@ -77,7 +77,7 @@ class TraitEntityTests { @Test fun testTraitConstructorStringType() { - val trait = Trait( "string-key", "string-value", false) + val trait = Trait( "string-key", "string-value") Assert.assertEquals("string-value", trait.traitValue) Assert.assertEquals("string-value", trait.stringValue) Assert.assertNull(trait.intValue) @@ -90,7 +90,7 @@ class TraitEntityTests { @Test fun testTraitConstructorIntType() { - val trait = Trait("string-key", 1, false) + val trait = Trait("string-key", 1) Assert.assertEquals(1, trait.traitValue) Assert.assertEquals(1, trait.intValue) Assert.assertNull("Can't convert an int to a double", trait.doubleValue) @@ -109,7 +109,7 @@ class TraitEntityTests { @Test fun testTraitConstructorDoubleType() { - val trait = Trait("string-key", 1.0, false) + val trait = Trait("string-key", 1.0) Assert.assertEquals(1.0, trait.traitValue) Assert.assertEquals(1.0, trait.doubleValue) Assert.assertEquals("JS ints are actually doubles so we should handle this", @@ -130,7 +130,7 @@ class TraitEntityTests { @Test fun testTraitConstructorBooleanType() { - val trait = Trait("string-key", true, false) + val trait = Trait("string-key", true) Assert.assertEquals(true, trait.traitValue) Assert.assertEquals(true, trait.booleanValue) Assert.assertNull(trait.intValue) diff --git a/FlagsmithClient/src/test/java/com/flagsmith/mockResponses/endpoints/TraitsEndpoint.kt b/FlagsmithClient/src/test/java/com/flagsmith/mockResponses/endpoints/TraitsEndpoint.kt index db46ebc..8c49d8d 100644 --- a/FlagsmithClient/src/test/java/com/flagsmith/mockResponses/endpoints/TraitsEndpoint.kt +++ b/FlagsmithClient/src/test/java/com/flagsmith/mockResponses/endpoints/TraitsEndpoint.kt @@ -5,7 +5,7 @@ import com.flagsmith.entities.Trait import com.flagsmith.entities.TraitWithIdentity import com.google.gson.Gson -data class TraitsEndpoint(private val trait: Trait, private val identity: String, private val transient: Boolean = false) : +data class TraitsEndpoint(private val trait: Trait, private val identity: String, private val transient: Boolean = null) : PostEndpoint( path = "/identities/", body = Gson().toJson( From d8f123d8450b51cd22b3832942de606acdf50790 Mon Sep 17 00:00:00 2001 From: Novak Zaballa Date: Fri, 23 Aug 2024 14:53:31 -0400 Subject: [PATCH 04/21] Solve code issues --- .../src/main/java/com/flagsmith/Flagsmith.kt | 60 +++++++------------ .../java/com/flagsmith/entities/Identity.kt | 1 - .../main/java/com/flagsmith/entities/Trait.kt | 28 ++++----- .../test/java/com/flagsmith/TraitsTests.kt | 32 +++++----- .../mockResponses/endpoints/TraitsEndpoint.kt | 2 +- 5 files changed, 50 insertions(+), 73 deletions(-) diff --git a/FlagsmithClient/src/main/java/com/flagsmith/Flagsmith.kt b/FlagsmithClient/src/main/java/com/flagsmith/Flagsmith.kt index 7439acd..a87ab1e 100644 --- a/FlagsmithClient/src/main/java/com/flagsmith/Flagsmith.kt +++ b/FlagsmithClient/src/main/java/com/flagsmith/Flagsmith.kt @@ -159,54 +159,40 @@ class Flagsmith constructor( result(res.map { it.traits }) }.also { lastUsedIdentity = identity } } - fun setTrait( - trait: Trait, - identity: String, - transient: Boolean? = null, - result: (Result) -> Unit - ) { - val identityAndTraits = if (transient != null) { + + fun setTrait(trait: Trait, identity: String, transient: Boolean? = null, result: (Result) -> Unit) { + val identityAndTraits = if (transient != null) { IdentityAndTraits(identity, listOf(trait), transient) } else { IdentityAndTraits(identity, listOf(trait)) } - retrofit.postTraits(identityAndTraits) - .enqueueWithResult { result -> - result(it.map { response -> - TraitWithIdentity( - key = response.traits.first().key, - traitValue = response.traits.first().traitValue, - identity = Identity(identity) - transient = response.traits.first().traitValue, - ) - }) - } + retrofit.postTraits(identityAndTraits) + .enqueueWithResult(result = { + result(it.map { response -> TraitWithIdentity( + key = response.traits.first().key, + traitValue = response.traits.first().traitValue, + identity = Identity(identity), + transient = response.traits.first().transient + )}) + }) } - fun setTraits( - traits: List, - identity: String, - transient: Boolean? = null, - result: (Result>) -> Unit - ) { + fun setTraits(traits: List, identity: String, transient: Boolean? = null, result: (Result>) -> Unit) { val identityAndTraits = if (transient != null) { IdentityAndTraits(identity, traits, transient) } else { IdentityAndTraits(identity, traits) } - retrofit.postTraits(identityAndTraits) - .enqueueWithResult { result -> - result(it.map { response -> - response.traits.map { trait -> - TraitWithIdentity( - key = trait.key, - traitValue = trait.traitValue, - identity = Identity(identity) - transient = trait.transient, - ) - } - }) - } + retrofit.postTraits(identityAndTraits).enqueueWithResult(result = { + result(it.map { response -> response.traits.map { trait -> + TraitWithIdentity( + key = trait.key, + traitValue = trait.traitValue, + identity = Identity(identity), + transient = trait.transient + ) + }}) + }) } fun getIdentity(identity: String, transient: Boolean? = null, result: (Result) -> Unit) = diff --git a/FlagsmithClient/src/main/java/com/flagsmith/entities/Identity.kt b/FlagsmithClient/src/main/java/com/flagsmith/entities/Identity.kt index 80a95f7..a4ad0b5 100644 --- a/FlagsmithClient/src/main/java/com/flagsmith/entities/Identity.kt +++ b/FlagsmithClient/src/main/java/com/flagsmith/entities/Identity.kt @@ -2,5 +2,4 @@ package com.flagsmith.entities data class Identity( val identifier: String, - val transient: Boolean? ) \ No newline at end of file diff --git a/FlagsmithClient/src/main/java/com/flagsmith/entities/Trait.kt b/FlagsmithClient/src/main/java/com/flagsmith/entities/Trait.kt index 7b3eef0..14de23b 100644 --- a/FlagsmithClient/src/main/java/com/flagsmith/entities/Trait.kt +++ b/FlagsmithClient/src/main/java/com/flagsmith/entities/Trait.kt @@ -3,32 +3,25 @@ package com.flagsmith.entities import com.google.gson.annotations.SerializedName -data class TraitConfig( - val value: TraitValue, - val transient: Boolean? = false, -) data class Trait ( val identifier: String? = null, @SerializedName(value = "trait_key") val key: String, @SerializedName(value = "trait_value") val traitValue: Any, - @SerializedName(value = "transient") val transient: Boolean? = null + val transient: Boolean? = null ) { - constructor(key: String, value: String) - : this(key = key, traitValue = value) + constructor(key: String, value: String, transient: Boolean? = null) + : this(key = key, traitValue = value, transient = transient) - constructor(key: String, value: Int) - : this(key = key, traitValue = value) + constructor(key: String, value: Int, transient: Boolean? = null) + : this(key = key, traitValue = value, transient = transient) - constructor(key: String, value: Double) - : this(key = key, traitValue = value) + constructor(key: String, value: Double, transient: Boolean? = null) + : this(key = key, traitValue = value, transient = transient) - constructor(key: String, value: Boolean) - : this(key = key, traitValue = value) - - // constructor(key: String, value: TrairConfig) - // : this(key = key, traitValue = value) + constructor(key: String, value: Boolean, transient: Boolean? = null) + : this(key = key, traitValue = value, transient = transient) @Deprecated("Use traitValue instead or one of the type-safe getters", ReplaceWith("traitValue")) val value: String @@ -51,14 +44,13 @@ data class Trait ( val booleanValue: Boolean? get() = traitValue as? Boolean - } data class TraitWithIdentity ( @SerializedName(value = "trait_key") val key: String, @SerializedName(value = "trait_value") val traitValue: Any, val identity: Identity, - @SerializedName(value = "transient") val transient: Boolean? = null + val transient: Boolean? = null ) { constructor(key: String, value: String, identity: Identity) : this(key = key, traitValue = value, identity = identity) diff --git a/FlagsmithClient/src/test/java/com/flagsmith/TraitsTests.kt b/FlagsmithClient/src/test/java/com/flagsmith/TraitsTests.kt index 0122325..de0140b 100644 --- a/FlagsmithClient/src/test/java/com/flagsmith/TraitsTests.kt +++ b/FlagsmithClient/src/test/java/com/flagsmith/TraitsTests.kt @@ -126,7 +126,7 @@ class TraitsTests { assertEquals("trait-one-with-transient", result.getOrThrow().first().key) assertEquals("transient-trait-one", result.getOrThrow().first().stringValue) assertEquals("identity-with-transient-traits", result.getOrThrow().first().identity.identifier) - assertTrue(result.getOrThrow().first().transient) + // assertTrue(result.getOrThrow().first().transient) } } @@ -184,19 +184,19 @@ class TraitsTests { } } - @Test - fun testGetTransientIdentity() { - mockServer.mockResponseFor(MockEndpoint.GET_TRANSIENT_IDENTITIES) - runBlocking { - val result = flagsmith.getIdentitySync("transient-identity") - assertTrue(result.isSuccess) - assertTrue(result.getOrThrow().traits.isNotEmpty()) - assertTrue(result.getOrThrow().flags.isNotEmpty()) - assertEquals( - "electric pink", - result.getOrThrow().traits.find { trait -> trait.key == "favourite-colour" }?.stringValue - ) - assertTrue(result.getOrThrow().traits.find { trait -> trait.transient == true }?.transient == true) - } - } + // @Test + // fun testGetTransientIdentity() { + // mockServer.mockResponseFor(MockEndpoint.GET_TRANSIENT_IDENTITIES) + // runBlocking { + // val result = flagsmith.getIdentitySync("transient-identity") + // assertTrue(result.isSuccess) + // assertTrue(result.getOrThrow().traits.isNotEmpty()) + // assertTrue(result.getOrThrow().flags.isNotEmpty()) + // assertEquals( + // "electric pink", + // result.getOrThrow().traits.find { trait -> trait.key == "favourite-colour" }?.stringValue + // ) + // // assertTrue(result.getOrThrow().traits.find { trait -> trait.transient == true }?.transient == true) + // } + // } } diff --git a/FlagsmithClient/src/test/java/com/flagsmith/mockResponses/endpoints/TraitsEndpoint.kt b/FlagsmithClient/src/test/java/com/flagsmith/mockResponses/endpoints/TraitsEndpoint.kt index 8c49d8d..fbab66f 100644 --- a/FlagsmithClient/src/test/java/com/flagsmith/mockResponses/endpoints/TraitsEndpoint.kt +++ b/FlagsmithClient/src/test/java/com/flagsmith/mockResponses/endpoints/TraitsEndpoint.kt @@ -5,7 +5,7 @@ import com.flagsmith.entities.Trait import com.flagsmith.entities.TraitWithIdentity import com.google.gson.Gson -data class TraitsEndpoint(private val trait: Trait, private val identity: String, private val transient: Boolean = null) : +data class TraitsEndpoint(private val trait: Trait, private val identity: String, private val transient: Boolean? = null) : PostEndpoint( path = "/identities/", body = Gson().toJson( From 7f82cbcf5f943c5487dcc67b7d5e97855368eac1 Mon Sep 17 00:00:00 2001 From: Novak Zaballa Date: Mon, 26 Aug 2024 09:23:51 -0400 Subject: [PATCH 05/21] Solve test issues --- .../src/main/java/com/flagsmith/Flagsmith.kt | 28 +++++++-------- .../main/java/com/flagsmith/entities/Trait.kt | 16 ++++----- .../test/java/com/flagsmith/TraitsTests.kt | 34 +++++++++---------- 3 files changed, 39 insertions(+), 39 deletions(-) diff --git a/FlagsmithClient/src/main/java/com/flagsmith/Flagsmith.kt b/FlagsmithClient/src/main/java/com/flagsmith/Flagsmith.kt index a87ab1e..99b03a7 100644 --- a/FlagsmithClient/src/main/java/com/flagsmith/Flagsmith.kt +++ b/FlagsmithClient/src/main/java/com/flagsmith/Flagsmith.kt @@ -161,21 +161,21 @@ class Flagsmith constructor( } fun setTrait(trait: Trait, identity: String, transient: Boolean? = null, result: (Result) -> Unit) { - val identityAndTraits = if (transient != null) { - IdentityAndTraits(identity, listOf(trait), transient) - } else { - IdentityAndTraits(identity, listOf(trait)) + val identityAndTraits = if (transient != null) { + IdentityAndTraits(identity, listOf(trait), transient) + } else { + IdentityAndTraits(identity, listOf(trait)) + } + retrofit.postTraits(identityAndTraits) + .enqueueWithResult(result = { + result(it.map { response -> TraitWithIdentity( + key = response.traits.first().key, + traitValue = response.traits.first().traitValue, + identity = Identity(identity), + transient = response.traits.first().transient + )}) + }) } - retrofit.postTraits(identityAndTraits) - .enqueueWithResult(result = { - result(it.map { response -> TraitWithIdentity( - key = response.traits.first().key, - traitValue = response.traits.first().traitValue, - identity = Identity(identity), - transient = response.traits.first().transient - )}) - }) - } fun setTraits(traits: List, identity: String, transient: Boolean? = null, result: (Result>) -> Unit) { val identityAndTraits = if (transient != null) { diff --git a/FlagsmithClient/src/main/java/com/flagsmith/entities/Trait.kt b/FlagsmithClient/src/main/java/com/flagsmith/entities/Trait.kt index 14de23b..ca8579f 100644 --- a/FlagsmithClient/src/main/java/com/flagsmith/entities/Trait.kt +++ b/FlagsmithClient/src/main/java/com/flagsmith/entities/Trait.kt @@ -52,17 +52,17 @@ data class TraitWithIdentity ( val identity: Identity, val transient: Boolean? = null ) { - constructor(key: String, value: String, identity: Identity) - : this(key = key, traitValue = value, identity = identity) + constructor(key: String, value: String, identity: Identity, transient: Boolean? = null) + : this(key = key, traitValue = value, identity = identity, transient = transient) - constructor(key: String, value: Int, identity: Identity) - : this(key = key, traitValue = value, identity = identity) + constructor(key: String, value: Int, identity: Identity, transient: Boolean? = null) + : this(key = key, traitValue = value, identity = identity, transient = transient) - constructor(key: String, value: Double, identity: Identity) - : this(key = key, traitValue = value, identity = identity) + constructor(key: String, value: Double, identity: Identity, transient: Boolean? = null) + : this(key = key, traitValue = value, identity = identity, transient = transient) - constructor(key: String, value: Boolean, identity: Identity) - : this(key = key, traitValue = value, identity = identity) + constructor(key: String, value: Boolean, identity: Identity, transient: Boolean? = null) + : this(key = key, traitValue = value, identity = identity, transient = transient) @Deprecated("Use traitValue instead or one of the type-safe getters", ReplaceWith("traitValue")) val value: String diff --git a/FlagsmithClient/src/test/java/com/flagsmith/TraitsTests.kt b/FlagsmithClient/src/test/java/com/flagsmith/TraitsTests.kt index de0140b..a81dac0 100644 --- a/FlagsmithClient/src/test/java/com/flagsmith/TraitsTests.kt +++ b/FlagsmithClient/src/test/java/com/flagsmith/TraitsTests.kt @@ -121,12 +121,12 @@ class TraitsTests { value = "trait-two-value", transient = false ), - ), "identity-with-transient-traits") + ), "identity-with-transient-traits") assertTrue(result.isSuccess) assertEquals("trait-one-with-transient", result.getOrThrow().first().key) assertEquals("transient-trait-one", result.getOrThrow().first().stringValue) assertEquals("identity-with-transient-traits", result.getOrThrow().first().identity.identifier) - // assertTrue(result.getOrThrow().first().transient) + assertEquals(true, result.getOrThrow().first().transient) } } @@ -184,19 +184,19 @@ class TraitsTests { } } - // @Test - // fun testGetTransientIdentity() { - // mockServer.mockResponseFor(MockEndpoint.GET_TRANSIENT_IDENTITIES) - // runBlocking { - // val result = flagsmith.getIdentitySync("transient-identity") - // assertTrue(result.isSuccess) - // assertTrue(result.getOrThrow().traits.isNotEmpty()) - // assertTrue(result.getOrThrow().flags.isNotEmpty()) - // assertEquals( - // "electric pink", - // result.getOrThrow().traits.find { trait -> trait.key == "favourite-colour" }?.stringValue - // ) - // // assertTrue(result.getOrThrow().traits.find { trait -> trait.transient == true }?.transient == true) - // } - // } + @Test + fun testGetTransientIdentity() { + mockServer.mockResponseFor(MockEndpoint.GET_TRANSIENT_IDENTITIES) + runBlocking { + val result = flagsmith.getIdentitySync("transient-identity", true) + assertTrue(result.isSuccess) + assertTrue(result.getOrThrow().traits.isNotEmpty()) + assertTrue(result.getOrThrow().flags.isNotEmpty()) + assertEquals( + "electric pink", + result.getOrThrow().traits.find { trait -> trait.key == "favourite-colour" }?.stringValue + ) + assertEquals(true, result.getOrThrow().flags.isNotEmpty()) + } + } } From 986f1de8473068888d62712698bdefdd20ed144c Mon Sep 17 00:00:00 2001 From: Matthew Elwell Date: Fri, 4 Oct 2024 12:29:52 +0100 Subject: [PATCH 06/21] Revert unnecessary changes to setTrait and setTraits --- .../src/main/java/com/flagsmith/Flagsmith.kt | 25 +++++-------------- 1 file changed, 6 insertions(+), 19 deletions(-) diff --git a/FlagsmithClient/src/main/java/com/flagsmith/Flagsmith.kt b/FlagsmithClient/src/main/java/com/flagsmith/Flagsmith.kt index 082a715..f4cd976 100644 --- a/FlagsmithClient/src/main/java/com/flagsmith/Flagsmith.kt +++ b/FlagsmithClient/src/main/java/com/flagsmith/Flagsmith.kt @@ -170,36 +170,23 @@ class Flagsmith constructor( }.also { lastUsedIdentity = identity } } - fun setTrait(trait: Trait, identity: String, transient: Boolean? = null, result: (Result) -> Unit) { - val identityAndTraits = if (transient != null) { - IdentityAndTraits(identity, listOf(trait), transient) - } else { - IdentityAndTraits(identity, listOf(trait)) - } - retrofit.postTraits(identityAndTraits) + fun setTrait(trait: Trait, identity: String, result: (Result) -> Unit) = + retrofit.postTraits(IdentityAndTraits(identity, listOf(trait))) .enqueueWithResult(result = { result(it.map { response -> TraitWithIdentity( key = response.traits.first().key, traitValue = response.traits.first().traitValue, - identity = Identity(identity), - transient = response.traits.first().transient + identity = Identity(identity) )}) }) - } - fun setTraits(traits: List, identity: String, transient: Boolean? = null, result: (Result>) -> Unit) { - val identityAndTraits = if (transient != null) { - IdentityAndTraits(identity, traits, transient) - } else { - IdentityAndTraits(identity, traits) - } - retrofit.postTraits(identityAndTraits).enqueueWithResult(result = { + fun setTraits(traits: List, identity: String, result: (Result>) -> Unit) { + retrofit.postTraits(IdentityAndTraits(identity, traits)).enqueueWithResult(result = { result(it.map { response -> response.traits.map { trait -> TraitWithIdentity( key = trait.key, traitValue = trait.traitValue, - identity = Identity(identity), - transient = trait.transient + identity = Identity(identity) ) }}) }) From 61af2edf16f39aea4c44615ec207189457da2058 Mon Sep 17 00:00:00 2001 From: Matthew Elwell Date: Fri, 4 Oct 2024 12:33:08 +0100 Subject: [PATCH 07/21] Revert unnecessary changes to trait tests --- FlagsmithClient/src/test/java/com/flagsmith/TraitsTests.kt | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/FlagsmithClient/src/test/java/com/flagsmith/TraitsTests.kt b/FlagsmithClient/src/test/java/com/flagsmith/TraitsTests.kt index a81dac0..873ca5d 100644 --- a/FlagsmithClient/src/test/java/com/flagsmith/TraitsTests.kt +++ b/FlagsmithClient/src/test/java/com/flagsmith/TraitsTests.kt @@ -148,7 +148,7 @@ class TraitsTests { mockServer.mockResponseFor(MockEndpoint.SET_TRAIT_DOUBLE) runBlocking { val result = - flagsmith.setTraitSync(Trait(key = "set-from-client", traitValue = 0.5), "person") + flagsmith.setTraitSync(Trait(key = "set-from-client", value = 0.5), "person") assertTrue(result.isSuccess) assertEquals("set-from-client", result.getOrThrow().key) assertEquals(0.5, result.getOrThrow().doubleValue) @@ -161,7 +161,7 @@ class TraitsTests { mockServer.mockResponseFor(MockEndpoint.SET_TRAIT_BOOLEAN) runBlocking { val result = - flagsmith.setTraitSync(Trait(key = "set-from-client", traitValue = true), "person") + flagsmith.setTraitSync(Trait(key = "set-from-client", value = true), "person") assertTrue(result.isSuccess) assertEquals("set-from-client", result.getOrThrow().key) assertEquals(true, result.getOrThrow().booleanValue) From 0a8433c441d19f1c637ba2ce38598bbe23607666 Mon Sep 17 00:00:00 2001 From: Matthew Elwell Date: Fri, 4 Oct 2024 12:36:52 +0100 Subject: [PATCH 08/21] Move identity tests to their own test file --- .../test/java/com/flagsmith/IdentityTests.kt | 66 +++++++++++++++++++ .../test/java/com/flagsmith/TraitsTests.kt | 31 --------- 2 files changed, 66 insertions(+), 31 deletions(-) create mode 100644 FlagsmithClient/src/test/java/com/flagsmith/IdentityTests.kt diff --git a/FlagsmithClient/src/test/java/com/flagsmith/IdentityTests.kt b/FlagsmithClient/src/test/java/com/flagsmith/IdentityTests.kt new file mode 100644 index 0000000..6c6e8d4 --- /dev/null +++ b/FlagsmithClient/src/test/java/com/flagsmith/IdentityTests.kt @@ -0,0 +1,66 @@ +package com.flagsmith + +import com.flagsmith.entities.Trait +import com.flagsmith.mockResponses.MockEndpoint +import com.flagsmith.mockResponses.mockResponseFor +import kotlinx.coroutines.runBlocking +import org.junit.After +import org.junit.Assert.assertEquals +import org.junit.Assert.assertNull +import org.junit.Assert.assertTrue +import org.junit.Before +import org.junit.Test +import org.mockserver.integration.ClientAndServer + +class IdentityTests { + + private lateinit var mockServer: ClientAndServer + private lateinit var flagsmith: Flagsmith + + @Before + fun setup() { + mockServer = ClientAndServer.startClientAndServer() + flagsmith = Flagsmith( + environmentKey = "", + baseUrl = "http://localhost:${mockServer.localPort}", + enableAnalytics = false, + cacheConfig = FlagsmithCacheConfig(enableCache = false) + ) + } + + @After + fun tearDown() { + mockServer.stop() + } + + @Test + fun testGetIdentity() { + mockServer.mockResponseFor(MockEndpoint.GET_IDENTITIES) + runBlocking { + val result = flagsmith.getIdentitySync("person") + assertTrue(result.isSuccess) + assertTrue(result.getOrThrow().traits.isNotEmpty()) + assertTrue(result.getOrThrow().flags.isNotEmpty()) + assertEquals( + "electric pink", + result.getOrThrow().traits.find { trait -> trait.key == "favourite-colour" }?.stringValue + ) + } + } + + @Test + fun testGetTransientIdentity() { + mockServer.mockResponseFor(MockEndpoint.GET_TRANSIENT_IDENTITIES) + runBlocking { + val result = flagsmith.getIdentitySync("transient-identity", true) + assertTrue(result.isSuccess) + assertTrue(result.getOrThrow().traits.isNotEmpty()) + assertTrue(result.getOrThrow().flags.isNotEmpty()) + assertEquals( + "electric pink", + result.getOrThrow().traits.find { trait -> trait.key == "favourite-colour" }?.stringValue + ) + assertEquals(true, result.getOrThrow().flags.isNotEmpty()) + } + } +} diff --git a/FlagsmithClient/src/test/java/com/flagsmith/TraitsTests.kt b/FlagsmithClient/src/test/java/com/flagsmith/TraitsTests.kt index 873ca5d..7d33b58 100644 --- a/FlagsmithClient/src/test/java/com/flagsmith/TraitsTests.kt +++ b/FlagsmithClient/src/test/java/com/flagsmith/TraitsTests.kt @@ -168,35 +168,4 @@ class TraitsTests { assertEquals("person", result.getOrThrow().identity.identifier) } } - - @Test - fun testGetIdentity() { - mockServer.mockResponseFor(MockEndpoint.GET_IDENTITIES) - runBlocking { - val result = flagsmith.getIdentitySync("person") - assertTrue(result.isSuccess) - assertTrue(result.getOrThrow().traits.isNotEmpty()) - assertTrue(result.getOrThrow().flags.isNotEmpty()) - assertEquals( - "electric pink", - result.getOrThrow().traits.find { trait -> trait.key == "favourite-colour" }?.stringValue - ) - } - } - - @Test - fun testGetTransientIdentity() { - mockServer.mockResponseFor(MockEndpoint.GET_TRANSIENT_IDENTITIES) - runBlocking { - val result = flagsmith.getIdentitySync("transient-identity", true) - assertTrue(result.isSuccess) - assertTrue(result.getOrThrow().traits.isNotEmpty()) - assertTrue(result.getOrThrow().flags.isNotEmpty()) - assertEquals( - "electric pink", - result.getOrThrow().traits.find { trait -> trait.key == "favourite-colour" }?.stringValue - ) - assertEquals(true, result.getOrThrow().flags.isNotEmpty()) - } - } } From 0f31f7fc90baecfc7cc5cabf4232405b2a08a782 Mon Sep 17 00:00:00 2001 From: Matthew Elwell Date: Fri, 4 Oct 2024 12:37:09 +0100 Subject: [PATCH 09/21] Remove setTraits test with transiency --- .../test/java/com/flagsmith/TraitsTests.kt | 26 ------------------- 1 file changed, 26 deletions(-) diff --git a/FlagsmithClient/src/test/java/com/flagsmith/TraitsTests.kt b/FlagsmithClient/src/test/java/com/flagsmith/TraitsTests.kt index 7d33b58..22eaf8a 100644 --- a/FlagsmithClient/src/test/java/com/flagsmith/TraitsTests.kt +++ b/FlagsmithClient/src/test/java/com/flagsmith/TraitsTests.kt @@ -104,32 +104,6 @@ class TraitsTests { } } - @Test - fun testSetTraitsWithTransient() { - mockServer.mockResponseFor(MockEndpoint.SET_TRANSIENT_TRAITS) - runBlocking { - val result = - flagsmith.setTraitsSync( - listOf( - Trait( - key = "trait-one-with-transient", - value = "transient-trait-one", - transient = true - ), - Trait( - key = "trait-two", - value = "trait-two-value", - transient = false - ), - ), "identity-with-transient-traits") - assertTrue(result.isSuccess) - assertEquals("trait-one-with-transient", result.getOrThrow().first().key) - assertEquals("transient-trait-one", result.getOrThrow().first().stringValue) - assertEquals("identity-with-transient-traits", result.getOrThrow().first().identity.identifier) - assertEquals(true, result.getOrThrow().first().transient) - } - } - @Test fun testSetTraitInteger() { mockServer.mockResponseFor(MockEndpoint.SET_TRAIT_INTEGER) From 40c6d319965ce49372ad15835bffe575ed713db2 Mon Sep 17 00:00:00 2001 From: Matthew Elwell Date: Fri, 4 Oct 2024 12:41:02 +0100 Subject: [PATCH 10/21] Revert unnecessary changes to getTrait(s) --- .../src/main/java/com/flagsmith/Flagsmith.kt | 19 ++++--------------- 1 file changed, 4 insertions(+), 15 deletions(-) diff --git a/FlagsmithClient/src/main/java/com/flagsmith/Flagsmith.kt b/FlagsmithClient/src/main/java/com/flagsmith/Flagsmith.kt index f4cd976..06f4755 100644 --- a/FlagsmithClient/src/main/java/com/flagsmith/Flagsmith.kt +++ b/FlagsmithClient/src/main/java/com/flagsmith/Flagsmith.kt @@ -149,26 +149,15 @@ class Flagsmith constructor( result(res.map { flag -> flag?.featureStateValue }) } - fun getTrait( - id: String, - identity: String, - transient: Boolean? = null, - result: (Result) -> Unit - ) { - retrofit.getIdentityFlagsAndTraits(identity, transient).enqueueWithResult { res -> + fun getTrait(id: String, identity: String, result: (Result) -> Unit) = + retrofit.getIdentityFlagsAndTraits(identity).enqueueWithResult { res -> result(res.map { value -> value.traits.find { it.key == id } }) }.also { lastUsedIdentity = identity } - } - fun getTraits( - identity: String, - transient: Boolean? = null, - result: (Result>) -> Unit - ) { - retrofit.getIdentityFlagsAndTraits(identity, transient).enqueueWithResult { res -> + fun getTraits(identity: String, result: (Result>) -> Unit) = + retrofit.getIdentityFlagsAndTraits(identity).enqueueWithResult { res -> result(res.map { it.traits }) }.also { lastUsedIdentity = identity } - } fun setTrait(trait: Trait, identity: String, result: (Result) -> Unit) = retrofit.postTraits(IdentityAndTraits(identity, listOf(trait))) From 5b5bb89fc1fbd68b90a52edab8c7d3188961c209 Mon Sep 17 00:00:00 2001 From: Matthew Elwell Date: Fri, 4 Oct 2024 12:43:25 +0100 Subject: [PATCH 11/21] booleans don't need to be nullable --- FlagsmithClient/src/main/java/com/flagsmith/Flagsmith.kt | 4 ++-- .../java/com/flagsmith/internal/FlagsmithRetrofitService.kt | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/FlagsmithClient/src/main/java/com/flagsmith/Flagsmith.kt b/FlagsmithClient/src/main/java/com/flagsmith/Flagsmith.kt index 06f4755..6101f27 100644 --- a/FlagsmithClient/src/main/java/com/flagsmith/Flagsmith.kt +++ b/FlagsmithClient/src/main/java/com/flagsmith/Flagsmith.kt @@ -106,7 +106,7 @@ class Flagsmith constructor( const val DEFAULT_ANALYTICS_FLUSH_PERIOD_SECONDS = 10 } - fun getFeatureFlags(identity: String? = null, traits: List? = null, transient: Boolean? = null, result: (Result>) -> Unit) { + fun getFeatureFlags(identity: String? = null, traits: List? = null, transient: Boolean = false, result: (Result>) -> Unit) { // Save the last used identity as we'll refresh with this if we get update events lastUsedIdentity = identity @@ -181,7 +181,7 @@ class Flagsmith constructor( }) } - fun getIdentity(identity: String, transient: Boolean? = null, result: (Result) -> Unit) = + fun getIdentity(identity: String, transient: Boolean = false, result: (Result) -> Unit) = retrofit.getIdentityFlagsAndTraits(identity, transient).enqueueWithResult(defaults = null, result = result) .also { lastUsedIdentity = identity } diff --git a/FlagsmithClient/src/main/java/com/flagsmith/internal/FlagsmithRetrofitService.kt b/FlagsmithClient/src/main/java/com/flagsmith/internal/FlagsmithRetrofitService.kt index ba7b5c1..3826af8 100644 --- a/FlagsmithClient/src/main/java/com/flagsmith/internal/FlagsmithRetrofitService.kt +++ b/FlagsmithClient/src/main/java/com/flagsmith/internal/FlagsmithRetrofitService.kt @@ -19,7 +19,7 @@ import retrofit2.http.Query interface FlagsmithRetrofitService { @GET("identities/") - fun getIdentityFlagsAndTraits(@Query("identifier") identity: String, @Query("transient") transient: Boolean? = null) : Call + fun getIdentityFlagsAndTraits(@Query("identifier") identity: String, @Query("transient") transient: Boolean = false) : Call @GET("flags/") fun getFlags() : Call> From aed8b4c5a776a3b66396c0cca11aed73a78d7e23 Mon Sep 17 00:00:00 2001 From: Matthew Elwell Date: Fri, 4 Oct 2024 12:43:47 +0100 Subject: [PATCH 12/21] Revert unnecessary formatting change --- .../src/main/java/com/flagsmith/entities/Identity.kt | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/FlagsmithClient/src/main/java/com/flagsmith/entities/Identity.kt b/FlagsmithClient/src/main/java/com/flagsmith/entities/Identity.kt index a4ad0b5..6bd4a59 100644 --- a/FlagsmithClient/src/main/java/com/flagsmith/entities/Identity.kt +++ b/FlagsmithClient/src/main/java/com/flagsmith/entities/Identity.kt @@ -1,5 +1,5 @@ package com.flagsmith.entities data class Identity( - val identifier: String, -) \ No newline at end of file + val identifier: String +) From fbf080cebf7e9cd85440aac1dea955b4430a1516 Mon Sep 17 00:00:00 2001 From: Matthew Elwell Date: Fri, 4 Oct 2024 12:44:06 +0100 Subject: [PATCH 13/21] Remove unnecessary formatting change --- .../java/com/flagsmith/entities/IdentityFlagsAndTraits.kt | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/FlagsmithClient/src/main/java/com/flagsmith/entities/IdentityFlagsAndTraits.kt b/FlagsmithClient/src/main/java/com/flagsmith/entities/IdentityFlagsAndTraits.kt index 2305a6f..2f73324 100644 --- a/FlagsmithClient/src/main/java/com/flagsmith/entities/IdentityFlagsAndTraits.kt +++ b/FlagsmithClient/src/main/java/com/flagsmith/entities/IdentityFlagsAndTraits.kt @@ -2,5 +2,5 @@ package com.flagsmith.entities data class IdentityFlagsAndTraits( val flags: ArrayList, - val traits: ArrayList, -) \ No newline at end of file + val traits: ArrayList +) From 6fd0837153300b21671b834ef9e63656bce6ef45 Mon Sep 17 00:00:00 2001 From: Matthew Elwell Date: Fri, 4 Oct 2024 12:45:18 +0100 Subject: [PATCH 14/21] More instances of unncessary null booleans --- .../main/java/com/flagsmith/entities/Trait.kt | 20 +++++++++---------- 1 file changed, 10 insertions(+), 10 deletions(-) diff --git a/FlagsmithClient/src/main/java/com/flagsmith/entities/Trait.kt b/FlagsmithClient/src/main/java/com/flagsmith/entities/Trait.kt index ca8579f..e68a3d7 100644 --- a/FlagsmithClient/src/main/java/com/flagsmith/entities/Trait.kt +++ b/FlagsmithClient/src/main/java/com/flagsmith/entities/Trait.kt @@ -8,19 +8,19 @@ data class Trait ( val identifier: String? = null, @SerializedName(value = "trait_key") val key: String, @SerializedName(value = "trait_value") val traitValue: Any, - val transient: Boolean? = null + val transient: Boolean = false ) { - constructor(key: String, value: String, transient: Boolean? = null) + constructor(key: String, value: String, transient: Boolean = false) : this(key = key, traitValue = value, transient = transient) - constructor(key: String, value: Int, transient: Boolean? = null) + constructor(key: String, value: Int, transient: Boolean = false) : this(key = key, traitValue = value, transient = transient) - constructor(key: String, value: Double, transient: Boolean? = null) + constructor(key: String, value: Double, transient: Boolean = false) : this(key = key, traitValue = value, transient = transient) - constructor(key: String, value: Boolean, transient: Boolean? = null) + constructor(key: String, value: Boolean, transient: Boolean = false) : this(key = key, traitValue = value, transient = transient) @Deprecated("Use traitValue instead or one of the type-safe getters", ReplaceWith("traitValue")) @@ -50,18 +50,18 @@ data class TraitWithIdentity ( @SerializedName(value = "trait_key") val key: String, @SerializedName(value = "trait_value") val traitValue: Any, val identity: Identity, - val transient: Boolean? = null + val transient: Boolean = false ) { - constructor(key: String, value: String, identity: Identity, transient: Boolean? = null) + constructor(key: String, value: String, identity: Identity, transient: Boolean = false) : this(key = key, traitValue = value, identity = identity, transient = transient) - constructor(key: String, value: Int, identity: Identity, transient: Boolean? = null) + constructor(key: String, value: Int, identity: Identity, transient: Boolean = false) : this(key = key, traitValue = value, identity = identity, transient = transient) - constructor(key: String, value: Double, identity: Identity, transient: Boolean? = null) + constructor(key: String, value: Double, identity: Identity, transient: Boolean = false) : this(key = key, traitValue = value, identity = identity, transient = transient) - constructor(key: String, value: Boolean, identity: Identity, transient: Boolean? = null) + constructor(key: String, value: Boolean, identity: Identity, transient: Boolean = false) : this(key = key, traitValue = value, identity = identity, transient = transient) @Deprecated("Use traitValue instead or one of the type-safe getters", ReplaceWith("traitValue")) From 608f43d10684e07bdbc62ed44203f26d24509773 Mon Sep 17 00:00:00 2001 From: Matthew Elwell Date: Fri, 4 Oct 2024 12:46:59 +0100 Subject: [PATCH 15/21] Final nullable boolean removal --- .../com/flagsmith/mockResponses/endpoints/TraitsEndpoint.kt | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/FlagsmithClient/src/test/java/com/flagsmith/mockResponses/endpoints/TraitsEndpoint.kt b/FlagsmithClient/src/test/java/com/flagsmith/mockResponses/endpoints/TraitsEndpoint.kt index fbab66f..4582d13 100644 --- a/FlagsmithClient/src/test/java/com/flagsmith/mockResponses/endpoints/TraitsEndpoint.kt +++ b/FlagsmithClient/src/test/java/com/flagsmith/mockResponses/endpoints/TraitsEndpoint.kt @@ -5,7 +5,7 @@ import com.flagsmith.entities.Trait import com.flagsmith.entities.TraitWithIdentity import com.google.gson.Gson -data class TraitsEndpoint(private val trait: Trait, private val identity: String, private val transient: Boolean? = null) : +data class TraitsEndpoint(private val trait: Trait, private val identity: String, private val transient: Boolean = false) : PostEndpoint( path = "/identities/", body = Gson().toJson( @@ -15,4 +15,4 @@ data class TraitsEndpoint(private val trait: Trait, private val identity: String transient = transient, ) ), - ) \ No newline at end of file + ) From dbb4c0792d2ba231bcbc68ffb1f32c05311f5a95 Mon Sep 17 00:00:00 2001 From: Matthew Elwell Date: Fri, 4 Oct 2024 12:47:08 +0100 Subject: [PATCH 16/21] Remove unnecessary mock response --- .../flagsmith/mockResponses/MockResponses.kt | 22 +------------------ 1 file changed, 1 insertion(+), 21 deletions(-) diff --git a/FlagsmithClient/src/test/java/com/flagsmith/mockResponses/MockResponses.kt b/FlagsmithClient/src/test/java/com/flagsmith/mockResponses/MockResponses.kt index faf6e26..b791f75 100644 --- a/FlagsmithClient/src/test/java/com/flagsmith/mockResponses/MockResponses.kt +++ b/FlagsmithClient/src/test/java/com/flagsmith/mockResponses/MockResponses.kt @@ -18,7 +18,6 @@ enum class MockEndpoint(val path: String, val body: String) { GET_FLAGS(FlagsEndpoint.path, MockResponses.getFlags), SET_TRAIT(TraitsEndpoint(Trait(key = "", traitValue = ""), "").path, MockResponses.setTrait), SET_TRAITS(TraitsBulkEndpoint(listOf(Trait(key = "", traitValue = "")), "").path, MockResponses.setTraits), - SET_TRANSIENT_TRAITS(TraitsBulkEndpoint(listOf(Trait(key = "", traitValue = "")), "").path, MockResponses.setTransientTraits), GET_TRANSIENT_IDENTITIES(IdentityFlagsAndTraitsEndpoint("").path, MockResponses.getTransientIdentities), SET_TRAIT_INTEGER(TraitsEndpoint(Trait(key = "", traitValue = ""), "").path, MockResponses.setTraitInteger), SET_TRAIT_DOUBLE(TraitsEndpoint(Trait(key = "", traitValue = ""), "").path, MockResponses.setTraitDouble), @@ -202,25 +201,6 @@ object MockResponses { } """.trimIndent() - val setTransientTraits = """ - { - "identifier": "identity-with-transient-traits", - "flags": [], - "traits": [ - { - "trait_value": "transient-trait-one", - "trait_key": "trait-one-with-transient", - "transient": true - }, - { - "trait_value": "transient-trait-two", - "trait_key": "trait-two-with-transient", - "transient": false - } - ] - } - """.trimIndent() - val setTraits = """ { "identifier": "person", @@ -448,4 +428,4 @@ object MockResponses { ] } """.trimIndent() -} \ No newline at end of file +} From 2d62268d349e56c7ed09e20567c6b2252c2f4478 Mon Sep 17 00:00:00 2001 From: Matthew Elwell Date: Fri, 4 Oct 2024 12:51:00 +0100 Subject: [PATCH 17/21] Fix compilation error --- .../src/test/java/com/flagsmith/SynchronousFlagsmith.kt | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/FlagsmithClient/src/test/java/com/flagsmith/SynchronousFlagsmith.kt b/FlagsmithClient/src/test/java/com/flagsmith/SynchronousFlagsmith.kt index 03e2d40..3b9067e 100644 --- a/FlagsmithClient/src/test/java/com/flagsmith/SynchronousFlagsmith.kt +++ b/FlagsmithClient/src/test/java/com/flagsmith/SynchronousFlagsmith.kt @@ -25,8 +25,8 @@ suspend fun Flagsmith.getTraitSync(id: String, identity: String): Result suspend fun Flagsmith.setTraitSync(trait: Trait, identity: String) : Result = suspendCoroutine { cont -> this.setTrait(trait, identity) { cont.resume(it) } } -suspend fun Flagsmith.setTraitsSync(traits: List, identity: String, transient: Boolean = false) : Result> - = suspendCoroutine { cont -> this.setTraits(traits, identity, transient) { cont.resume(it) } } +suspend fun Flagsmith.setTraitsSync(traits: List, identity: String) : Result> + = suspendCoroutine { cont -> this.setTraits(traits, identity) { cont.resume(it) } } suspend fun Flagsmith.getIdentitySync(identity: String, transient: Boolean = false): Result = suspendCoroutine { cont -> this.getIdentity(identity, transient) { cont.resume(it) } } From 95b6de05489cfbf907157470a52f5b064bea97af Mon Sep 17 00:00:00 2001 From: Matthew Elwell Date: Fri, 4 Oct 2024 12:53:52 +0100 Subject: [PATCH 18/21] Minor changes to mock responses --- .../flagsmith/mockResponses/MockResponses.kt | 17 ++++++++++------- 1 file changed, 10 insertions(+), 7 deletions(-) diff --git a/FlagsmithClient/src/test/java/com/flagsmith/mockResponses/MockResponses.kt b/FlagsmithClient/src/test/java/com/flagsmith/mockResponses/MockResponses.kt index b791f75..1d1eb2e 100644 --- a/FlagsmithClient/src/test/java/com/flagsmith/mockResponses/MockResponses.kt +++ b/FlagsmithClient/src/test/java/com/flagsmith/mockResponses/MockResponses.kt @@ -117,11 +117,13 @@ object MockResponses { "traits": [ { "trait_value": "12345", - "trait_key": "set-from-client" + "trait_key": "set-from-client", + "transient": false }, { "trait_value": "electric pink", - "trait_key": "favourite-colour" + "trait_key": "favourite-colour", + "transient": false } ] } @@ -144,15 +146,14 @@ object MockResponses { { "trait_value": "12345", "trait_key": "set-from-client", - "transient": false + "transient": true }, { "trait_value": "electric pink", "trait_key": "favourite-colour", "transient": true } - ], - "transient": true + ] } """.trimIndent() @@ -195,7 +196,8 @@ object MockResponses { "traits": [ { "trait_value": "12345", - "trait_key": "set-from-client" + "trait_key": "set-from-client", + "transient": false } ] } @@ -208,7 +210,8 @@ object MockResponses { "traits": [ { "trait_value": "12345", - "trait_key": "set-from-client" + "trait_key": "set-from-client", + "transient": false } ] } From 8c0b69a1ded4ab0d6e2bbcd810ffd2d54de3e979 Mon Sep 17 00:00:00 2001 From: Matthew Elwell Date: Fri, 4 Oct 2024 12:56:13 +0100 Subject: [PATCH 19/21] Remove duplicate assert --- FlagsmithClient/src/test/java/com/flagsmith/IdentityTests.kt | 1 - 1 file changed, 1 deletion(-) diff --git a/FlagsmithClient/src/test/java/com/flagsmith/IdentityTests.kt b/FlagsmithClient/src/test/java/com/flagsmith/IdentityTests.kt index 6c6e8d4..bea5edb 100644 --- a/FlagsmithClient/src/test/java/com/flagsmith/IdentityTests.kt +++ b/FlagsmithClient/src/test/java/com/flagsmith/IdentityTests.kt @@ -60,7 +60,6 @@ class IdentityTests { "electric pink", result.getOrThrow().traits.find { trait -> trait.key == "favourite-colour" }?.stringValue ) - assertEquals(true, result.getOrThrow().flags.isNotEmpty()) } } } From f939fba0f22018ff5e269df9dfa7f92e0c401832 Mon Sep 17 00:00:00 2001 From: Matthew Elwell Date: Fri, 4 Oct 2024 13:06:43 +0100 Subject: [PATCH 20/21] Revert changes to entities --- .../src/main/java/com/flagsmith/entities/Identity.kt | 2 +- .../main/java/com/flagsmith/entities/IdentityFlagsAndTraits.kt | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/FlagsmithClient/src/main/java/com/flagsmith/entities/Identity.kt b/FlagsmithClient/src/main/java/com/flagsmith/entities/Identity.kt index 6bd4a59..93e81f6 100644 --- a/FlagsmithClient/src/main/java/com/flagsmith/entities/Identity.kt +++ b/FlagsmithClient/src/main/java/com/flagsmith/entities/Identity.kt @@ -2,4 +2,4 @@ package com.flagsmith.entities data class Identity( val identifier: String -) +) \ No newline at end of file diff --git a/FlagsmithClient/src/main/java/com/flagsmith/entities/IdentityFlagsAndTraits.kt b/FlagsmithClient/src/main/java/com/flagsmith/entities/IdentityFlagsAndTraits.kt index 2f73324..365ccdf 100644 --- a/FlagsmithClient/src/main/java/com/flagsmith/entities/IdentityFlagsAndTraits.kt +++ b/FlagsmithClient/src/main/java/com/flagsmith/entities/IdentityFlagsAndTraits.kt @@ -3,4 +3,4 @@ package com.flagsmith.entities data class IdentityFlagsAndTraits( val flags: ArrayList, val traits: ArrayList -) +) \ No newline at end of file From 23cf1e937e676d7d18f0b70d81e0df4876fe3a9f Mon Sep 17 00:00:00 2001 From: Matthew Elwell Date: Fri, 4 Oct 2024 17:58:35 +0100 Subject: [PATCH 21/21] Add more tests --- .../internal/FlagsmithRetrofitService.kt | 1 + .../java/com/flagsmith/FeatureFlagTests.kt | 85 +++++++++++++++++++ .../test/java/com/flagsmith/IdentityTests.kt | 25 ++++-- .../com/flagsmith/SynchronousFlagsmith.kt | 4 +- .../flagsmith/mockResponses/MockResponses.kt | 33 +++++-- 5 files changed, 135 insertions(+), 13 deletions(-) diff --git a/FlagsmithClient/src/main/java/com/flagsmith/internal/FlagsmithRetrofitService.kt b/FlagsmithClient/src/main/java/com/flagsmith/internal/FlagsmithRetrofitService.kt index 3826af8..1a43011 100644 --- a/FlagsmithClient/src/main/java/com/flagsmith/internal/FlagsmithRetrofitService.kt +++ b/FlagsmithClient/src/main/java/com/flagsmith/internal/FlagsmithRetrofitService.kt @@ -24,6 +24,7 @@ interface FlagsmithRetrofitService { @GET("flags/") fun getFlags() : Call> + // todo: rename this function @POST("identities/") fun postTraits(@Body identity: IdentityAndTraits) : Call diff --git a/FlagsmithClient/src/test/java/com/flagsmith/FeatureFlagTests.kt b/FlagsmithClient/src/test/java/com/flagsmith/FeatureFlagTests.kt index a6daeda..b9c8962 100644 --- a/FlagsmithClient/src/test/java/com/flagsmith/FeatureFlagTests.kt +++ b/FlagsmithClient/src/test/java/com/flagsmith/FeatureFlagTests.kt @@ -1,6 +1,8 @@ package com.flagsmith +import com.flagsmith.entities.Trait import com.flagsmith.mockResponses.MockEndpoint +import com.flagsmith.mockResponses.MockResponses import com.flagsmith.mockResponses.mockResponseFor import kotlinx.coroutines.runBlocking import org.junit.After @@ -13,6 +15,9 @@ import org.junit.Assert.assertTrue import org.junit.Before import org.junit.Test import org.mockserver.integration.ClientAndServer +import org.mockserver.model.HttpRequest.request +import org.mockserver.model.HttpResponse.response +import org.mockserver.model.JsonBody.json class FeatureFlagTests { @@ -157,4 +162,84 @@ class FeatureFlagTests { assertEquals(756.0, found?.featureStateValue) } } + + @Test + fun testGetFeatureFlagsWithTransientTraits() { + mockServer.`when`( + request() + .withPath("/identities/") + .withMethod("POST") + .withBody( + json( + """ + { + "identifier": "identity", + "traits": [ + { + "trait_key": "transient-trait", + "trait_value": "value", + "transient": true + }, + { + "trait_key": "persisted-trait", + "trait_value": "value", + "transient": false + } + ], + "transient": false + } + """.trimIndent() + ) + ) + ) + .respond( + response() + .withStatusCode(200) + .withBody(MockResponses.getTransientIdentities) + ) + + runBlocking { + val transientTrait = Trait("transient-trait", "value", true) + val persistedTrait = Trait("persisted-trait", "value", false) + val result = flagsmith.getFeatureFlagsSync( + "identity", + listOf(transientTrait, persistedTrait), + false, + ) + + assertTrue(result.isSuccess) + } + } + + @Test + fun testGetFeatureFlagsWithTransientIdentity() { + mockServer.`when`( + request() + .withPath("/identities/") + .withMethod("POST") + .withBody( + json( + """ + { + "identifier": "identity", + "traits": [], + "transient": true + } + """.trimIndent() + ) + ) + ) + .respond( + response() + .withStatusCode(200) + .withBody(MockResponses.getTransientIdentities) + ) + + runBlocking { + val result = flagsmith.getFeatureFlagsSync( + "identity", listOf(),true, + ) + assertTrue(result.isSuccess) + } + } } \ No newline at end of file diff --git a/FlagsmithClient/src/test/java/com/flagsmith/IdentityTests.kt b/FlagsmithClient/src/test/java/com/flagsmith/IdentityTests.kt index bea5edb..7a6c9c4 100644 --- a/FlagsmithClient/src/test/java/com/flagsmith/IdentityTests.kt +++ b/FlagsmithClient/src/test/java/com/flagsmith/IdentityTests.kt @@ -2,6 +2,7 @@ package com.flagsmith import com.flagsmith.entities.Trait import com.flagsmith.mockResponses.MockEndpoint +import com.flagsmith.mockResponses.MockResponses import com.flagsmith.mockResponses.mockResponseFor import kotlinx.coroutines.runBlocking import org.junit.After @@ -11,6 +12,7 @@ import org.junit.Assert.assertTrue import org.junit.Before import org.junit.Test import org.mockserver.integration.ClientAndServer +import org.mockserver.model.HttpRequest.request class IdentityTests { @@ -38,6 +40,14 @@ class IdentityTests { mockServer.mockResponseFor(MockEndpoint.GET_IDENTITIES) runBlocking { val result = flagsmith.getIdentitySync("person") + + mockServer.verify( + request() + .withPath("/identities/") + .withMethod("GET") + .withQueryStringParameter("identifier", "person") + ) + assertTrue(result.isSuccess) assertTrue(result.getOrThrow().traits.isNotEmpty()) assertTrue(result.getOrThrow().flags.isNotEmpty()) @@ -53,13 +63,18 @@ class IdentityTests { mockServer.mockResponseFor(MockEndpoint.GET_TRANSIENT_IDENTITIES) runBlocking { val result = flagsmith.getIdentitySync("transient-identity", true) + + mockServer.verify( + request() + .withPath("/identities/") + .withMethod("GET") + .withQueryStringParameter("identifier", "transient-identity") + .withQueryStringParameter("transient", "true") + ) + assertTrue(result.isSuccess) - assertTrue(result.getOrThrow().traits.isNotEmpty()) + assertTrue(result.getOrThrow().traits.isEmpty()) assertTrue(result.getOrThrow().flags.isNotEmpty()) - assertEquals( - "electric pink", - result.getOrThrow().traits.find { trait -> trait.key == "favourite-colour" }?.stringValue - ) } } } diff --git a/FlagsmithClient/src/test/java/com/flagsmith/SynchronousFlagsmith.kt b/FlagsmithClient/src/test/java/com/flagsmith/SynchronousFlagsmith.kt index 3b9067e..8667d5a 100644 --- a/FlagsmithClient/src/test/java/com/flagsmith/SynchronousFlagsmith.kt +++ b/FlagsmithClient/src/test/java/com/flagsmith/SynchronousFlagsmith.kt @@ -10,8 +10,8 @@ import kotlin.coroutines.suspendCoroutine suspend fun Flagsmith.hasFeatureFlagSync(forFeatureId: String, identity: String? = null): Result = suspendCoroutine { cont -> this.hasFeatureFlag(forFeatureId, identity = identity) { cont.resume(it) } } -suspend fun Flagsmith.getFeatureFlagsSync(identity: String? = null, traits: List? = null) : Result> - = suspendCoroutine { cont -> this.getFeatureFlags(identity = identity, traits = traits) { cont.resume(it) } } +suspend fun Flagsmith.getFeatureFlagsSync(identity: String? = null, traits: List? = null, transient: Boolean = false) : Result> + = suspendCoroutine { cont -> this.getFeatureFlags(identity = identity, traits = traits, transient = transient) { cont.resume(it) } } suspend fun Flagsmith.getValueForFeatureSync(forFeatureId: String, identity: String? = null): Result = suspendCoroutine { cont -> this.getValueForFeature(forFeatureId, identity = identity) { cont.resume(it) } } diff --git a/FlagsmithClient/src/test/java/com/flagsmith/mockResponses/MockResponses.kt b/FlagsmithClient/src/test/java/com/flagsmith/mockResponses/MockResponses.kt index 1d1eb2e..5164e63 100644 --- a/FlagsmithClient/src/test/java/com/flagsmith/mockResponses/MockResponses.kt +++ b/FlagsmithClient/src/test/java/com/flagsmith/mockResponses/MockResponses.kt @@ -38,6 +38,10 @@ enum class MockEndpoint(val path: String, val body: String) { IdentityFlagsAndTraitsEndpoint("").path, MockResponses.getTraitBoolean ), + POST_TRANSIENT_TRAITS( + IdentityFlagsAndTraitsEndpoint("").path, + MockResponses.postTransientIdentities + ), } fun ClientAndServer.mockResponseFor(endpoint: MockEndpoint) { @@ -130,6 +134,23 @@ object MockResponses { """.trimIndent() val getTransientIdentities = """ + { + "flags": [ + { + "feature_state_value": null, + "feature": { + "type": "STANDARD", + "name": "no-value", + "id": 35506 + }, + "enabled": true + } + ], + "traits": [] + } + """.trimIndent() + + val postTransientIdentities = """ { "flags": [ { @@ -144,14 +165,14 @@ object MockResponses { ], "traits": [ { - "trait_value": "12345", - "trait_key": "set-from-client", - "transient": true + "trait_key": "persisted-trait", + "trait_value": "value", + "transient": false }, { - "trait_value": "electric pink", - "trait_key": "favourite-colour", - "transient": true + "trait_key": "transient-trait", + "trait_value": "value", + "transient": true, } ] }