Skip to content

Commit 2a80e82

Browse files
nbradburyadalpari
andauthored
Make experimental features testable (#21902)
* Moved feature enum inside of ExperimentalFeatures class * Adjusted other experimental features classes to adjust for previous commit * Adjusted EditPostActivity and SelectedSiteRepository for changes to experimental features * Fixed missing param in SelectedSiteRepositoryTest * Updated SelectedSiteRepositoryTest to no longer mock shared prefs --------- Co-authored-by: Adalberto Plaza <[email protected]>
1 parent c071554 commit 2a80e82

File tree

9 files changed

+88
-83
lines changed

9 files changed

+88
-83
lines changed

WordPress/src/main/java/org/wordpress/android/ui/mysite/SelectedSiteRepository.kt

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -12,8 +12,9 @@ import org.wordpress.android.fluxc.store.EditorSettingsStore.FetchEditorSettings
1212
import org.wordpress.android.fluxc.store.EditorThemeStore
1313
import org.wordpress.android.ui.prefs.AppPrefs
1414
import org.wordpress.android.ui.prefs.AppPrefsWrapper
15-
import org.wordpress.android.ui.prefs.experimentalfeatures.ExperimentalFeature
15+
import org.wordpress.android.ui.prefs.experimentalfeatures.ExperimentalFeatures.Feature
1616
import org.wordpress.android.ui.prefs.SiteSettingsInterfaceWrapper
17+
import org.wordpress.android.ui.prefs.experimentalfeatures.ExperimentalFeatures
1718
import org.wordpress.android.util.config.GutenbergKitFeature
1819
import org.wordpress.android.util.mapSafe
1920
import javax.inject.Inject
@@ -24,6 +25,7 @@ class SelectedSiteRepository @Inject constructor(
2425
private val dispatcher: Dispatcher,
2526
private val siteSettingsInterfaceFactory: SiteSettingsInterfaceWrapper.Factory,
2627
private val appPrefsWrapper: AppPrefsWrapper,
28+
private val experimentalFeatures: ExperimentalFeatures,
2729
) {
2830
private var siteSettings: SiteSettingsInterfaceWrapper? = null
2931

@@ -136,7 +138,8 @@ class SelectedSiteRepository @Inject constructor(
136138
}
137139

138140
// Fetch the site's editor theme and settings
139-
if (ExperimentalFeature.EXPERIMENTAL_BLOCK_EDITOR.isEnabled() || gutenbergKitFeature.isEnabled()) {
141+
if (experimentalFeatures.isEnabled(Feature.EXPERIMENTAL_BLOCK_EDITOR) ||
142+
gutenbergKitFeature.isEnabled()) {
140143
fetchEditorSettings(selectedSite)
141144
} else {
142145
fetchEditorTheme(selectedSite)

WordPress/src/main/java/org/wordpress/android/ui/posts/EditPostActivity.kt

Lines changed: 8 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -198,9 +198,10 @@ import org.wordpress.android.ui.posts.services.AztecVideoLoader
198198
import org.wordpress.android.ui.posts.sharemessage.EditJetpackSocialShareMessageActivity
199199
import org.wordpress.android.ui.posts.sharemessage.EditJetpackSocialShareMessageActivity.Companion.createIntent
200200
import org.wordpress.android.ui.prefs.AppPrefs
201-
import org.wordpress.android.ui.prefs.experimentalfeatures.ExperimentalFeature
201+
import org.wordpress.android.ui.prefs.experimentalfeatures.ExperimentalFeatures.Feature
202202
import org.wordpress.android.ui.prefs.SiteSettingsInterface
203203
import org.wordpress.android.ui.prefs.SiteSettingsInterface.SiteSettingsListener
204+
import org.wordpress.android.ui.prefs.experimentalfeatures.ExperimentalFeatures
204205
import org.wordpress.android.ui.reader.utils.ReaderUtilsWrapper
205206
import org.wordpress.android.ui.suggestion.SuggestionActivity
206207
import org.wordpress.android.ui.suggestion.SuggestionType
@@ -421,12 +422,7 @@ class EditPostActivity : BaseAppCompatActivity(), EditorFragmentActivity, Editor
421422

422423
@Inject lateinit var gutenbergKitFeature: GutenbergKitFeature
423424
@Inject lateinit var gutenbergKitPluginsFeature: GutenbergKitPluginsFeature
424-
425-
private val disableGutenbergKitFeatureConfig: ExperimentalFeature =
426-
ExperimentalFeature.DISABLE_EXPERIMENTAL_BLOCK_EDITOR
427-
private val gutenbergKitFeatureConfig: ExperimentalFeature = ExperimentalFeature.EXPERIMENTAL_BLOCK_EDITOR
428-
private val gutenbergKitThemeStylesConfig: ExperimentalFeature =
429-
ExperimentalFeature.EXPERIMENTAL_BLOCK_EDITOR_THEME_STYLES
425+
@Inject lateinit var experimentalFeatures: ExperimentalFeatures
430426

431427
@Inject lateinit var storePostViewModel: StorePostViewModel
432428
@Inject lateinit var storageUtilsViewModel: StorageUtilsViewModel
@@ -531,8 +527,10 @@ class EditPostActivity : BaseAppCompatActivity(), EditorFragmentActivity, Editor
531527
}
532528
onBackPressedDispatcher.addCallback(this, callback)
533529
dispatcher.register(this)
534-
isGutenbergKitEditor = (gutenbergKitFeatureConfig.isEnabled() || gutenbergKitFeature.isEnabled())
535-
&& !disableGutenbergKitFeatureConfig.isEnabled()
530+
val isGutenbergEnabled = experimentalFeatures.isEnabled(Feature.EXPERIMENTAL_BLOCK_EDITOR) ||
531+
gutenbergKitFeature.isEnabled()
532+
val isGutenbergDisabled = experimentalFeatures.isEnabled(Feature.DISABLE_EXPERIMENTAL_BLOCK_EDITOR)
533+
isGutenbergKitEditor = isGutenbergEnabled && !isGutenbergDisabled
536534

537535
createEditShareMessageActivityResultLauncher()
538536

@@ -2532,7 +2530,7 @@ class EditPostActivity : BaseAppCompatActivity(), EditorFragmentActivity, Editor
25322530
"namespaceExcludedPaths" to arrayOf("/wpcom/v2/following/recommendations", "/wpcom/v2/following/mine"),
25332531
"authHeader" to authHeader,
25342532
"siteApiNamespace" to siteApiNamespace,
2535-
"themeStyles" to gutenbergKitThemeStylesConfig.isEnabled(),
2533+
"themeStyles" to experimentalFeatures.isEnabled(Feature.EXPERIMENTAL_BLOCK_EDITOR_THEME_STYLES),
25362534
// Limited to Simple sites until application passwords are supported
25372535
"plugins" to (gutenbergKitPluginsFeature.isEnabled() && site.isWPCom),
25382536
"locale" to wpcomLocaleSlug,

WordPress/src/main/java/org/wordpress/android/ui/prefs/AppPrefsWrapper.kt

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -197,6 +197,10 @@ class AppPrefsWrapper @Inject constructor(val buildConfigWrapper: BuildConfigWra
197197
return AppPrefs.getExperimentalFeatureConfig(featureKey)
198198
}
199199

200+
fun setExperimentalFeatureConfig(isEnabled: Boolean, featureKey: String) {
201+
AppPrefs.setExperimentalFeatureConfig(isEnabled, featureKey)
202+
}
203+
200204
fun incrementPublishedPostCount() {
201205
AppPrefs.incrementPublishedPostCount()
202206
}

WordPress/src/main/java/org/wordpress/android/ui/prefs/experimentalfeatures/ExperimentalFeature.kt

Lines changed: 0 additions & 39 deletions
This file was deleted.
Lines changed: 44 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,44 @@
1+
package org.wordpress.android.ui.prefs.experimentalfeatures
2+
3+
import org.wordpress.android.R
4+
import org.wordpress.android.ui.prefs.AppPrefsWrapper
5+
import javax.inject.Inject
6+
7+
class ExperimentalFeatures @Inject constructor(
8+
private val appPrefsWrapper: AppPrefsWrapper
9+
) {
10+
fun isEnabled(feature: Feature) : Boolean {
11+
return appPrefsWrapper.getExperimentalFeatureConfig(feature.prefKey)
12+
}
13+
14+
fun setEnabled(feature: Feature, isEnabled: Boolean) {
15+
appPrefsWrapper.setExperimentalFeatureConfig(isEnabled, feature.prefKey)
16+
}
17+
18+
enum class Feature(
19+
val prefKey: String,
20+
val labelResId: Int,
21+
val descriptionResId: Int
22+
) {
23+
DISABLE_EXPERIMENTAL_BLOCK_EDITOR(
24+
"disable_experimental_block_editor",
25+
R.string.disable_experimental_block_editor,
26+
R.string.disable_experimental_block_editor_description
27+
),
28+
EXPERIMENTAL_BLOCK_EDITOR(
29+
"experimental_block_editor",
30+
R.string.experimental_block_editor,
31+
R.string.experimental_block_editor_description
32+
),
33+
EXPERIMENTAL_BLOCK_EDITOR_THEME_STYLES(
34+
"experimental_block_editor_theme_styles",
35+
R.string.experimental_block_editor_theme_styles,
36+
R.string.experimental_block_editor_theme_styles_description
37+
),
38+
EXPERIMENTAL_SUBSCRIBERS_FEATURE(
39+
"experimental_subscribers_feature",
40+
R.string.experimental_subscribers_feature,
41+
R.string.experimental_subscribers_feature_description
42+
);
43+
}
44+
}

WordPress/src/main/java/org/wordpress/android/ui/prefs/experimentalfeatures/ExperimentalFeaturesActivity.kt

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -37,7 +37,7 @@ class ExperimentalFeaturesActivity : BaseAppCompatActivity() {
3737
ExperimentalFeaturesScreen(
3838
features = features,
3939
onFeatureToggled = { feature, enabled ->
40-
if (feature == ExperimentalFeature.EXPERIMENTAL_BLOCK_EDITOR && !enabled) {
40+
if (feature == ExperimentalFeatures.Feature.EXPERIMENTAL_BLOCK_EDITOR && !enabled) {
4141
showDialog.value = true
4242
}
4343
viewModel.onFeatureToggled(feature, enabled)

WordPress/src/main/java/org/wordpress/android/ui/prefs/experimentalfeatures/ExperimentalFeaturesScreen.kt

Lines changed: 6 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -28,12 +28,13 @@ import androidx.compose.ui.tooling.preview.Preview
2828
import org.wordpress.android.R
2929
import org.wordpress.android.ui.compose.theme.AppThemeM3
3030
import org.wordpress.android.ui.compose.unit.Margin
31+
import org.wordpress.android.ui.prefs.experimentalfeatures.ExperimentalFeatures.Feature
3132

3233
@OptIn(ExperimentalMaterial3Api::class)
3334
@Composable
3435
fun ExperimentalFeaturesScreen(
35-
features: Map<ExperimentalFeature, Boolean>,
36-
onFeatureToggled: (feature: ExperimentalFeature, enabled: Boolean) -> Unit,
36+
features: Map<Feature, Boolean>,
37+
onFeatureToggled: (feature: Feature, enabled: Boolean) -> Unit,
3738
onNavigateBack: () -> Unit
3839
) {
3940
Scaffold(
@@ -91,9 +92,9 @@ fun ExperimentalFeaturesScreen(
9192

9293
@Composable
9394
fun FeatureToggle(
94-
feature: ExperimentalFeature,
95+
feature: Feature,
9596
enabled: Boolean,
96-
onChange: (ExperimentalFeature, Boolean) -> Unit,
97+
onChange: (Feature, Boolean) -> Unit,
9798
) {
9899
ListItem(
99100
headlineContent = {
@@ -145,7 +146,7 @@ fun FeedbackDialog(onDismiss: () -> Unit, onSendFeedback: () -> Unit) {
145146
fun ExperimentalFeaturesScreenPreview() {
146147
AppThemeM3 {
147148
val featuresStatusAlternated = remember {
148-
ExperimentalFeature.entries.toTypedArray().mapIndexed { index, feature ->
149+
ExperimentalFeatures.Feature.entries.toTypedArray().mapIndexed { index, feature ->
149150
feature to (index % 2 == 0)
150151
}.toMap()
151152
}

WordPress/src/main/java/org/wordpress/android/ui/prefs/experimentalfeatures/ExperimentalFeaturesViewModel.kt

Lines changed: 12 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -9,40 +9,42 @@ import kotlinx.coroutines.flow.update
99
import org.wordpress.android.BuildConfig
1010
import org.wordpress.android.util.config.GutenbergKitFeature
1111
import javax.inject.Inject
12+
import org.wordpress.android.ui.prefs.experimentalfeatures.ExperimentalFeatures.Feature
1213

1314
@HiltViewModel
1415
internal class ExperimentalFeaturesViewModel @Inject constructor(
16+
private val experimentalFeatures: ExperimentalFeatures,
1517
private val gutenbergKitFeature: GutenbergKitFeature
1618
) : ViewModel() {
17-
private val _switchStates = MutableStateFlow<Map<ExperimentalFeature, Boolean>>(emptyMap())
18-
val switchStates: StateFlow<Map<ExperimentalFeature, Boolean>> = _switchStates.asStateFlow()
19+
private val _switchStates = MutableStateFlow<Map<Feature, Boolean>>(emptyMap())
20+
val switchStates: StateFlow<Map<Feature, Boolean>> = _switchStates.asStateFlow()
1921

2022
init {
21-
val initialStates = ExperimentalFeature.entries
23+
val initialStates = Feature.entries
2224
.filter { feature ->
2325
shouldShowFeature(feature)
2426
}.associateWith { feature ->
25-
feature.isEnabled()
27+
experimentalFeatures.isEnabled(feature)
2628
}
2729
_switchStates.value = initialStates
2830
}
2931

30-
private fun shouldShowFeature(feature: ExperimentalFeature): Boolean {
32+
private fun shouldShowFeature(feature: Feature): Boolean {
3133
// only show subscribers in debug builds
32-
return if (BuildConfig.DEBUG.not() && feature == ExperimentalFeature.EXPERIMENTAL_SUBSCRIBERS_FEATURE) {
34+
return if (BuildConfig.DEBUG.not() && feature == Feature.EXPERIMENTAL_SUBSCRIBERS_FEATURE) {
3335
false
3436
} else if (gutenbergKitFeature.isEnabled()) {
35-
feature != ExperimentalFeature.EXPERIMENTAL_BLOCK_EDITOR
37+
feature != Feature.EXPERIMENTAL_BLOCK_EDITOR
3638
} else {
37-
feature != ExperimentalFeature.DISABLE_EXPERIMENTAL_BLOCK_EDITOR
39+
feature != Feature.DISABLE_EXPERIMENTAL_BLOCK_EDITOR
3840
}
3941
}
4042

41-
fun onFeatureToggled(feature: ExperimentalFeature, enabled: Boolean) {
43+
fun onFeatureToggled(feature: Feature, enabled: Boolean) {
4244
_switchStates.update { currentStates ->
4345
currentStates.toMutableMap().apply {
4446
this[feature] = enabled
45-
feature.setEnabled(enabled)
47+
experimentalFeatures.setEnabled(feature, enabled)
4648
}
4749
}
4850
}

WordPress/src/test/java/org/wordpress/android/ui/mysite/SelectedSiteRepositoryTest.kt

Lines changed: 8 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,6 @@
11
package org.wordpress.android.ui.mysite
22

33
import android.content.Context
4-
import android.content.SharedPreferences
5-
import android.content.SharedPreferences.Editor
64
import kotlinx.coroutines.ExperimentalCoroutinesApi
75
import org.assertj.core.api.Assertions.assertThat
86
import org.junit.Before
@@ -27,6 +25,8 @@ import org.wordpress.android.ui.prefs.SiteSettingsInterfaceWrapper
2725
import org.wordpress.android.util.config.GutenbergKitFeature
2826
import org.wordpress.android.AppInitializer
2927
import org.wordpress.android.fluxc.action.EditorSettingsAction
28+
import org.wordpress.android.ui.prefs.experimentalfeatures.ExperimentalFeatures
29+
import org.wordpress.android.ui.prefs.experimentalfeatures.ExperimentalFeatures.Feature
3030

3131
@ExperimentalCoroutinesApi
3232
class SelectedSiteRepositoryTest : BaseUnitTest() {
@@ -46,13 +46,10 @@ class SelectedSiteRepositoryTest : BaseUnitTest() {
4646
lateinit var gutenbergKitFeature: GutenbergKitFeature
4747

4848
@Mock
49-
lateinit var context: Context
50-
51-
@Mock
52-
lateinit var sharedPreferences: SharedPreferences
49+
lateinit var experimentalFeatures: ExperimentalFeatures
5350

5451
@Mock
55-
lateinit var editor: Editor
52+
lateinit var context: Context
5653

5754
private lateinit var siteModel: SiteModel
5855
private var siteIconProgressBarVisible: Boolean = false
@@ -72,9 +69,6 @@ class SelectedSiteRepositoryTest : BaseUnitTest() {
7269
set(null, context)
7370
}
7471

75-
// Mock shared preferences
76-
whenever(context.getSharedPreferences(any(), any())).thenReturn(sharedPreferences)
77-
7872
// Mock AppPrefsWrapper
7973
whenever(appPrefsWrapper.setSelectedSite(any())).then { }
8074

@@ -85,6 +79,7 @@ class SelectedSiteRepositoryTest : BaseUnitTest() {
8579
dispatcher,
8680
siteSettingsInterfaceFactory,
8781
appPrefsWrapper,
82+
experimentalFeatures,
8883
)
8984
selectedSiteRepository.gutenbergKitFeature = gutenbergKitFeature
9085
selectedSiteRepository.showSiteIconProgressBar.observeForever { siteIconProgressBarVisible = it == true }
@@ -279,12 +274,9 @@ class SelectedSiteRepositoryTest : BaseUnitTest() {
279274

280275
@Test
281276
fun `Should fetch EditorSettings when ExperimentalBlockEditor is enabled`() {
282-
// Mocking via the specific key is required as ExperimentalFeature currently relies upon AppPrefs rather than
283-
// AppPrefsWrapper, making mocking a bit more difficult
284-
whenever(sharedPreferences.getBoolean(
285-
eq("EXPERIMENTAL_FEATURE_CONFIGexperimental_block_editor"),
286-
eq(false)
287-
)).thenReturn(true)
277+
whenever(
278+
experimentalFeatures.isEnabled(Feature.EXPERIMENTAL_BLOCK_EDITOR)
279+
).thenReturn(true)
288280
initializeSiteAndSiteSettings()
289281

290282
selectedSiteRepository.updateSiteSettingsIfNecessary()

0 commit comments

Comments
 (0)