From d5556c59e951c2ef2c3cc913b4f3c6092dd2371e Mon Sep 17 00:00:00 2001 From: tomhsu Date: Mon, 27 May 2024 12:42:03 +0000 Subject: [PATCH] Fix when edittext only has space and cause name look like blank fix: 335763360 Test: Manual test. see b/335763360#comment14 Test: atest passed Change-Id: I9ebae13039d7b78b7acfea545a89d3096aa82c31 --- .../spa/network/SimOnboardingLabelSim.kt | 5 +- .../spa/network/SimOnboardingLabelSimTest.kt | 152 ++++++++++++++---- 2 files changed, 127 insertions(+), 30 deletions(-) diff --git a/src/com/android/settings/spa/network/SimOnboardingLabelSim.kt b/src/com/android/settings/spa/network/SimOnboardingLabelSim.kt index 4dd0defe795..6c8ce6e3bdf 100644 --- a/src/com/android/settings/spa/network/SimOnboardingLabelSim.kt +++ b/src/com/android/settings/spa/network/SimOnboardingLabelSim.kt @@ -28,6 +28,7 @@ import androidx.compose.runtime.mutableStateOf import androidx.compose.runtime.remember import androidx.compose.runtime.setValue import androidx.compose.ui.Modifier +import androidx.compose.ui.platform.testTag import androidx.compose.ui.res.stringResource import com.android.settings.R import com.android.settings.network.SimOnboardingService @@ -104,9 +105,9 @@ private fun LabelSimPreference( value = titleSimName, label = stringResource(R.string.sim_onboarding_label_sim_dialog_label), placeholder = {Text(text = originalSimCarrierName)}, - modifier = Modifier.fillMaxWidth() + modifier = Modifier.fillMaxWidth().testTag("contentInput") ) { - titleSimName = if (it.isEmpty()) originalSimCarrierName else it + titleSimName = if (it.matches(Regex("^\\s*$"))) originalSimCarrierName else it } }, ) diff --git a/tests/spa_unit/src/com/android/settings/spa/network/SimOnboardingLabelSimTest.kt b/tests/spa_unit/src/com/android/settings/spa/network/SimOnboardingLabelSimTest.kt index 43270c2433d..79f53cab4ad 100644 --- a/tests/spa_unit/src/com/android/settings/spa/network/SimOnboardingLabelSimTest.kt +++ b/tests/spa_unit/src/com/android/settings/spa/network/SimOnboardingLabelSimTest.kt @@ -19,20 +19,30 @@ package com.android.settings.spa.network import android.content.Context import android.telephony.SubscriptionInfo import android.telephony.SubscriptionManager +import android.view.KeyEvent.ACTION_DOWN +import android.view.KeyEvent.KEYCODE_FORWARD_DEL import androidx.compose.runtime.CompositionLocalProvider +import androidx.compose.ui.input.key.KeyEvent +import androidx.compose.ui.input.key.NativeKeyEvent import androidx.compose.ui.platform.LocalContext import androidx.compose.ui.platform.LocalLifecycleOwner +import androidx.compose.ui.semantics.SemanticsProperties import androidx.compose.ui.test.assertIsDisplayed import androidx.compose.ui.test.hasText import androidx.compose.ui.test.junit4.createComposeRule +import androidx.compose.ui.test.onNodeWithTag import androidx.compose.ui.test.onNodeWithText import androidx.compose.ui.test.performClick +import androidx.compose.ui.test.performKeyPress +import androidx.compose.ui.test.performTextClearance +import androidx.compose.ui.test.performTextInput import androidx.lifecycle.testing.TestLifecycleOwner import androidx.test.core.app.ApplicationProvider import androidx.test.ext.junit.runners.AndroidJUnit4 import com.android.settings.R import com.android.settings.network.SimOnboardingService import com.android.settingslib.spa.testutils.waitUntilExists +import org.junit.Assert.assertEquals import org.junit.Rule import org.junit.Test import org.junit.runner.RunWith @@ -125,22 +135,7 @@ class SimOnboardingLabelSimTest { @Test fun simOnboardingLabelSimImpl_showItem_show3Items() { - mockSimOnboardingService.stub { - on { targetSubId }.doReturn(SUB_ID_1) - on { targetSubInfo }.doReturn(SUB_INFO_1) - on { availableSubInfoList }.doReturn(listOf(SUB_INFO_1, SUB_INFO_2, SUB_INFO_3)) - on { activeSubInfoList }.doReturn(listOf(SUB_INFO_2, SUB_INFO_3)) - on { getSelectableSubscriptionInfoList() }.doReturn( - listOf( - SUB_INFO_1, - SUB_INFO_2, - SUB_INFO_3 - ) - ) - on { getSubscriptionInfoDisplayName(SUB_INFO_1) }.doReturn(DISPLAY_NAME_1) - on { getSubscriptionInfoDisplayName(SUB_INFO_2) }.doReturn(DISPLAY_NAME_2) - on { getSubscriptionInfoDisplayName(SUB_INFO_3) }.doReturn(DISPLAY_NAME_3) - } + preSetupContent() composeTestRule.setContent { CompositionLocalProvider( @@ -161,6 +156,118 @@ class SimOnboardingLabelSimTest { @Test fun simOnboardingLabelSimImpl_showDialog_checkTitle() { + preSetupContent() + + composeTestRule.setContent { + SimOnboardingLabelSimImpl(nextAction, cancelAction, mockSimOnboardingService) + } + composeTestRule.onNodeWithText(DISPLAY_NAME_1).performClick() + + composeTestRule.onNodeWithText( + context.getString(R.string.sim_onboarding_label_sim_dialog_title) + ).assertIsDisplayed() + } + + @Test + fun showDialog_noContentInput_showOriginalDisplayName() { + preSetupContent() + + composeTestRule.setContent { + SimOnboardingLabelSimImpl(nextAction, cancelAction, mockSimOnboardingService) + } + + composeTestRule.onNodeWithText(DISPLAY_NAME_1).performClick() + + assertEquals( + composeTestRule.onNodeWithTag(TEXT_FIELD_INPUT) + .fetchSemanticsNode() + .config[SemanticsProperties.EditableText].text, DISPLAY_NAME_1 + ) + } + + @Test + fun showDialog_clearContent_showOriginalDisplayName() { + preSetupContent() + + composeTestRule.setContent { + SimOnboardingLabelSimImpl(nextAction, cancelAction, mockSimOnboardingService) + } + + composeTestRule.onNodeWithText(DISPLAY_NAME_1).performClick() + composeTestRule.onNodeWithTag(TEXT_FIELD_INPUT).performTextClearance() + + assertEquals( + composeTestRule.onNodeWithTag(TEXT_FIELD_INPUT) + .fetchSemanticsNode() + .config[SemanticsProperties.EditableText].text, DISPLAY_NAME_1 + ) + } + + @Test + fun showDialog_modifyContent_showModifiedDisplayName() { + val inputData = "input_data" + preSetupContent() + + composeTestRule.setContent { + SimOnboardingLabelSimImpl(nextAction, cancelAction, mockSimOnboardingService) + } + + composeTestRule.onNodeWithText(DISPLAY_NAME_1).performClick() + composeTestRule.onNodeWithTag(TEXT_FIELD_INPUT).performTextInput(inputData) + + // Due to this TextField with Text and EditText, it need fetch correct node to get correct + // content. + assertEquals( + composeTestRule.onNodeWithTag(TEXT_FIELD_INPUT) + .fetchSemanticsNode() + .config[SemanticsProperties.EditableText].text, inputData + DISPLAY_NAME_1 + ) + + // Click save button + composeTestRule.onNodeWithText(context.getString(R.string.mobile_network_sim_name_rename)) + .performClick() + + // Check preference's name is still DISPLAY_NAME_1 + composeTestRule.onNodeWithText(inputData + DISPLAY_NAME_1).assertExists() + } + + @Test + fun showDialog_onlySpaceCharContent_showAndSaveOriginalDisplayName() { + val spaceChars = " "; + preSetupContent() + + composeTestRule.setContent { + SimOnboardingLabelSimImpl(nextAction, cancelAction, mockSimOnboardingService) + } + + // Simulate real operation, + // 1. Click preference of DISPLAY_NAME_1 + composeTestRule.onNodeWithText(DISPLAY_NAME_1).performClick() + // 2. Input space chars to EditText view + composeTestRule.onNodeWithTag(TEXT_FIELD_INPUT).performTextInput(spaceChars) + // 3. Remove the string of DISPLAY_NAME_1 from EditText view + repeat(DISPLAY_NAME_1.length) { + composeTestRule.onNodeWithTag(TEXT_FIELD_INPUT) + .performKeyPress(KeyEvent(NativeKeyEvent(ACTION_DOWN, KEYCODE_FORWARD_DEL))) + } + + // Due to this TextField with Text and EditText, it need fetch correct node to get correct + // content. + assertEquals( + DISPLAY_NAME_1, composeTestRule.onNodeWithTag(TEXT_FIELD_INPUT) + .fetchSemanticsNode() + .config[SemanticsProperties.EditableText].text + ) + + // Click save button + composeTestRule.onNodeWithText(context.getString(R.string.mobile_network_sim_name_rename)) + .performClick() + + // Check preference's name is still DISPLAY_NAME_1 + composeTestRule.onNodeWithText(DISPLAY_NAME_1).assertExists() + } + + fun preSetupContent() { mockSimOnboardingService.stub { on { targetSubId }.doReturn(SUB_ID_1) on { targetSubInfo }.doReturn(SUB_INFO_1) @@ -177,21 +284,10 @@ class SimOnboardingLabelSimTest { on { getSubscriptionInfoDisplayName(SUB_INFO_2) }.doReturn(DISPLAY_NAME_2) on { getSubscriptionInfoDisplayName(SUB_INFO_3) }.doReturn(DISPLAY_NAME_3) } - - composeTestRule.setContent { - SimOnboardingLabelSimImpl(nextAction, cancelAction, mockSimOnboardingService) - } - - - composeTestRule.onNodeWithText(DISPLAY_NAME_1).performClick() - - composeTestRule.onNodeWithText( - context.getString(R.string.sim_onboarding_label_sim_dialog_title) - ) - .assertIsDisplayed() } private companion object { + const val TEXT_FIELD_INPUT = "contentInput" const val SUB_ID_1 = 1 const val SUB_ID_2 = 2 const val SUB_ID_3 = 3