Browse Source

Add Ui test on DeveloperSettingsView

pull/2744/head
Benoit Marty 5 months ago
parent
commit
d06ec9099b
  1. 32
      features/preferences/impl/src/main/kotlin/io/element/android/features/preferences/impl/developer/DeveloperSettingsStateProvider.kt
  2. 127
      features/preferences/impl/src/test/kotlin/io/element/android/features/preferences/impl/developer/DeveloperSettingsViewTest.kt
  3. 5
      libraries/designsystem/src/main/kotlin/io/element/android/libraries/designsystem/components/preferences/PreferenceTextField.kt

32
features/preferences/impl/src/main/kotlin/io/element/android/features/preferences/impl/developer/DeveloperSettingsStateProvider.kt

@ -25,22 +25,36 @@ open class DeveloperSettingsStateProvider : PreviewParameterProvider<DeveloperSe
override val values: Sequence<DeveloperSettingsState> override val values: Sequence<DeveloperSettingsState>
get() = sequenceOf( get() = sequenceOf(
aDeveloperSettingsState(), aDeveloperSettingsState(),
aDeveloperSettingsState().copy(clearCacheAction = AsyncData.Loading()), aDeveloperSettingsState(
aDeveloperSettingsState().copy( clearCacheAction = AsyncData.Loading()
customElementCallBaseUrlState = CustomElementCallBaseUrlState( ),
aDeveloperSettingsState(
customElementCallBaseUrlState = aCustomElementCallBaseUrlState(
baseUrl = "https://call.element.ahoy", baseUrl = "https://call.element.ahoy",
defaultUrl = "https://call.element.io",
validator = { true }
) )
), ),
) )
} }
fun aDeveloperSettingsState() = DeveloperSettingsState( fun aDeveloperSettingsState(
clearCacheAction: AsyncData<Unit> = AsyncData.Uninitialized,
customElementCallBaseUrlState: CustomElementCallBaseUrlState = aCustomElementCallBaseUrlState(),
eventSink: (DeveloperSettingsEvents) -> Unit = {},
) = DeveloperSettingsState(
features = aFeatureUiModelList(), features = aFeatureUiModelList(),
rageshakeState = aRageshakePreferencesState(), rageshakeState = aRageshakePreferencesState(),
cacheSize = AsyncData.Success("1.2 MB"), cacheSize = AsyncData.Success("1.2 MB"),
clearCacheAction = AsyncData.Uninitialized, clearCacheAction = clearCacheAction,
customElementCallBaseUrlState = CustomElementCallBaseUrlState(baseUrl = null, defaultUrl = "https://call.element.io", validator = { true }), customElementCallBaseUrlState = customElementCallBaseUrlState,
eventSink = {} eventSink = eventSink,
)
fun aCustomElementCallBaseUrlState(
baseUrl: String? = null,
defaultUrl: String = "https://call.element.io",
validator: (String?) -> Boolean = { true },
) = CustomElementCallBaseUrlState(
baseUrl = baseUrl,
defaultUrl = defaultUrl,
validator = validator,
) )

127
features/preferences/impl/src/test/kotlin/io/element/android/features/preferences/impl/developer/DeveloperSettingsViewTest.kt

