From 39b6a68bb4b6238ed602a0eaaa69db757fbb06ca Mon Sep 17 00:00:00 2001 From: toluo-stripe Date: Wed, 22 Jan 2025 14:09:03 -0500 Subject: [PATCH] Link Gate to determine link behaviour --- .../settings/LinkTypeSettingsDefinition.kt | 44 +++++++++ .../playground/settings/PlaygroundSettings.kt | 2 +- .../android/link/gate/DefaultLinkGate.kt | 20 ++++ .../com/stripe/android/link/gate/LinkGate.kt | 6 ++ .../android/link/gate/DefaultLinkGateTest.kt | 91 +++++++++++++++++++ .../stripe/android/link/gate/FakeLinkGate.kt | 19 ++++ .../stripe/android/core/utils/FeatureFlags.kt | 1 + 7 files changed, 182 insertions(+), 1 deletion(-) create mode 100644 paymentsheet-example/src/main/java/com/stripe/android/paymentsheet/example/playground/settings/LinkTypeSettingsDefinition.kt create mode 100644 paymentsheet/src/main/java/com/stripe/android/link/gate/DefaultLinkGate.kt create mode 100644 paymentsheet/src/main/java/com/stripe/android/link/gate/LinkGate.kt create mode 100644 paymentsheet/src/test/java/com/stripe/android/link/gate/DefaultLinkGateTest.kt create mode 100644 paymentsheet/src/test/java/com/stripe/android/link/gate/FakeLinkGate.kt diff --git a/paymentsheet-example/src/main/java/com/stripe/android/paymentsheet/example/playground/settings/LinkTypeSettingsDefinition.kt b/paymentsheet-example/src/main/java/com/stripe/android/paymentsheet/example/playground/settings/LinkTypeSettingsDefinition.kt new file mode 100644 index 00000000000..48fe2d7d95d --- /dev/null +++ b/paymentsheet-example/src/main/java/com/stripe/android/paymentsheet/example/playground/settings/LinkTypeSettingsDefinition.kt @@ -0,0 +1,44 @@ +package com.stripe.android.paymentsheet.example.playground.settings + +import com.stripe.android.core.utils.FeatureFlags + +internal object LinkTypeSettingsDefinition : PlaygroundSettingDefinition, + PlaygroundSettingDefinition.Saveable by EnumSaveable( + key = "LinkType", + values = LinkType.entries.toTypedArray(), + defaultValue = LinkType.Native + ), + PlaygroundSettingDefinition.Displayable { + override val displayName: String = "LinkType" + + override fun createOptions(configurationData: PlaygroundConfigurationData): List> { + return listOf( + option("Native", LinkType.Native), + option("Native + Attest", LinkType.NativeAttest), + option("Web", LinkType.Web), + ) + } + + override fun setValue(value: LinkType) { + when (value) { + LinkType.Native -> { + FeatureFlags.nativeLinkEnabled.setEnabled(true) + FeatureFlags.nativeLinkAttestationEnabled.setEnabled(false) + } + LinkType.NativeAttest -> { + FeatureFlags.nativeLinkEnabled.setEnabled(true) + FeatureFlags.nativeLinkAttestationEnabled.setEnabled(true) + } + LinkType.Web -> { + FeatureFlags.nativeLinkEnabled.setEnabled(false) + FeatureFlags.nativeLinkAttestationEnabled.setEnabled(false) + } + } + } +} + +enum class LinkType(override val value: String) : ValueEnum { + Native("Native"), + NativeAttest("Native + Attest"), + Web("Web"), +} diff --git a/paymentsheet-example/src/main/java/com/stripe/android/paymentsheet/example/playground/settings/PlaygroundSettings.kt b/paymentsheet-example/src/main/java/com/stripe/android/paymentsheet/example/playground/settings/PlaygroundSettings.kt index e76e09d5f86..2c5d8219227 100644 --- a/paymentsheet-example/src/main/java/com/stripe/android/paymentsheet/example/playground/settings/PlaygroundSettings.kt +++ b/paymentsheet-example/src/main/java/com/stripe/android/paymentsheet/example/playground/settings/PlaygroundSettings.kt @@ -425,7 +425,7 @@ internal class PlaygroundSettings private constructor( CustomerSettingsDefinition, CheckoutModeSettingsDefinition, LinkSettingsDefinition, - FeatureFlagSettingsDefinition(FeatureFlags.nativeLinkEnabled), + LinkTypeSettingsDefinition, CountrySettingsDefinition, CurrencySettingsDefinition, GooglePaySettingsDefinition, diff --git a/paymentsheet/src/main/java/com/stripe/android/link/gate/DefaultLinkGate.kt b/paymentsheet/src/main/java/com/stripe/android/link/gate/DefaultLinkGate.kt new file mode 100644 index 00000000000..04c66d48699 --- /dev/null +++ b/paymentsheet/src/main/java/com/stripe/android/link/gate/DefaultLinkGate.kt @@ -0,0 +1,20 @@ +package com.stripe.android.link.gate + +import com.stripe.android.core.utils.FeatureFlags +import com.stripe.android.link.LinkConfiguration + +internal class DefaultLinkGate( + private val configuration: LinkConfiguration +) : LinkGate { + override val useNativeLink: Boolean + get() { + if (FeatureFlags.nativeLinkEnabled.isEnabled) return true + return useAttestationEndpoints + } + + override val useAttestationEndpoints: Boolean + get() { + if (FeatureFlags.nativeLinkAttestationEnabled.isEnabled) return true + return configuration.useAttestationEndpointsForLink + } +} diff --git a/paymentsheet/src/main/java/com/stripe/android/link/gate/LinkGate.kt b/paymentsheet/src/main/java/com/stripe/android/link/gate/LinkGate.kt new file mode 100644 index 00000000000..740679adfef --- /dev/null +++ b/paymentsheet/src/main/java/com/stripe/android/link/gate/LinkGate.kt @@ -0,0 +1,6 @@ +package com.stripe.android.link.gate + +internal interface LinkGate { + val useNativeLink: Boolean + val useAttestationEndpoints: Boolean +} diff --git a/paymentsheet/src/test/java/com/stripe/android/link/gate/DefaultLinkGateTest.kt b/paymentsheet/src/test/java/com/stripe/android/link/gate/DefaultLinkGateTest.kt new file mode 100644 index 00000000000..a7ee6ee87f1 --- /dev/null +++ b/paymentsheet/src/test/java/com/stripe/android/link/gate/DefaultLinkGateTest.kt @@ -0,0 +1,91 @@ +package com.stripe.android.link.gate + +import com.google.common.truth.Truth.assertThat +import com.stripe.android.core.utils.FeatureFlags +import com.stripe.android.link.TestFactory +import com.stripe.android.testing.FeatureFlagTestRule +import org.junit.Rule +import org.junit.Test +import org.junit.runner.RunWith +import org.robolectric.RobolectricTestRunner + +@RunWith(RobolectricTestRunner::class) +internal class DefaultLinkGateTest { + + @get:Rule + val nativeLinkFeatureFlagTestRule = FeatureFlagTestRule( + featureFlag = FeatureFlags.nativeLinkEnabled, + isEnabled = false + ) + + @get:Rule + val attestationFeatureFlagTestRule = FeatureFlagTestRule( + featureFlag = FeatureFlags.nativeLinkAttestationEnabled, + isEnabled = false + ) + + @Test + fun `useNativeLink is true when nativeLinkFeatureFlag is enabled`() { + nativeLinkFeatureFlagTestRule.setEnabled(true) + val gate = gate() + + assertThat(gate.useNativeLink).isTrue() + } + + @Test + fun `useNativeLink is true when nativeLinkFeatureFlag is enabled regardless of other settings`() { + nativeLinkFeatureFlagTestRule.setEnabled(true) + attestationFeatureFlagTestRule.setEnabled(false) + + val gate = gate(useAttestationEndpoints = false) + + assertThat(gate.useNativeLink).isTrue() + } + + @Test + fun `useNativeLink reflects useAttestationEndpoints when nativeLinkFeatureFlag is disabled`() { + nativeLinkFeatureFlagTestRule.setEnabled(false) + attestationFeatureFlagTestRule.setEnabled(true) + + val gate = gate() + + assertThat(gate.useNativeLink).isEqualTo(gate.useAttestationEndpoints) + } + + @Test + fun `useAttestationEndpoints is true when attestationFeatureFlag is enabled`() { + attestationFeatureFlagTestRule.setEnabled(true) + + val gate = gate() + + assertThat(gate.useAttestationEndpoints).isTrue() + } + + @Test + fun `useAttestationEndpoints is true when attestationFeatureFlag is enabled regardless of configuration`() { + attestationFeatureFlagTestRule.setEnabled(true) + + val gate = gate(useAttestationEndpoints = false) + + assertThat(gate.useAttestationEndpoints).isTrue() + } + + @Test + fun `useAttestationEndpoints reflects configuration when attestationFeatureFlag is disabled`() { + attestationFeatureFlagTestRule.setEnabled(false) + + val gateTrue = gate(useAttestationEndpoints = true) + val gateFalse = gate(useAttestationEndpoints = false) + + assertThat(gateTrue.useAttestationEndpoints).isTrue() + assertThat(gateFalse.useAttestationEndpoints).isFalse() + } + + private fun gate(useAttestationEndpoints: Boolean = true): DefaultLinkGate { + return DefaultLinkGate( + configuration = TestFactory.LINK_CONFIGURATION.copy( + useAttestationEndpointsForLink = useAttestationEndpoints + ) + ) + } +} diff --git a/paymentsheet/src/test/java/com/stripe/android/link/gate/FakeLinkGate.kt b/paymentsheet/src/test/java/com/stripe/android/link/gate/FakeLinkGate.kt new file mode 100644 index 00000000000..64d2de56687 --- /dev/null +++ b/paymentsheet/src/test/java/com/stripe/android/link/gate/FakeLinkGate.kt @@ -0,0 +1,19 @@ +package com.stripe.android.link.gate + +internal class FakeLinkGate : LinkGate { + private var _useNativeLink = true + override val useNativeLink: Boolean + get() = _useNativeLink + + private var _useAttestationEndpoints = true + override val useAttestationEndpoints: Boolean + get() = _useAttestationEndpoints + + fun setUseNativeLink(value: Boolean) { + _useNativeLink = value + } + + fun setUseAttestationEndpoints(value: Boolean) { + _useAttestationEndpoints = value + } +} diff --git a/stripe-core/src/main/java/com/stripe/android/core/utils/FeatureFlags.kt b/stripe-core/src/main/java/com/stripe/android/core/utils/FeatureFlags.kt index 54de3694fea..b4d4f723b6c 100644 --- a/stripe-core/src/main/java/com/stripe/android/core/utils/FeatureFlags.kt +++ b/stripe-core/src/main/java/com/stripe/android/core/utils/FeatureFlags.kt @@ -7,6 +7,7 @@ import com.stripe.android.core.BuildConfig object FeatureFlags { // Add any feature flags here val nativeLinkEnabled = FeatureFlag("Native Link") + val nativeLinkAttestationEnabled = FeatureFlag("Native Link Attestation") val instantDebitsIncentives = FeatureFlag("Instant Bank Payments Incentives") val enableDefaultPaymentMethods = FeatureFlag("Enable Default Payment Methods") }