@ -0,0 +1,127 @@
/*
* Copyright (c) 2024 New Vector Ltd
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package io.element.android.features.preferences.impl.developer
import androidx.activity.ComponentActivity
import androidx.compose.ui.test.junit4.AndroidComposeTestRule
import androidx.compose.ui.test.junit4.createAndroidComposeRule
import androidx.compose.ui.test.onNodeWithText
import androidx.compose.ui.test.performClick
import androidx.test.ext.junit.runners.AndroidJUnit4
import io.element.android.features.preferences.impl.R
import io.element.android.libraries.ui.strings.CommonStrings
import io.element.android.tests.testutils.EnsureNeverCalled
import io.element.android.tests.testutils.EventsRecorder
import io.element.android.tests.testutils.clickOn
import io.element.android.tests.testutils.ensureCalledOnce
import io.element.android.tests.testutils.pressBack
import org.junit.Rule
import org.junit.Test
import org.junit.rules.TestRule
import org.junit.runner.RunWith
import org.robolectric.annotation.Config
@RunWith(AndroidJUnit4::class)
class DeveloperSettingsViewTest {
@get:Rule
val rule = createAndroidComposeRule<ComponentActivity>()
@Test
fun `clicking on back invokes the expected callback`() {
val eventsRecorder = EventsRecorder<DeveloperSettingsEvents>(expectEvents = false)
ensureCalledOnce {
rule.setDeveloperSettingsView(
state = aDeveloperSettingsState(
eventSink = eventsRecorder
),
onBackPressed = it
)
rule.pressBack()
}
}
@Test
fun `clicking on element call url open the dialogs and submit emits the expected event`() {
val eventsRecorder = EventsRecorder<DeveloperSettingsEvents>()
rule.setDeveloperSettingsView(
state = aDeveloperSettingsState(
eventSink = eventsRecorder
),
)
rule.clickOn(R.string.screen_advanced_settings_element_call_base_url)
rule.clickOn(CommonStrings.action_ok)
eventsRecorder.assertSingle(DeveloperSettingsEvents.SetCustomElementCallBaseUrl("https://call.element.io"))
}
@Config(qualifiers = "h1024dp")
@Test
fun `clicking on open showkase invokes the expected callback`() {
val eventsRecorder = EventsRecorder<DeveloperSettingsEvents>(expectEvents = false)
ensureCalledOnce {
rule.setDeveloperSettingsView(
state = aDeveloperSettingsState(
eventSink = eventsRecorder
),
onOpenShowkase = it
)
rule.onNodeWithText("Open Showkase browser").performClick()
}
}
@Test
fun `clicking on configure tracing invokes the expected callback`() {
val eventsRecorder = EventsRecorder<DeveloperSettingsEvents>(expectEvents = false)
ensureCalledOnce {
rule.setDeveloperSettingsView(
state = aDeveloperSettingsState(
eventSink = eventsRecorder
),
onOpenConfigureTracing = it
)
rule.onNodeWithText("Configure tracing").performClick()
}
}
@Config(qualifiers = "h1024dp")
@Test
fun `clicking on clear cache emits the expected event`() {
val eventsRecorder = EventsRecorder<DeveloperSettingsEvents>()
rule.setDeveloperSettingsView(
state = aDeveloperSettingsState(
eventSink = eventsRecorder
),
)
rule.onNodeWithText("Clear cache").performClick()
eventsRecorder.assertSingle(DeveloperSettingsEvents.ClearCache)
}
}
private fun <R : TestRule> AndroidComposeTestRule<R, ComponentActivity>.setDeveloperSettingsView(
state: DeveloperSettingsState,
onOpenShowkase: () -> Unit = EnsureNeverCalled(),
onOpenConfigureTracing: () -> Unit = EnsureNeverCalled(),
onBackPressed: () -> Unit = EnsureNeverCalled()
) {
setContent {
DeveloperSettingsView(
state = state,
onOpenShowkase = onOpenShowkase,
onOpenConfigureTracing = onOpenConfigureTracing,
onBackPressed = onBackPressed,
)
}
}

5
libraries/designsystem/src/main/kotlin/io/element/android/libraries/designsystem/components/preferences/PreferenceTextField.kt

@ -98,11 +98,11 @@ private fun TextFieldDialog(
keyboardOptions: KeyboardOptions = KeyboardOptions.Default, keyboardOptions: KeyboardOptions = KeyboardOptions.Default,
) { ) {
val focusRequester = remember { FocusRequester() } val focusRequester = remember { FocusRequester() }
var textFieldContents by rememberSaveable(stateSaver = TextFieldValue.Saver) { var textFieldContents by rememberSaveable(stateSaver = TextFieldValue.Saver) {
mutableStateOf(TextFieldValue(value.orEmpty(), selection = TextRange(value.orEmpty().length))) mutableStateOf(TextFieldValue(value.orEmpty(), selection = TextRange(value.orEmpty().length)))
} }
var error by rememberSaveable { mutableStateOf<String?>(null) } var error by rememberSaveable { mutableStateOf<String?>(null) }
var canRequestFocus by rememberSaveable { mutableStateOf(false) }
val canSubmit by remember { derivedStateOf { validation(textFieldContents.text) } } val canSubmit by remember { derivedStateOf { validation(textFieldContents.text) } }
ListDialog( ListDialog(
title = title, title = title,
@ -128,10 +128,11 @@ private fun TextFieldDialog(
maxLines = maxLines, maxLines = maxLines,
modifier = Modifier.focusRequester(focusRequester), modifier = Modifier.focusRequester(focusRequester),
) )
canRequestFocus = true
} }
} }
if (autoSelectOnDisplay) { if (autoSelectOnDisplay && canRequestFocus) {
LaunchedEffect(Unit) { LaunchedEffect(Unit) {
focusRequester.requestFocus() focusRequester.requestFocus()
} }

Loading…
Cancel
Save