From 3ecfad908598cc49fe16227aef0bec44ce7744a6 Mon Sep 17 00:00:00 2001 From: Janina Davydova Date: Mon, 8 Jun 2026 07:04:34 +0200 Subject: [PATCH 01/12] WIP --- .../ui/interaction/TextFieldEditMenuTest.kt | 28 +++++++------------ 1 file changed, 10 insertions(+), 18 deletions(-) diff --git a/compose/ui/ui/src/uikitInstrumentedTest/kotlin/androidx/compose/ui/interaction/TextFieldEditMenuTest.kt b/compose/ui/ui/src/uikitInstrumentedTest/kotlin/androidx/compose/ui/interaction/TextFieldEditMenuTest.kt index 7cc650a66272f..213eb43fc35c0 100644 --- a/compose/ui/ui/src/uikitInstrumentedTest/kotlin/androidx/compose/ui/interaction/TextFieldEditMenuTest.kt +++ b/compose/ui/ui/src/uikitInstrumentedTest/kotlin/androidx/compose/ui/interaction/TextFieldEditMenuTest.kt @@ -581,26 +581,18 @@ class TextFieldEditMenuTest { } @OptIn(ExperimentalForeignApi::class) - private fun UIKitInstrumentedTest.verifyFullToolbarPresent() { - findNodeWithLabel("Cut").let { - it.assertVisibleInContainer() - assertTrue(it.isAccessibilityElement ?: false) - } - - findNodeWithLabel("Copy").let { - it.assertVisibleInContainer() - assertTrue(it.isAccessibilityElement ?: false) - } - - findNodeWithLabel("Paste").let { - it.assertVisibleInContainer() - assertTrue(it.isAccessibilityElement ?: false) + private fun UIKitInstrumentedTest.verifyContextMenuItemsVisible(labels: List) { + labels.forEach { label -> + findNodeWithLabel(label).let { + it.assertVisibleInContainer() + assertTrue(it.isAccessibilityElement ?: false) + } } + } - findNodeWithLabel("Select All").let { - it.assertVisibleInContainer() - assertTrue(it.isAccessibilityElement ?: false) - } + @OptIn(ExperimentalForeignApi::class) + private fun UIKitInstrumentedTest.verifyFullToolbarPresent() { + verifyContextMenuItemsVisible(listOf("Cut", "Copy", "Paste", "Select All")) } private fun UIKitInstrumentedTest.tapContextMenuButton(label: String) { From 4e5b996e65ac0dc9ea7a3ae3a9227144555fcb5b Mon Sep 17 00:00:00 2001 From: Janina Davydova Date: Mon, 8 Jun 2026 07:08:39 +0200 Subject: [PATCH 02/12] + test{Old/New}ContextMenuEditableCollapsedClipboardText --- .../ui/interaction/TextFieldEditMenuTest.kt | 54 +++++++++++++++++++ 1 file changed, 54 insertions(+) diff --git a/compose/ui/ui/src/uikitInstrumentedTest/kotlin/androidx/compose/ui/interaction/TextFieldEditMenuTest.kt b/compose/ui/ui/src/uikitInstrumentedTest/kotlin/androidx/compose/ui/interaction/TextFieldEditMenuTest.kt index 213eb43fc35c0..546c52df12de4 100644 --- a/compose/ui/ui/src/uikitInstrumentedTest/kotlin/androidx/compose/ui/interaction/TextFieldEditMenuTest.kt +++ b/compose/ui/ui/src/uikitInstrumentedTest/kotlin/androidx/compose/ui/interaction/TextFieldEditMenuTest.kt @@ -63,6 +63,7 @@ import kotlin.test.Test import kotlin.test.assertEquals import kotlin.test.assertFalse import kotlin.test.assertNotNull +import kotlin.test.assertNull import kotlin.test.assertTrue import kotlin.test.fail import kotlin.time.Duration.Companion.seconds @@ -286,6 +287,22 @@ class TextFieldEditMenuTest { findNodeWithLabel("Paste").assertVisibleInContainer() } + @Test + fun testOldContextMenuEditableCollapsedClipboardText() = runContextMenuTest(false) { + verifyEditableCollapsedClipboardTextContextMenu( + visibleActions = listOf("Paste", "Select", "Select All"), + hiddenActions = listOf("Cut", "Copy") + ) + } + + @Test + fun testNewContextMenuEditableCollapsedClipboardText() = runContextMenuTest(true) { + verifyEditableCollapsedClipboardTextContextMenu( + visibleActions = listOf("Paste", "Select All"), + hiddenActions = listOf("Cut", "Copy", "Select") + ) + } + @Test fun testTapsCountingWithMultiTouch() = runUIKitInstrumentedTest { var touchesDown = 0 @@ -566,6 +583,34 @@ class TextFieldEditMenuTest { waitForContextMenu() } + private fun UIKitInstrumentedTest.verifyEditableCollapsedClipboardTextContextMenu( + visibleActions: List, + hiddenActions: List, + ) { + UIPasteboard.generalPasteboard().string = "Paste text" + val textFieldValue = mutableStateOf(TextFieldValue("Text", TextRange(4,4))) + setContent { + val focusRequester = remember { FocusRequester() } + Column(modifier = Modifier.safeDrawingPadding()) { + BasicTextField( + value = textFieldValue.value, + onValueChange = { textFieldValue.value = it }, + modifier = Modifier + .testTag("TextField") + .focusRequester(focusRequester) + ) + } + LaunchedEffect(focusRequester) { + focusRequester.requestFocus() + } + } + + longPressAndAwaitContextMenu("TextField") + + verifyContextMenuItemsVisible(visibleActions) + verifyContextMenuItemsHidden(hiddenActions) + } + @OptIn(ExperimentalFoundationApi::class) private fun runContextMenuTest( newContextMenuEnabled: Boolean, @@ -590,6 +635,15 @@ class TextFieldEditMenuTest { } } + @OptIn(ExperimentalForeignApi::class) private fun UIKitInstrumentedTest.verifyContextMenuItemsHidden(labels: List) { + labels.forEach { label -> + assertNull( + findNodeWithLabelOrNull(label), + "Context menu item \"$label\" should be hidden" + ) + } + } + @OptIn(ExperimentalForeignApi::class) private fun UIKitInstrumentedTest.verifyFullToolbarPresent() { verifyContextMenuItemsVisible(listOf("Cut", "Copy", "Paste", "Select All")) From 735b1f582c0c4b02d0749a61fe9f38915444f8fe Mon Sep 17 00:00:00 2001 From: Janina Davydova Date: Mon, 8 Jun 2026 07:32:55 +0200 Subject: [PATCH 03/12] +test{Old/New}ContextMenuEditableCollapsedClipboardEmpty --- .../ui/interaction/TextFieldEditMenuTest.kt | 43 ++++++++++++++++++- 1 file changed, 41 insertions(+), 2 deletions(-) diff --git a/compose/ui/ui/src/uikitInstrumentedTest/kotlin/androidx/compose/ui/interaction/TextFieldEditMenuTest.kt b/compose/ui/ui/src/uikitInstrumentedTest/kotlin/androidx/compose/ui/interaction/TextFieldEditMenuTest.kt index 546c52df12de4..c5cf9eb7f47b0 100644 --- a/compose/ui/ui/src/uikitInstrumentedTest/kotlin/androidx/compose/ui/interaction/TextFieldEditMenuTest.kt +++ b/compose/ui/ui/src/uikitInstrumentedTest/kotlin/androidx/compose/ui/interaction/TextFieldEditMenuTest.kt @@ -303,6 +303,22 @@ class TextFieldEditMenuTest { ) } + @Test + fun testOldContextMenuEditableCollapsedClipboardEmpty() = runContextMenuTest(false) { + verifyEditableCollapsedClipboardEmptyContextMenu( + visibleActions = listOf("Select", "Select All"), + hiddenActions = listOf("Cut", "Copy", "Paste") + ) + } + + @Test + fun testNewContextMenuEditableCollapsedClipboardEmpty() = runContextMenuTest(true) { + verifyEditableCollapsedClipboardEmptyContextMenu( + visibleActions = listOf("Select All"), + hiddenActions = listOf("Cut", "Copy", "Paste", "Select") + ) + } + @Test fun testTapsCountingWithMultiTouch() = runUIKitInstrumentedTest { var touchesDown = 0 @@ -587,7 +603,30 @@ class TextFieldEditMenuTest { visibleActions: List, hiddenActions: List, ) { - UIPasteboard.generalPasteboard().string = "Paste text" + verifyEditableCollapsedContextMenu( + clipboardText = "Paste text", + visibleActions = visibleActions, + hiddenActions = hiddenActions + ) + } + + private fun UIKitInstrumentedTest.verifyEditableCollapsedClipboardEmptyContextMenu( + visibleActions: List, + hiddenActions: List, + ) { + verifyEditableCollapsedContextMenu( + clipboardText = null, + visibleActions = visibleActions, + hiddenActions = hiddenActions + ) + } + + private fun UIKitInstrumentedTest.verifyEditableCollapsedContextMenu( + clipboardText: String?, + visibleActions: List, + hiddenActions: List, + ) { + UIPasteboard.generalPasteboard().string = clipboardText val textFieldValue = mutableStateOf(TextFieldValue("Text", TextRange(4,4))) setContent { val focusRequester = remember { FocusRequester() } @@ -662,4 +701,4 @@ class TextFieldEditMenuTest { .up() } } -} \ No newline at end of file +} From ffa0b53db33b0e2cf44cd58c270465763872f928 Mon Sep 17 00:00:00 2001 From: Janina Davydova Date: Tue, 9 Jun 2026 12:53:20 +0200 Subject: [PATCH 04/12] Added 2nd type of the TextField for use in the menu availability tests --- .../ui/interaction/TextFieldEditMenuTest.kt | 91 ++++++++++++++++--- 1 file changed, 79 insertions(+), 12 deletions(-) diff --git a/compose/ui/ui/src/uikitInstrumentedTest/kotlin/androidx/compose/ui/interaction/TextFieldEditMenuTest.kt b/compose/ui/ui/src/uikitInstrumentedTest/kotlin/androidx/compose/ui/interaction/TextFieldEditMenuTest.kt index c5cf9eb7f47b0..655ebac31b41b 100644 --- a/compose/ui/ui/src/uikitInstrumentedTest/kotlin/androidx/compose/ui/interaction/TextFieldEditMenuTest.kt +++ b/compose/ui/ui/src/uikitInstrumentedTest/kotlin/androidx/compose/ui/interaction/TextFieldEditMenuTest.kt @@ -288,32 +288,72 @@ class TextFieldEditMenuTest { } @Test - fun testOldContextMenuEditableCollapsedClipboardText() = runContextMenuTest(false) { + fun testOldContextMenuBasicTextFieldEditableCollapsedClipboardText() = runContextMenuTest(false) { verifyEditableCollapsedClipboardTextContextMenu( + textFieldKind = EditableTextFieldKind.BasicTextField, visibleActions = listOf("Paste", "Select", "Select All"), hiddenActions = listOf("Cut", "Copy") ) } @Test - fun testNewContextMenuEditableCollapsedClipboardText() = runContextMenuTest(true) { + fun testOldContextMenuBasicTextField2EditableCollapsedClipboardText() = runContextMenuTest(false) { verifyEditableCollapsedClipboardTextContextMenu( + textFieldKind = EditableTextFieldKind.BasicTextField2, + visibleActions = listOf("Paste", "Select", "Select All"), + hiddenActions = listOf("Cut", "Copy") + ) + } + + @Test + fun testNewContextMenuBasicTextFieldEditableCollapsedClipboardText() = runContextMenuTest(true) { + verifyEditableCollapsedClipboardTextContextMenu( + textFieldKind = EditableTextFieldKind.BasicTextField, visibleActions = listOf("Paste", "Select All"), hiddenActions = listOf("Cut", "Copy", "Select") ) } @Test - fun testOldContextMenuEditableCollapsedClipboardEmpty() = runContextMenuTest(false) { + fun testNewContextMenuBasicTextField2EditableCollapsedClipboardText() = runContextMenuTest(true) { + verifyEditableCollapsedClipboardTextContextMenu( + textFieldKind = EditableTextFieldKind.BasicTextField2, + visibleActions = listOf("Paste", "Select All"), + hiddenActions = listOf("Cut", "Copy", "Select") + ) + } + + @Test + fun testOldContextMenuBasicTextFieldEditableCollapsedClipboardEmpty() = runContextMenuTest(false) { + verifyEditableCollapsedClipboardEmptyContextMenu( + textFieldKind = EditableTextFieldKind.BasicTextField, + visibleActions = listOf("Select", "Select All"), + hiddenActions = listOf("Cut", "Copy", "Paste") + ) + } + + @Test + fun testOldContextMenuBasicTextField2EditableCollapsedClipboardEmpty() = runContextMenuTest(false) { verifyEditableCollapsedClipboardEmptyContextMenu( + textFieldKind = EditableTextFieldKind.BasicTextField2, visibleActions = listOf("Select", "Select All"), hiddenActions = listOf("Cut", "Copy", "Paste") ) } @Test - fun testNewContextMenuEditableCollapsedClipboardEmpty() = runContextMenuTest(true) { + fun testNewContextMenuBasicTextFieldEditableCollapsedClipboardEmpty() = runContextMenuTest(true) { verifyEditableCollapsedClipboardEmptyContextMenu( + textFieldKind = EditableTextFieldKind.BasicTextField, + visibleActions = listOf("Select All"), + hiddenActions = listOf("Cut", "Copy", "Paste", "Select") + ) + } + + @Test + fun testNewContextMenuBasicTextField2EditableCollapsedClipboardEmpty() = runContextMenuTest(true) { + verifyEditableCollapsedClipboardEmptyContextMenu( + textFieldKind = EditableTextFieldKind.BasicTextField2, visibleActions = listOf("Select All"), hiddenActions = listOf("Cut", "Copy", "Paste", "Select") ) @@ -600,10 +640,12 @@ class TextFieldEditMenuTest { } private fun UIKitInstrumentedTest.verifyEditableCollapsedClipboardTextContextMenu( + textFieldKind: EditableTextFieldKind, visibleActions: List, hiddenActions: List, ) { verifyEditableCollapsedContextMenu( + textFieldKind = textFieldKind, clipboardText = "Paste text", visibleActions = visibleActions, hiddenActions = hiddenActions @@ -611,10 +653,12 @@ class TextFieldEditMenuTest { } private fun UIKitInstrumentedTest.verifyEditableCollapsedClipboardEmptyContextMenu( + textFieldKind: EditableTextFieldKind, visibleActions: List, hiddenActions: List, ) { verifyEditableCollapsedContextMenu( + textFieldKind = textFieldKind, clipboardText = null, visibleActions = visibleActions, hiddenActions = hiddenActions @@ -622,22 +666,40 @@ class TextFieldEditMenuTest { } private fun UIKitInstrumentedTest.verifyEditableCollapsedContextMenu( + textFieldKind: EditableTextFieldKind, clipboardText: String?, visibleActions: List, hiddenActions: List, ) { UIPasteboard.generalPasteboard().string = clipboardText - val textFieldValue = mutableStateOf(TextFieldValue("Text", TextRange(4,4))) setContent { val focusRequester = remember { FocusRequester() } Column(modifier = Modifier.safeDrawingPadding()) { - BasicTextField( - value = textFieldValue.value, - onValueChange = { textFieldValue.value = it }, - modifier = Modifier - .testTag("TextField") - .focusRequester(focusRequester) - ) + when (textFieldKind) { + EditableTextFieldKind.BasicTextField -> { + val textFieldValue = remember { + mutableStateOf(TextFieldValue("Text", TextRange(4, 4))) + } + BasicTextField( + value = textFieldValue.value, + onValueChange = { textFieldValue.value = it }, + modifier = Modifier + .testTag("TextField") + .focusRequester(focusRequester) + ) + } + EditableTextFieldKind.BasicTextField2 -> { + val textFieldState = remember { + TextFieldState("Text", TextRange(4, 4)) + } + BasicTextField( + state = textFieldState, + modifier = Modifier + .testTag("TextField") + .focusRequester(focusRequester) + ) + } + } } LaunchedEffect(focusRequester) { focusRequester.requestFocus() @@ -650,6 +712,11 @@ class TextFieldEditMenuTest { verifyContextMenuItemsHidden(hiddenActions) } + private enum class EditableTextFieldKind { + BasicTextField, + BasicTextField2 + } + @OptIn(ExperimentalFoundationApi::class) private fun runContextMenuTest( newContextMenuEnabled: Boolean, From c91d921449f7eebf122b0ebdaf3a9b05bfa21ba7 Mon Sep 17 00:00:00 2001 From: Janina Davydova Date: Tue, 9 Jun 2026 13:49:43 +0200 Subject: [PATCH 05/12] +test{Old/New}testOldContextMenuBasicTextFieldEditablePartialSelection tests --- .../ui/interaction/TextFieldEditMenuTest.kt | 81 +++++++++++++++++-- 1 file changed, 74 insertions(+), 7 deletions(-) diff --git a/compose/ui/ui/src/uikitInstrumentedTest/kotlin/androidx/compose/ui/interaction/TextFieldEditMenuTest.kt b/compose/ui/ui/src/uikitInstrumentedTest/kotlin/androidx/compose/ui/interaction/TextFieldEditMenuTest.kt index 655ebac31b41b..46d43719d859f 100644 --- a/compose/ui/ui/src/uikitInstrumentedTest/kotlin/androidx/compose/ui/interaction/TextFieldEditMenuTest.kt +++ b/compose/ui/ui/src/uikitInstrumentedTest/kotlin/androidx/compose/ui/interaction/TextFieldEditMenuTest.kt @@ -359,6 +359,42 @@ class TextFieldEditMenuTest { ) } + @Test + fun testOldContextMenuBasicTextFieldEditablePartialSelectionClipboardText() = runContextMenuTest(false) { + verifyEditablePartialSelectionClipboardTextContextMenu( + textFieldKind = EditableTextFieldKind.BasicTextField, + visibleActions = listOf("Cut", "Copy", "Paste", "Select All"), + hiddenActions = listOf("Select") + ) + } + + @Test + fun testOldContextMenuBasicTextField2EditablePartialSelectionClipboardText() = runContextMenuTest(false) { + verifyEditablePartialSelectionClipboardTextContextMenu( + textFieldKind = EditableTextFieldKind.BasicTextField2, + visibleActions = listOf("Cut", "Copy", "Paste", "Select All"), + hiddenActions = listOf("Select") + ) + } + + @Test + fun testNewContextMenuBasicTextFieldEditablePartialSelectionClipboardText() = runContextMenuTest(true) { + verifyEditablePartialSelectionClipboardTextContextMenu( + textFieldKind = EditableTextFieldKind.BasicTextField, + visibleActions = listOf("Cut", "Copy", "Paste", "Select All"), + hiddenActions = listOf("Select") + ) + } + + @Test + fun testNewContextMenuBasicTextField2EditablePartialSelectionClipboardText() = runContextMenuTest(true) { + verifyEditablePartialSelectionClipboardTextContextMenu( + textFieldKind = EditableTextFieldKind.BasicTextField2, + visibleActions = listOf("Cut", "Copy", "Paste", "Select All"), + hiddenActions = listOf("Select") + ) + } + @Test fun testTapsCountingWithMultiTouch() = runUIKitInstrumentedTest { var touchesDown = 0 @@ -672,13 +708,45 @@ class TextFieldEditMenuTest { hiddenActions: List, ) { UIPasteboard.generalPasteboard().string = clipboardText + setEditableTextFieldContent( + textFieldKind = textFieldKind, + initialValue = TextFieldValue("Text", TextRange(4, 4)) + ) + + longPressAndAwaitContextMenu("TextField") + + verifyContextMenuItemsVisible(visibleActions) + verifyContextMenuItemsHidden(hiddenActions) + } + + private fun UIKitInstrumentedTest.verifyEditablePartialSelectionClipboardTextContextMenu( + textFieldKind: EditableTextFieldKind, + visibleActions: List, + hiddenActions: List, + ) { + UIPasteboard.generalPasteboard().string = "Paste text" + setEditableTextFieldContent( + textFieldKind = textFieldKind, + initialValue = TextFieldValue(PARTIAL_SELECTION_TEXT) + ) + + openToolbar("TextField") + + verifyContextMenuItemsVisible(visibleActions) + verifyContextMenuItemsHidden(hiddenActions) + } + + private fun UIKitInstrumentedTest.setEditableTextFieldContent( + textFieldKind: EditableTextFieldKind, + initialValue: TextFieldValue, + ) { setContent { val focusRequester = remember { FocusRequester() } Column(modifier = Modifier.safeDrawingPadding()) { when (textFieldKind) { EditableTextFieldKind.BasicTextField -> { val textFieldValue = remember { - mutableStateOf(TextFieldValue("Text", TextRange(4, 4))) + mutableStateOf(initialValue) } BasicTextField( value = textFieldValue.value, @@ -690,7 +758,7 @@ class TextFieldEditMenuTest { } EditableTextFieldKind.BasicTextField2 -> { val textFieldState = remember { - TextFieldState("Text", TextRange(4, 4)) + TextFieldState(initialValue.text, initialValue.selection) } BasicTextField( state = textFieldState, @@ -705,11 +773,6 @@ class TextFieldEditMenuTest { focusRequester.requestFocus() } } - - longPressAndAwaitContextMenu("TextField") - - verifyContextMenuItemsVisible(visibleActions) - verifyContextMenuItemsHidden(hiddenActions) } private enum class EditableTextFieldKind { @@ -717,6 +780,10 @@ class TextFieldEditMenuTest { BasicTextField2 } + private companion object { + private const val PARTIAL_SELECTION_TEXT = "accomplishment extraordinary magnificent establishment" + } + @OptIn(ExperimentalFoundationApi::class) private fun runContextMenuTest( newContextMenuEnabled: Boolean, From c439e4f7d31820db26dd7c1aec412a06e4b2094a Mon Sep 17 00:00:00 2001 From: Janina Davydova Date: Tue, 9 Jun 2026 16:05:18 +0200 Subject: [PATCH 06/12] + EditableFullSelection menu items tests --- .../ui/interaction/TextFieldEditMenuTest.kt | 106 +++++++++++++++++- 1 file changed, 105 insertions(+), 1 deletion(-) diff --git a/compose/ui/ui/src/uikitInstrumentedTest/kotlin/androidx/compose/ui/interaction/TextFieldEditMenuTest.kt b/compose/ui/ui/src/uikitInstrumentedTest/kotlin/androidx/compose/ui/interaction/TextFieldEditMenuTest.kt index 46d43719d859f..2f32373f918fb 100644 --- a/compose/ui/ui/src/uikitInstrumentedTest/kotlin/androidx/compose/ui/interaction/TextFieldEditMenuTest.kt +++ b/compose/ui/ui/src/uikitInstrumentedTest/kotlin/androidx/compose/ui/interaction/TextFieldEditMenuTest.kt @@ -65,7 +65,6 @@ import kotlin.test.assertFalse import kotlin.test.assertNotNull import kotlin.test.assertNull import kotlin.test.assertTrue -import kotlin.test.fail import kotlin.time.Duration.Companion.seconds import kotlinx.cinterop.ExperimentalForeignApi import org.jetbrains.skiko.OS @@ -395,6 +394,42 @@ class TextFieldEditMenuTest { ) } + @Test + fun testOldContextMenuBasicTextFieldEditableFullSelectionClipboardText() = runContextMenuTest(false) { + verifyEditableFullSelectionClipboardTextContextMenu( + textFieldKind = EditableTextFieldKind.BasicTextField, + visibleActions = listOf("Cut", "Copy", "Paste"), + hiddenActions = listOf("Select", "Select All") + ) + } + + @Test + fun testOldContextMenuBasicTextField2EditableFullSelectionClipboardText() = runContextMenuTest(false) { + verifyEditableFullSelectionClipboardTextContextMenu( + textFieldKind = EditableTextFieldKind.BasicTextField2, + visibleActions = listOf("Cut", "Copy", "Paste"), + hiddenActions = listOf("Select", "Select All") + ) + } + + @Test + fun testNewContextMenuBasicTextFieldEditableFullSelectionClipboardText() = runContextMenuTest(true) { + verifyEditableFullSelectionClipboardTextContextMenu( + textFieldKind = EditableTextFieldKind.BasicTextField, + visibleActions = listOf("Cut", "Copy", "Paste"), + hiddenActions = listOf("Select", "Select All") + ) + } + + @Test + fun testNewContextMenuBasicTextField2EditableFullSelectionClipboardText() = runContextMenuTest(true) { + verifyEditableFullSelectionClipboardTextContextMenu( + textFieldKind = EditableTextFieldKind.BasicTextField2, + visibleActions = listOf("Cut", "Copy", "Paste"), + hiddenActions = listOf("Select", "Select All") + ) + } + @Test fun testTapsCountingWithMultiTouch() = runUIKitInstrumentedTest { var touchesDown = 0 @@ -736,6 +771,75 @@ class TextFieldEditMenuTest { verifyContextMenuItemsHidden(hiddenActions) } + private fun UIKitInstrumentedTest.verifyEditableFullSelectionClipboardTextContextMenu( + textFieldKind: EditableTextFieldKind, + visibleActions: List, + hiddenActions: List, + ) { + UIPasteboard.generalPasteboard().string = "Paste text" + when (textFieldKind) { + EditableTextFieldKind.BasicTextField -> { + val textFieldValue = mutableStateOf(TextFieldValue("Text", TextRange(4, 4))) + setContent { + val focusRequester = remember { FocusRequester() } + Column(modifier = Modifier.safeDrawingPadding()) { + BasicTextField( + value = textFieldValue.value, + onValueChange = { textFieldValue.value = it }, + modifier = Modifier + .testTag("TextField") + .focusRequester(focusRequester) + ) + } + LaunchedEffect(focusRequester) { + focusRequester.requestFocus() + } + } + + longPressAndAwaitContextMenu("TextField") + tapContextMenuButton("Select All") + waitUntil("Text field should be fully selected") { + textFieldValue.value.selection.start == 0 && + textFieldValue.value.selection.end == textFieldValue.value.text.length + } + } + EditableTextFieldKind.BasicTextField2 -> { + val textFieldState = TextFieldState("Text", TextRange(4, 4)) + setContent { + val focusRequester = remember { FocusRequester() } + Column(modifier = Modifier.safeDrawingPadding()) { + BasicTextField( + state = textFieldState, + modifier = Modifier + .testTag("TextField") + .focusRequester(focusRequester) + ) + } + LaunchedEffect(focusRequester) { + focusRequester.requestFocus() + } + } + + // delay(60000) + + longPressAndAwaitContextMenu("TextField") + tapContextMenuButton("Select All") + waitUntil("Text field should be fully selected") { + textFieldState.selection.start == 0 && + textFieldState.selection.end == textFieldState.text.length + } + } + } + + waitUntil("Context menu should update for full selection") { + visibleActions.all { findNodeWithLabelOrNull(it) != null } && + hiddenActions.all { findNodeWithLabelOrNull(it) == null } + } + + verifyContextMenuItemsVisible(visibleActions) + verifyContextMenuItemsHidden(hiddenActions) + } + private fun UIKitInstrumentedTest.setEditableTextFieldContent( textFieldKind: EditableTextFieldKind, initialValue: TextFieldValue, From 84f6246bfa840d712126c3c96643fc7ff9f4aef1 Mon Sep 17 00:00:00 2001 From: Janina Davydova Date: Tue, 9 Jun 2026 17:07:40 +0200 Subject: [PATCH 07/12] + ReadOnly menu items tests --- .../ui/interaction/TextFieldEditMenuTest.kt | 128 ++++++++++++++++-- 1 file changed, 120 insertions(+), 8 deletions(-) diff --git a/compose/ui/ui/src/uikitInstrumentedTest/kotlin/androidx/compose/ui/interaction/TextFieldEditMenuTest.kt b/compose/ui/ui/src/uikitInstrumentedTest/kotlin/androidx/compose/ui/interaction/TextFieldEditMenuTest.kt index 2f32373f918fb..9167bb361451a 100644 --- a/compose/ui/ui/src/uikitInstrumentedTest/kotlin/androidx/compose/ui/interaction/TextFieldEditMenuTest.kt +++ b/compose/ui/ui/src/uikitInstrumentedTest/kotlin/androidx/compose/ui/interaction/TextFieldEditMenuTest.kt @@ -62,7 +62,6 @@ import androidx.compose.ui.unit.dp import kotlin.test.Test import kotlin.test.assertEquals import kotlin.test.assertFalse -import kotlin.test.assertNotNull import kotlin.test.assertNull import kotlin.test.assertTrue import kotlin.time.Duration.Companion.seconds @@ -430,6 +429,78 @@ class TextFieldEditMenuTest { ) } + @Test + fun testOldContextMenuBasicTextFieldReadOnlyCollapsedClipboardText() = runContextMenuTest(false) { + verifyReadOnlyCollapsedClipboardTextContextMenu( + textFieldKind = EditableTextFieldKind.BasicTextField, + visibleActions = listOf("Select All"), + hiddenActions = listOf("Cut", "Copy", "Paste", "Select") + ) + } + + @Test + fun testOldContextMenuBasicTextField2ReadOnlyCollapsedClipboardText() = runContextMenuTest(false) { + verifyReadOnlyCollapsedClipboardTextContextMenu( + textFieldKind = EditableTextFieldKind.BasicTextField2, + visibleActions = listOf("Select All"), + hiddenActions = listOf("Cut", "Copy", "Paste", "Select") + ) + } + + @Test + fun testNewContextMenuBasicTextFieldReadOnlyCollapsedClipboardText() = runContextMenuTest(true) { + verifyReadOnlyCollapsedClipboardTextContextMenu( + textFieldKind = EditableTextFieldKind.BasicTextField, + visibleActions = listOf("Select All"), + hiddenActions = listOf("Cut", "Copy", "Paste", "Select") + ) + } + + @Test + fun testNewContextMenuBasicTextField2ReadOnlyCollapsedClipboardText() = runContextMenuTest(true) { + verifyReadOnlyCollapsedClipboardTextContextMenu( + textFieldKind = EditableTextFieldKind.BasicTextField2, + visibleActions = listOf("Select All"), + hiddenActions = listOf("Cut", "Copy", "Paste", "Select") + ) + } + + @Test + fun testOldContextMenuBasicTextFieldReadOnlyPartialSelectionClipboardText() = runContextMenuTest(false) { + verifyReadOnlyPartialSelectionClipboardTextContextMenu( + textFieldKind = EditableTextFieldKind.BasicTextField, + visibleActions = listOf("Copy", "Select All"), + hiddenActions = listOf("Cut", "Paste", "Select") + ) + } + + @Test + fun testOldContextMenuBasicTextField2ReadOnlyPartialSelectionClipboardText() = runContextMenuTest(false) { + verifyReadOnlyPartialSelectionClipboardTextContextMenu( + textFieldKind = EditableTextFieldKind.BasicTextField2, + visibleActions = listOf("Copy", "Select All"), + hiddenActions = listOf("Cut", "Paste", "Select") + ) + } + + @Test + fun testNewContextMenuBasicTextFieldReadOnlyPartialSelectionClipboardText() = runContextMenuTest(true) { + verifyReadOnlyPartialSelectionClipboardTextContextMenu( + textFieldKind = EditableTextFieldKind.BasicTextField, + visibleActions = listOf("Copy", "Select All"), + hiddenActions = listOf("Cut", "Paste", "Select") + ) + } + + @Test + fun testNewContextMenuBasicTextField2ReadOnlyPartialSelectionClipboardText() = runContextMenuTest(true) { + verifyReadOnlyPartialSelectionClipboardTextContextMenu( + textFieldKind = EditableTextFieldKind.BasicTextField2, + visibleActions = listOf("Copy", "Select All"), + hiddenActions = listOf("Cut", "Paste", "Select") + ) + } + @Test fun testTapsCountingWithMultiTouch() = runUIKitInstrumentedTest { var touchesDown = 0 @@ -743,9 +814,10 @@ class TextFieldEditMenuTest { hiddenActions: List, ) { UIPasteboard.generalPasteboard().string = clipboardText - setEditableTextFieldContent( + setTextFieldContent( textFieldKind = textFieldKind, - initialValue = TextFieldValue("Text", TextRange(4, 4)) + initialValue = TextFieldValue("Text", TextRange(4, 4)), + readOnly = false ) longPressAndAwaitContextMenu("TextField") @@ -760,9 +832,46 @@ class TextFieldEditMenuTest { hiddenActions: List, ) { UIPasteboard.generalPasteboard().string = "Paste text" - setEditableTextFieldContent( + setTextFieldContent( textFieldKind = textFieldKind, - initialValue = TextFieldValue(PARTIAL_SELECTION_TEXT) + initialValue = TextFieldValue(PARTIAL_SELECTION_TEXT), + readOnly = false + ) + + openToolbar("TextField") + + verifyContextMenuItemsVisible(visibleActions) + verifyContextMenuItemsHidden(hiddenActions) + } + + private fun UIKitInstrumentedTest.verifyReadOnlyCollapsedClipboardTextContextMenu( + textFieldKind: EditableTextFieldKind, + visibleActions: List, + hiddenActions: List, + ) { + UIPasteboard.generalPasteboard().string = "Paste text" + setTextFieldContent( + textFieldKind = textFieldKind, + initialValue = TextFieldValue("Text", TextRange(4, 4)), + readOnly = true + ) + + longPressAndAwaitContextMenu("TextField") + + verifyContextMenuItemsVisible(visibleActions) + verifyContextMenuItemsHidden(hiddenActions) + } + + private fun UIKitInstrumentedTest.verifyReadOnlyPartialSelectionClipboardTextContextMenu( + textFieldKind: EditableTextFieldKind, + visibleActions: List, + hiddenActions: List, + ) { + UIPasteboard.generalPasteboard().string = "Paste text" + setTextFieldContent( + textFieldKind = textFieldKind, + initialValue = TextFieldValue(PARTIAL_SELECTION_TEXT), + readOnly = true ) openToolbar("TextField") @@ -840,9 +949,10 @@ class TextFieldEditMenuTest { verifyContextMenuItemsHidden(hiddenActions) } - private fun UIKitInstrumentedTest.setEditableTextFieldContent( + private fun UIKitInstrumentedTest.setTextFieldContent( textFieldKind: EditableTextFieldKind, initialValue: TextFieldValue, + readOnly: Boolean, ) { setContent { val focusRequester = remember { FocusRequester() } @@ -857,7 +967,8 @@ class TextFieldEditMenuTest { onValueChange = { textFieldValue.value = it }, modifier = Modifier .testTag("TextField") - .focusRequester(focusRequester) + .focusRequester(focusRequester), + readOnly = readOnly ) } EditableTextFieldKind.BasicTextField2 -> { @@ -868,7 +979,8 @@ class TextFieldEditMenuTest { state = textFieldState, modifier = Modifier .testTag("TextField") - .focusRequester(focusRequester) + .focusRequester(focusRequester), + readOnly = readOnly ) } } From ca822eba4a358abf6362bac799fda419bd3ffe78 Mon Sep 17 00:00:00 2001 From: Janina Davydova Date: Tue, 9 Jun 2026 19:12:19 +0200 Subject: [PATCH 08/12] Ignore test where menu is not shown after tap --- .../androidx/compose/ui/interaction/TextFieldEditMenuTest.kt | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/compose/ui/ui/src/uikitInstrumentedTest/kotlin/androidx/compose/ui/interaction/TextFieldEditMenuTest.kt b/compose/ui/ui/src/uikitInstrumentedTest/kotlin/androidx/compose/ui/interaction/TextFieldEditMenuTest.kt index 9167bb361451a..7328d14abc9e1 100644 --- a/compose/ui/ui/src/uikitInstrumentedTest/kotlin/androidx/compose/ui/interaction/TextFieldEditMenuTest.kt +++ b/compose/ui/ui/src/uikitInstrumentedTest/kotlin/androidx/compose/ui/interaction/TextFieldEditMenuTest.kt @@ -59,6 +59,7 @@ import androidx.compose.ui.test.waitForContextMenu import androidx.compose.ui.text.TextRange import androidx.compose.ui.text.input.TextFieldValue import androidx.compose.ui.unit.dp +import kotlin.test.Ignore import kotlin.test.Test import kotlin.test.assertEquals import kotlin.test.assertFalse @@ -421,6 +422,7 @@ class TextFieldEditMenuTest { } @Test + @Ignore // CMP-10301: Menu is not shown after tap on Select All fun testNewContextMenuBasicTextField2EditableFullSelectionClipboardText() = runContextMenuTest(true) { verifyEditableFullSelectionClipboardTextContextMenu( textFieldKind = EditableTextFieldKind.BasicTextField2, @@ -929,8 +931,6 @@ class TextFieldEditMenuTest { } } - // delay(60000) - longPressAndAwaitContextMenu("TextField") tapContextMenuButton("Select All") waitUntil("Text field should be fully selected") { From ada8c8ec6750bc0e6282ed77f8fe969ca6c8eae4 Mon Sep 17 00:00:00 2001 From: Janina Davydova Date: Tue, 9 Jun 2026 19:46:30 +0200 Subject: [PATCH 09/12] Refactor duplicated functions --- .../ui/interaction/TextFieldEditMenuTest.kt | 284 ++++++++++-------- 1 file changed, 164 insertions(+), 120 deletions(-) diff --git a/compose/ui/ui/src/uikitInstrumentedTest/kotlin/androidx/compose/ui/interaction/TextFieldEditMenuTest.kt b/compose/ui/ui/src/uikitInstrumentedTest/kotlin/androidx/compose/ui/interaction/TextFieldEditMenuTest.kt index 7328d14abc9e1..47108750ccf45 100644 --- a/compose/ui/ui/src/uikitInstrumentedTest/kotlin/androidx/compose/ui/interaction/TextFieldEditMenuTest.kt +++ b/compose/ui/ui/src/uikitInstrumentedTest/kotlin/androidx/compose/ui/interaction/TextFieldEditMenuTest.kt @@ -287,221 +287,173 @@ class TextFieldEditMenuTest { } @Test - fun testOldContextMenuBasicTextFieldEditableCollapsedClipboardText() = runContextMenuTest(false) { - verifyEditableCollapsedClipboardTextContextMenu( + fun testOldContextMenuBasicTextFieldEditableCollapsedClipboardText() = + runEditableCollapsedClipboardTextContextMenuTest( textFieldKind = EditableTextFieldKind.BasicTextField, - visibleActions = listOf("Paste", "Select", "Select All"), - hiddenActions = listOf("Cut", "Copy") + newContextMenu = false ) - } @Test - fun testOldContextMenuBasicTextField2EditableCollapsedClipboardText() = runContextMenuTest(false) { - verifyEditableCollapsedClipboardTextContextMenu( + fun testOldContextMenuBasicTextField2EditableCollapsedClipboardText() = + runEditableCollapsedClipboardTextContextMenuTest( textFieldKind = EditableTextFieldKind.BasicTextField2, - visibleActions = listOf("Paste", "Select", "Select All"), - hiddenActions = listOf("Cut", "Copy") + newContextMenu = false ) - } @Test - fun testNewContextMenuBasicTextFieldEditableCollapsedClipboardText() = runContextMenuTest(true) { - verifyEditableCollapsedClipboardTextContextMenu( + fun testNewContextMenuBasicTextFieldEditableCollapsedClipboardText() = + runEditableCollapsedClipboardTextContextMenuTest( textFieldKind = EditableTextFieldKind.BasicTextField, - visibleActions = listOf("Paste", "Select All"), - hiddenActions = listOf("Cut", "Copy", "Select") + newContextMenu = true ) - } @Test - fun testNewContextMenuBasicTextField2EditableCollapsedClipboardText() = runContextMenuTest(true) { - verifyEditableCollapsedClipboardTextContextMenu( + fun testNewContextMenuBasicTextField2EditableCollapsedClipboardText() = + runEditableCollapsedClipboardTextContextMenuTest( textFieldKind = EditableTextFieldKind.BasicTextField2, - visibleActions = listOf("Paste", "Select All"), - hiddenActions = listOf("Cut", "Copy", "Select") + newContextMenu = true ) - } @Test - fun testOldContextMenuBasicTextFieldEditableCollapsedClipboardEmpty() = runContextMenuTest(false) { - verifyEditableCollapsedClipboardEmptyContextMenu( + fun testOldContextMenuBasicTextFieldEditableCollapsedClipboardEmpty() = + runEditableCollapsedClipboardEmptyContextMenuTest( textFieldKind = EditableTextFieldKind.BasicTextField, - visibleActions = listOf("Select", "Select All"), - hiddenActions = listOf("Cut", "Copy", "Paste") + newContextMenu = false ) - } @Test - fun testOldContextMenuBasicTextField2EditableCollapsedClipboardEmpty() = runContextMenuTest(false) { - verifyEditableCollapsedClipboardEmptyContextMenu( + fun testOldContextMenuBasicTextField2EditableCollapsedClipboardEmpty() = + runEditableCollapsedClipboardEmptyContextMenuTest( textFieldKind = EditableTextFieldKind.BasicTextField2, - visibleActions = listOf("Select", "Select All"), - hiddenActions = listOf("Cut", "Copy", "Paste") + newContextMenu = false ) - } @Test - fun testNewContextMenuBasicTextFieldEditableCollapsedClipboardEmpty() = runContextMenuTest(true) { - verifyEditableCollapsedClipboardEmptyContextMenu( + fun testNewContextMenuBasicTextFieldEditableCollapsedClipboardEmpty() = + runEditableCollapsedClipboardEmptyContextMenuTest( textFieldKind = EditableTextFieldKind.BasicTextField, - visibleActions = listOf("Select All"), - hiddenActions = listOf("Cut", "Copy", "Paste", "Select") + newContextMenu = true ) - } @Test - fun testNewContextMenuBasicTextField2EditableCollapsedClipboardEmpty() = runContextMenuTest(true) { - verifyEditableCollapsedClipboardEmptyContextMenu( + fun testNewContextMenuBasicTextField2EditableCollapsedClipboardEmpty() = + runEditableCollapsedClipboardEmptyContextMenuTest( textFieldKind = EditableTextFieldKind.BasicTextField2, - visibleActions = listOf("Select All"), - hiddenActions = listOf("Cut", "Copy", "Paste", "Select") + newContextMenu = true ) - } @Test - fun testOldContextMenuBasicTextFieldEditablePartialSelectionClipboardText() = runContextMenuTest(false) { - verifyEditablePartialSelectionClipboardTextContextMenu( + fun testOldContextMenuBasicTextFieldEditablePartialSelectionClipboardText() = + runEditablePartialSelectionClipboardTextContextMenuTest( textFieldKind = EditableTextFieldKind.BasicTextField, - visibleActions = listOf("Cut", "Copy", "Paste", "Select All"), - hiddenActions = listOf("Select") + newContextMenu = false ) - } @Test - fun testOldContextMenuBasicTextField2EditablePartialSelectionClipboardText() = runContextMenuTest(false) { - verifyEditablePartialSelectionClipboardTextContextMenu( + fun testOldContextMenuBasicTextField2EditablePartialSelectionClipboardText() = + runEditablePartialSelectionClipboardTextContextMenuTest( textFieldKind = EditableTextFieldKind.BasicTextField2, - visibleActions = listOf("Cut", "Copy", "Paste", "Select All"), - hiddenActions = listOf("Select") + newContextMenu = false ) - } @Test - fun testNewContextMenuBasicTextFieldEditablePartialSelectionClipboardText() = runContextMenuTest(true) { - verifyEditablePartialSelectionClipboardTextContextMenu( + fun testNewContextMenuBasicTextFieldEditablePartialSelectionClipboardText() = + runEditablePartialSelectionClipboardTextContextMenuTest( textFieldKind = EditableTextFieldKind.BasicTextField, - visibleActions = listOf("Cut", "Copy", "Paste", "Select All"), - hiddenActions = listOf("Select") + newContextMenu = true ) - } @Test - fun testNewContextMenuBasicTextField2EditablePartialSelectionClipboardText() = runContextMenuTest(true) { - verifyEditablePartialSelectionClipboardTextContextMenu( + fun testNewContextMenuBasicTextField2EditablePartialSelectionClipboardText() = + runEditablePartialSelectionClipboardTextContextMenuTest( textFieldKind = EditableTextFieldKind.BasicTextField2, - visibleActions = listOf("Cut", "Copy", "Paste", "Select All"), - hiddenActions = listOf("Select") + newContextMenu = true ) - } @Test - fun testOldContextMenuBasicTextFieldEditableFullSelectionClipboardText() = runContextMenuTest(false) { - verifyEditableFullSelectionClipboardTextContextMenu( + fun testOldContextMenuBasicTextFieldEditableFullSelectionClipboardText() = + runEditableFullSelectionClipboardTextContextMenuTest( textFieldKind = EditableTextFieldKind.BasicTextField, - visibleActions = listOf("Cut", "Copy", "Paste"), - hiddenActions = listOf("Select", "Select All") + newContextMenu = false ) - } @Test - fun testOldContextMenuBasicTextField2EditableFullSelectionClipboardText() = runContextMenuTest(false) { - verifyEditableFullSelectionClipboardTextContextMenu( + fun testOldContextMenuBasicTextField2EditableFullSelectionClipboardText() = + runEditableFullSelectionClipboardTextContextMenuTest( textFieldKind = EditableTextFieldKind.BasicTextField2, - visibleActions = listOf("Cut", "Copy", "Paste"), - hiddenActions = listOf("Select", "Select All") + newContextMenu = false ) - } @Test - fun testNewContextMenuBasicTextFieldEditableFullSelectionClipboardText() = runContextMenuTest(true) { - verifyEditableFullSelectionClipboardTextContextMenu( + fun testNewContextMenuBasicTextFieldEditableFullSelectionClipboardText() = + runEditableFullSelectionClipboardTextContextMenuTest( textFieldKind = EditableTextFieldKind.BasicTextField, - visibleActions = listOf("Cut", "Copy", "Paste"), - hiddenActions = listOf("Select", "Select All") + newContextMenu = true ) - } @Test @Ignore // CMP-10301: Menu is not shown after tap on Select All - fun testNewContextMenuBasicTextField2EditableFullSelectionClipboardText() = runContextMenuTest(true) { - verifyEditableFullSelectionClipboardTextContextMenu( + fun testNewContextMenuBasicTextField2EditableFullSelectionClipboardText() = + runEditableFullSelectionClipboardTextContextMenuTest( textFieldKind = EditableTextFieldKind.BasicTextField2, - visibleActions = listOf("Cut", "Copy", "Paste"), - hiddenActions = listOf("Select", "Select All") + newContextMenu = true ) - } @Test - fun testOldContextMenuBasicTextFieldReadOnlyCollapsedClipboardText() = runContextMenuTest(false) { - verifyReadOnlyCollapsedClipboardTextContextMenu( + fun testOldContextMenuBasicTextFieldReadOnlyCollapsedClipboardText() = + runReadOnlyCollapsedClipboardTextContextMenuTest( textFieldKind = EditableTextFieldKind.BasicTextField, - visibleActions = listOf("Select All"), - hiddenActions = listOf("Cut", "Copy", "Paste", "Select") + newContextMenu = false ) - } @Test - fun testOldContextMenuBasicTextField2ReadOnlyCollapsedClipboardText() = runContextMenuTest(false) { - verifyReadOnlyCollapsedClipboardTextContextMenu( + fun testOldContextMenuBasicTextField2ReadOnlyCollapsedClipboardText() = + runReadOnlyCollapsedClipboardTextContextMenuTest( textFieldKind = EditableTextFieldKind.BasicTextField2, - visibleActions = listOf("Select All"), - hiddenActions = listOf("Cut", "Copy", "Paste", "Select") + newContextMenu = false ) - } @Test - fun testNewContextMenuBasicTextFieldReadOnlyCollapsedClipboardText() = runContextMenuTest(true) { - verifyReadOnlyCollapsedClipboardTextContextMenu( + fun testNewContextMenuBasicTextFieldReadOnlyCollapsedClipboardText() = + runReadOnlyCollapsedClipboardTextContextMenuTest( textFieldKind = EditableTextFieldKind.BasicTextField, - visibleActions = listOf("Select All"), - hiddenActions = listOf("Cut", "Copy", "Paste", "Select") + newContextMenu = true ) - } @Test - fun testNewContextMenuBasicTextField2ReadOnlyCollapsedClipboardText() = runContextMenuTest(true) { - verifyReadOnlyCollapsedClipboardTextContextMenu( + fun testNewContextMenuBasicTextField2ReadOnlyCollapsedClipboardText() = + runReadOnlyCollapsedClipboardTextContextMenuTest( textFieldKind = EditableTextFieldKind.BasicTextField2, - visibleActions = listOf("Select All"), - hiddenActions = listOf("Cut", "Copy", "Paste", "Select") + newContextMenu = true ) - } @Test - fun testOldContextMenuBasicTextFieldReadOnlyPartialSelectionClipboardText() = runContextMenuTest(false) { - verifyReadOnlyPartialSelectionClipboardTextContextMenu( + fun testOldContextMenuBasicTextFieldReadOnlyPartialSelectionClipboardText() = + runReadOnlyPartialSelectionClipboardTextContextMenuTest( textFieldKind = EditableTextFieldKind.BasicTextField, - visibleActions = listOf("Copy", "Select All"), - hiddenActions = listOf("Cut", "Paste", "Select") + newContextMenu = false ) - } @Test - fun testOldContextMenuBasicTextField2ReadOnlyPartialSelectionClipboardText() = runContextMenuTest(false) { - verifyReadOnlyPartialSelectionClipboardTextContextMenu( + fun testOldContextMenuBasicTextField2ReadOnlyPartialSelectionClipboardText() = + runReadOnlyPartialSelectionClipboardTextContextMenuTest( textFieldKind = EditableTextFieldKind.BasicTextField2, - visibleActions = listOf("Copy", "Select All"), - hiddenActions = listOf("Cut", "Paste", "Select") + newContextMenu = false ) - } @Test - fun testNewContextMenuBasicTextFieldReadOnlyPartialSelectionClipboardText() = runContextMenuTest(true) { - verifyReadOnlyPartialSelectionClipboardTextContextMenu( + fun testNewContextMenuBasicTextFieldReadOnlyPartialSelectionClipboardText() = + runReadOnlyPartialSelectionClipboardTextContextMenuTest( textFieldKind = EditableTextFieldKind.BasicTextField, - visibleActions = listOf("Copy", "Select All"), - hiddenActions = listOf("Cut", "Paste", "Select") + newContextMenu = true ) - } @Test - fun testNewContextMenuBasicTextField2ReadOnlyPartialSelectionClipboardText() = runContextMenuTest(true) { - verifyReadOnlyPartialSelectionClipboardTextContextMenu( + fun testNewContextMenuBasicTextField2ReadOnlyPartialSelectionClipboardText() = + runReadOnlyPartialSelectionClipboardTextContextMenuTest( textFieldKind = EditableTextFieldKind.BasicTextField2, - visibleActions = listOf("Copy", "Select All"), - hiddenActions = listOf("Cut", "Paste", "Select") + newContextMenu = true ) - } @Test fun testTapsCountingWithMultiTouch() = runUIKitInstrumentedTest { @@ -774,6 +726,98 @@ class TextFieldEditMenuTest { waitForContextMenu() } + private fun runEditableCollapsedClipboardTextContextMenuTest( + textFieldKind: EditableTextFieldKind, + newContextMenu: Boolean, + ) = runContextMenuTest(newContextMenu) { + val visibleActions = + if (newContextMenu) { + listOf("Paste", "Select All") + } else { + listOf("Paste", "Select", "Select All") + } + val hiddenActions = + if (newContextMenu) { + listOf("Cut", "Copy", "Select") + } else { + listOf("Cut", "Copy") + } + + verifyEditableCollapsedClipboardTextContextMenu( + textFieldKind = textFieldKind, + visibleActions = visibleActions, + hiddenActions = hiddenActions + ) + } + + private fun runEditableCollapsedClipboardEmptyContextMenuTest( + textFieldKind: EditableTextFieldKind, + newContextMenu: Boolean, + ) = runContextMenuTest(newContextMenu) { + val visibleActions = + if (newContextMenu) { + listOf("Select All") + } else { + listOf("Select", "Select All") + } + val hiddenActions = + if (newContextMenu) { + listOf("Cut", "Copy", "Paste", "Select") + } else { + listOf("Cut", "Copy", "Paste") + } + + verifyEditableCollapsedClipboardEmptyContextMenu( + textFieldKind = textFieldKind, + visibleActions = visibleActions, + hiddenActions = hiddenActions + ) + } + + private fun runEditablePartialSelectionClipboardTextContextMenuTest( + textFieldKind: EditableTextFieldKind, + newContextMenu: Boolean, + ) = runContextMenuTest(newContextMenu) { + verifyEditablePartialSelectionClipboardTextContextMenu( + textFieldKind = textFieldKind, + visibleActions = listOf("Cut", "Copy", "Paste", "Select All"), + hiddenActions = listOf("Select") + ) + } + + private fun runEditableFullSelectionClipboardTextContextMenuTest( + textFieldKind: EditableTextFieldKind, + newContextMenu: Boolean, + ) = runContextMenuTest(newContextMenu) { + verifyEditableFullSelectionClipboardTextContextMenu( + textFieldKind = textFieldKind, + visibleActions = listOf("Cut", "Copy", "Paste"), + hiddenActions = listOf("Select", "Select All") + ) + } + + private fun runReadOnlyCollapsedClipboardTextContextMenuTest( + textFieldKind: EditableTextFieldKind, + newContextMenu: Boolean, + ) = runContextMenuTest(newContextMenu) { + verifyReadOnlyCollapsedClipboardTextContextMenu( + textFieldKind = textFieldKind, + visibleActions = listOf("Select All"), + hiddenActions = listOf("Cut", "Copy", "Paste", "Select") + ) + } + + private fun runReadOnlyPartialSelectionClipboardTextContextMenuTest( + textFieldKind: EditableTextFieldKind, + newContextMenu: Boolean, + ) = runContextMenuTest(newContextMenu) { + verifyReadOnlyPartialSelectionClipboardTextContextMenu( + textFieldKind = textFieldKind, + visibleActions = listOf("Copy", "Select All"), + hiddenActions = listOf("Cut", "Paste", "Select") + ) + } + private fun UIKitInstrumentedTest.longPressAndAwaitContextMenu(textFieldTag: String) { val touch = findNodeWithTag(textFieldTag).touchDown() waitUntil { From bb599407c21086f02951e489e01cabfcc5272ea4 Mon Sep 17 00:00:00 2001 From: Janina Davydova Date: Tue, 9 Jun 2026 20:01:59 +0200 Subject: [PATCH 10/12] Extract repeated modifier into function --- .../ui/interaction/TextFieldEditMenuTest.kt | 49 +++++++------------ 1 file changed, 19 insertions(+), 30 deletions(-) diff --git a/compose/ui/ui/src/uikitInstrumentedTest/kotlin/androidx/compose/ui/interaction/TextFieldEditMenuTest.kt b/compose/ui/ui/src/uikitInstrumentedTest/kotlin/androidx/compose/ui/interaction/TextFieldEditMenuTest.kt index 47108750ccf45..131f9d836a4c2 100644 --- a/compose/ui/ui/src/uikitInstrumentedTest/kotlin/androidx/compose/ui/interaction/TextFieldEditMenuTest.kt +++ b/compose/ui/ui/src/uikitInstrumentedTest/kotlin/androidx/compose/ui/interaction/TextFieldEditMenuTest.kt @@ -83,7 +83,7 @@ class TextFieldEditMenuTest { BasicTextField( textValue.value, { textValue.value = it }, - modifier = Modifier.testTag("TextField").focusRequester(focusRequester) + modifier = textFieldModifier(focusRequester) ) } LaunchedEffect(focusRequester) { @@ -105,7 +105,7 @@ class TextFieldEditMenuTest { Column(modifier = Modifier.safeDrawingPadding()) { BasicTextField( textFieldState, - modifier = Modifier.testTag("TextField").focusRequester(focusRequester) + modifier = textFieldModifier(focusRequester) ) } LaunchedEffect(focusRequester) { @@ -124,7 +124,7 @@ class TextFieldEditMenuTest { setContent { val focusRequester = remember { FocusRequester() } Column(modifier = Modifier.safeDrawingPadding()) { - TextField("Hello-LongLongLongLongLong-text", {}, modifier = Modifier.testTag("TextField").focusRequester(focusRequester)) + TextField("Hello-LongLongLongLongLong-text", {}, modifier = textFieldModifier(focusRequester)) } LaunchedEffect(focusRequester) { focusRequester.requestFocus() @@ -143,7 +143,7 @@ class TextFieldEditMenuTest { setContent { val focusRequester = remember { FocusRequester() } Column(modifier = Modifier.safeDrawingPadding()) { - BasicTextField(textFieldState, modifier = Modifier.testTag("TextField").focusRequester(focusRequester)) + BasicTextField(textFieldState, modifier = textFieldModifier(focusRequester)) } LaunchedEffect(focusRequester) { focusRequester.requestFocus() @@ -164,7 +164,7 @@ class TextFieldEditMenuTest { BasicTextField( value = textFieldValue.value, onValueChange = { textFieldValue.value = it }, - modifier = Modifier.testTag("TextField").focusRequester(focusRequester) + modifier = textFieldModifier(focusRequester) ) } LaunchedEffect(focusRequester) { @@ -193,7 +193,7 @@ class TextFieldEditMenuTest { setContent { val focusRequester = remember { FocusRequester() } Column(modifier = Modifier.safeDrawingPadding()) { - BasicTextField(textFieldState, modifier = Modifier.testTag("TextField").focusRequester(focusRequester)) + BasicTextField(textFieldState, modifier = textFieldModifier(focusRequester)) } LaunchedEffect(focusRequester) { focusRequester.requestFocus() @@ -225,9 +225,7 @@ class TextFieldEditMenuTest { BasicTextField( value = textFieldValue.value, onValueChange = { textFieldValue.value = it }, - modifier = Modifier - .testTag("TextField") - .focusRequester(focusRequester) + modifier = textFieldModifier(focusRequester) ) } LaunchedEffect(focusRequester) { @@ -261,9 +259,7 @@ class TextFieldEditMenuTest { Column(modifier = Modifier.safeDrawingPadding()) { BasicTextField( state = textFieldState, - modifier = Modifier - .testTag("TextField") - .focusRequester(focusRequester) + modifier = textFieldModifier(focusRequester) ) } LaunchedEffect(focusRequester) { @@ -602,9 +598,7 @@ class TextFieldEditMenuTest { BasicTextField( value = textFieldValue.value, onValueChange = { textFieldValue.value = it }, - modifier = Modifier - .testTag("TextField") - .focusRequester(focusRequester) + modifier = textFieldModifier(focusRequester) .appendTextContextMenuComponents { item(key = "CustomKey", label = "Custom Action") { customItemClicked = true @@ -646,9 +640,7 @@ class TextFieldEditMenuTest { Column(modifier = Modifier.safeDrawingPadding()) { BasicTextField( state = textFieldState, - modifier = Modifier - .testTag("TextField") - .focusRequester(focusRequester) + modifier = textFieldModifier(focusRequester) .appendTextContextMenuComponents { item(key = "CustomKey", label = "Custom Action") { customItemClicked = true @@ -726,6 +718,11 @@ class TextFieldEditMenuTest { waitForContextMenu() } + private fun textFieldModifier(focusRequester: FocusRequester): Modifier = + Modifier + .testTag("TextField") + .focusRequester(focusRequester) + private fun runEditableCollapsedClipboardTextContextMenuTest( textFieldKind: EditableTextFieldKind, newContextMenu: Boolean, @@ -941,9 +938,7 @@ class TextFieldEditMenuTest { BasicTextField( value = textFieldValue.value, onValueChange = { textFieldValue.value = it }, - modifier = Modifier - .testTag("TextField") - .focusRequester(focusRequester) + modifier = textFieldModifier(focusRequester) ) } LaunchedEffect(focusRequester) { @@ -965,9 +960,7 @@ class TextFieldEditMenuTest { Column(modifier = Modifier.safeDrawingPadding()) { BasicTextField( state = textFieldState, - modifier = Modifier - .testTag("TextField") - .focusRequester(focusRequester) + modifier = textFieldModifier(focusRequester) ) } LaunchedEffect(focusRequester) { @@ -1009,9 +1002,7 @@ class TextFieldEditMenuTest { BasicTextField( value = textFieldValue.value, onValueChange = { textFieldValue.value = it }, - modifier = Modifier - .testTag("TextField") - .focusRequester(focusRequester), + modifier = textFieldModifier(focusRequester), readOnly = readOnly ) } @@ -1021,9 +1012,7 @@ class TextFieldEditMenuTest { } BasicTextField( state = textFieldState, - modifier = Modifier - .testTag("TextField") - .focusRequester(focusRequester), + modifier = textFieldModifier(focusRequester), readOnly = readOnly ) } From e8d9bd63f3bf67762a1e65cd0dcb4eab84cc7d84 Mon Sep 17 00:00:00 2001 From: Janina Davydova Date: Tue, 16 Jun 2026 11:31:57 +0200 Subject: [PATCH 11/12] introduce runComplexTextFieldTest function --- .../ui/interaction/TextFieldEditMenuTest.kt | 54 +++++++++++-------- 1 file changed, 31 insertions(+), 23 deletions(-) diff --git a/compose/ui/ui/src/uikitInstrumentedTest/kotlin/androidx/compose/ui/interaction/TextFieldEditMenuTest.kt b/compose/ui/ui/src/uikitInstrumentedTest/kotlin/androidx/compose/ui/interaction/TextFieldEditMenuTest.kt index 131f9d836a4c2..9f6e028b2f106 100644 --- a/compose/ui/ui/src/uikitInstrumentedTest/kotlin/androidx/compose/ui/interaction/TextFieldEditMenuTest.kt +++ b/compose/ui/ui/src/uikitInstrumentedTest/kotlin/androidx/compose/ui/interaction/TextFieldEditMenuTest.kt @@ -283,32 +283,40 @@ class TextFieldEditMenuTest { } @Test - fun testOldContextMenuBasicTextFieldEditableCollapsedClipboardText() = - runEditableCollapsedClipboardTextContextMenuTest( - textFieldKind = EditableTextFieldKind.BasicTextField, - newContextMenu = false - ) + fun testEditableCollapsedClipboardText() = + runComplexTextFieldTest { textFieldKind, newContextMenu -> + UIPasteboard.generalPasteboard().string = "Paste text" + setTextFieldContent( + textFieldKind = textFieldKind, + initialValue = TextFieldValue("Text", TextRange(4, 4)), + readOnly = false + ) - @Test - fun testOldContextMenuBasicTextField2EditableCollapsedClipboardText() = - runEditableCollapsedClipboardTextContextMenuTest( - textFieldKind = EditableTextFieldKind.BasicTextField2, - newContextMenu = false - ) + longPressAndAwaitContextMenu("TextField") + verifyContextMenuItemsVisible(labels = if (newContextMenu) { + listOf("Paste", "Select All") + } else { + listOf("Paste", "Select", "Select All") + }) - @Test - fun testNewContextMenuBasicTextFieldEditableCollapsedClipboardText() = - runEditableCollapsedClipboardTextContextMenuTest( - textFieldKind = EditableTextFieldKind.BasicTextField, - newContextMenu = true - ) + verifyContextMenuItemsHidden( + labels = if (newContextMenu) { + listOf("Cut", "Copy", "Select") + } else { + listOf("Cut", "Copy") + } + ) + } - @Test - fun testNewContextMenuBasicTextField2EditableCollapsedClipboardText() = - runEditableCollapsedClipboardTextContextMenuTest( - textFieldKind = EditableTextFieldKind.BasicTextField2, - newContextMenu = true - ) + private fun runComplexTextFieldTest(test: UIKitInstrumentedTest.(EditableTextFieldKind, newContextMenuEnabled: Boolean) -> Unit) { + for (newContextMenuEnabled in arrayOf(false, true)) { + for (textFieldKind in EditableTextFieldKind.entries) { + runContextMenuTest(newContextMenuEnabled) { + test(textFieldKind, newContextMenuEnabled) + } + } + } + } @Test fun testOldContextMenuBasicTextFieldEditableCollapsedClipboardEmpty() = From 33e1f585289dd39d58c077653b30672dbe1fb890 Mon Sep 17 00:00:00 2001 From: Janina Davydova Date: Tue, 16 Jun 2026 16:33:49 +0200 Subject: [PATCH 12/12] address review comments --- .../ui/interaction/TextFieldEditMenuTest.kt | 514 +++++------------- 1 file changed, 141 insertions(+), 373 deletions(-) diff --git a/compose/ui/ui/src/uikitInstrumentedTest/kotlin/androidx/compose/ui/interaction/TextFieldEditMenuTest.kt b/compose/ui/ui/src/uikitInstrumentedTest/kotlin/androidx/compose/ui/interaction/TextFieldEditMenuTest.kt index 9f6e028b2f106..3ed04829cf51b 100644 --- a/compose/ui/ui/src/uikitInstrumentedTest/kotlin/androidx/compose/ui/interaction/TextFieldEditMenuTest.kt +++ b/compose/ui/ui/src/uikitInstrumentedTest/kotlin/androidx/compose/ui/interaction/TextFieldEditMenuTest.kt @@ -293,11 +293,13 @@ class TextFieldEditMenuTest { ) longPressAndAwaitContextMenu("TextField") - verifyContextMenuItemsVisible(labels = if (newContextMenu) { - listOf("Paste", "Select All") - } else { - listOf("Paste", "Select", "Select All") - }) + verifyContextMenuItemsVisible( + labels = if (newContextMenu) { + listOf("Paste", "Select All") + } else { + listOf("Paste", "Select", "Select All") + } + ) verifyContextMenuItemsHidden( labels = if (newContextMenu) { @@ -319,145 +321,165 @@ class TextFieldEditMenuTest { } @Test - fun testOldContextMenuBasicTextFieldEditableCollapsedClipboardEmpty() = - runEditableCollapsedClipboardEmptyContextMenuTest( - textFieldKind = EditableTextFieldKind.BasicTextField, - newContextMenu = false - ) + fun testEditableCollapsedClipboardEmpty() = + runComplexTextFieldTest { textFieldKind, newContextMenu -> + UIPasteboard.generalPasteboard().string = null + setTextFieldContent( + textFieldKind = textFieldKind, + initialValue = TextFieldValue("Text", TextRange(4, 4)), + readOnly = false + ) - @Test - fun testOldContextMenuBasicTextField2EditableCollapsedClipboardEmpty() = - runEditableCollapsedClipboardEmptyContextMenuTest( - textFieldKind = EditableTextFieldKind.BasicTextField2, - newContextMenu = false - ) + longPressAndAwaitContextMenu("TextField") + verifyContextMenuItemsVisible( + labels = if (newContextMenu) { + listOf("Select All") + } else { + listOf("Select", "Select All") + } + ) - @Test - fun testNewContextMenuBasicTextFieldEditableCollapsedClipboardEmpty() = - runEditableCollapsedClipboardEmptyContextMenuTest( - textFieldKind = EditableTextFieldKind.BasicTextField, - newContextMenu = true - ) + verifyContextMenuItemsHidden( + labels = if (newContextMenu) { + listOf("Cut", "Copy", "Paste", "Select") + } else { + listOf("Cut", "Copy", "Paste") + } + ) + } @Test - fun testNewContextMenuBasicTextField2EditableCollapsedClipboardEmpty() = - runEditableCollapsedClipboardEmptyContextMenuTest( - textFieldKind = EditableTextFieldKind.BasicTextField2, - newContextMenu = true - ) + fun testEditablePartialSelectionClipboardText() = + runComplexTextFieldTest { textFieldKind, _ -> + UIPasteboard.generalPasteboard().string = "Paste text" + setTextFieldContent( + textFieldKind = textFieldKind, + initialValue = TextFieldValue(PARTIAL_SELECTION_TEXT), + readOnly = false + ) - @Test - fun testOldContextMenuBasicTextFieldEditablePartialSelectionClipboardText() = - runEditablePartialSelectionClipboardTextContextMenuTest( - textFieldKind = EditableTextFieldKind.BasicTextField, - newContextMenu = false - ) + openToolbar("TextField") + verifyContextMenuItemsVisible(labels = listOf("Cut", "Copy", "Paste", "Select All")) + verifyContextMenuItemsHidden(labels = listOf("Select")) + } @Test - fun testOldContextMenuBasicTextField2EditablePartialSelectionClipboardText() = - runEditablePartialSelectionClipboardTextContextMenuTest( - textFieldKind = EditableTextFieldKind.BasicTextField2, - newContextMenu = false - ) + fun testEditableFullSelectionClipboardTextBasicTextField() { + for (newContextMenuEnabled in arrayOf(false, true)) { + runEditableFullSelectionClipboardTextTest(newContextMenuEnabled) { + val textFieldValue = mutableStateOf(TextFieldValue("Text", TextRange(4, 4))) + setContent { + val focusRequester = remember { FocusRequester() } + Column(modifier = Modifier.safeDrawingPadding()) { + BasicTextField( + value = textFieldValue.value, + onValueChange = { textFieldValue.value = it }, + modifier = textFieldModifier(focusRequester) + ) + } + LaunchedEffect(focusRequester) { + focusRequester.requestFocus() + } + } - @Test - fun testNewContextMenuBasicTextFieldEditablePartialSelectionClipboardText() = - runEditablePartialSelectionClipboardTextContextMenuTest( - textFieldKind = EditableTextFieldKind.BasicTextField, - newContextMenu = true - ) + val isFullySelected = { + val selection = textFieldValue.value.selection + selection.start == 0 && selection.end == textFieldValue.value.text.length + } + isFullySelected + } + } + } @Test - fun testNewContextMenuBasicTextField2EditablePartialSelectionClipboardText() = - runEditablePartialSelectionClipboardTextContextMenuTest( - textFieldKind = EditableTextFieldKind.BasicTextField2, - newContextMenu = true - ) + fun testEditableFullSelectionClipboardTextBasicTextField2OldContextMenu() = + runEditableFullSelectionClipboardTextTest(newContextMenuEnabled = false) { + runEditableFullSelectionClipboardTextBasicTextField2() + } @Test - fun testOldContextMenuBasicTextFieldEditableFullSelectionClipboardText() = - runEditableFullSelectionClipboardTextContextMenuTest( - textFieldKind = EditableTextFieldKind.BasicTextField, - newContextMenu = false - ) + @Ignore // CMP-10301: Menu is not shown after tap on Select All + fun testEditableFullSelectionClipboardTextBasicTextField2NewContextMenu() = + runEditableFullSelectionClipboardTextTest(newContextMenuEnabled = true) { + runEditableFullSelectionClipboardTextBasicTextField2() + } - @Test - fun testOldContextMenuBasicTextField2EditableFullSelectionClipboardText() = - runEditableFullSelectionClipboardTextContextMenuTest( - textFieldKind = EditableTextFieldKind.BasicTextField2, - newContextMenu = false - ) + private fun UIKitInstrumentedTest.runEditableFullSelectionClipboardTextBasicTextField2(): () -> Boolean { + val textFieldState = TextFieldState("Text", TextRange(4, 4)) + setContent { + val focusRequester = remember { FocusRequester() } + Column(modifier = Modifier.safeDrawingPadding()) { + BasicTextField( + state = textFieldState, + modifier = textFieldModifier(focusRequester) + ) + } + LaunchedEffect(focusRequester) { + focusRequester.requestFocus() + } + } - @Test - fun testNewContextMenuBasicTextFieldEditableFullSelectionClipboardText() = - runEditableFullSelectionClipboardTextContextMenuTest( - textFieldKind = EditableTextFieldKind.BasicTextField, - newContextMenu = true - ) + return { + val selection = textFieldState.selection + selection.start == 0 && selection.end == textFieldState.text.length + } + } - @Test - @Ignore // CMP-10301: Menu is not shown after tap on Select All - fun testNewContextMenuBasicTextField2EditableFullSelectionClipboardText() = - runEditableFullSelectionClipboardTextContextMenuTest( - textFieldKind = EditableTextFieldKind.BasicTextField2, - newContextMenu = true - ) + private fun runEditableFullSelectionClipboardTextTest( + newContextMenuEnabled: Boolean, + setContentAndGetIsFullySelected: UIKitInstrumentedTest.() -> () -> Boolean + ) = + runContextMenuTest(newContextMenuEnabled) { + UIPasteboard.generalPasteboard().string = "Paste text" + val isFullySelected = setContentAndGetIsFullySelected() - @Test - fun testOldContextMenuBasicTextFieldReadOnlyCollapsedClipboardText() = - runReadOnlyCollapsedClipboardTextContextMenuTest( - textFieldKind = EditableTextFieldKind.BasicTextField, - newContextMenu = false - ) + longPressAndAwaitContextMenu("TextField") + tapContextMenuButton("Select All") + waitUntil("Text field should be fully selected") { + isFullySelected() + } - @Test - fun testOldContextMenuBasicTextField2ReadOnlyCollapsedClipboardText() = - runReadOnlyCollapsedClipboardTextContextMenuTest( - textFieldKind = EditableTextFieldKind.BasicTextField2, - newContextMenu = false - ) + val visible = listOf("Cut", "Copy", "Paste") + val hidden = listOf("Select", "Select All") - @Test - fun testNewContextMenuBasicTextFieldReadOnlyCollapsedClipboardText() = - runReadOnlyCollapsedClipboardTextContextMenuTest( - textFieldKind = EditableTextFieldKind.BasicTextField, - newContextMenu = true - ) + waitUntil("Context menu should update for full selection") { + visible.all { findNodeWithLabelOrNull(it) != null } && + hidden.all { findNodeWithLabelOrNull(it) == null } + } - @Test - fun testNewContextMenuBasicTextField2ReadOnlyCollapsedClipboardText() = - runReadOnlyCollapsedClipboardTextContextMenuTest( - textFieldKind = EditableTextFieldKind.BasicTextField2, - newContextMenu = true - ) + verifyContextMenuItemsVisible(labels = visible) + verifyContextMenuItemsHidden(labels = hidden) + } @Test - fun testOldContextMenuBasicTextFieldReadOnlyPartialSelectionClipboardText() = - runReadOnlyPartialSelectionClipboardTextContextMenuTest( - textFieldKind = EditableTextFieldKind.BasicTextField, - newContextMenu = false - ) + fun testReadOnlyCollapsedClipboardText() = + runComplexTextFieldTest { textFieldKind, _ -> + UIPasteboard.generalPasteboard().string = "Paste text" + setTextFieldContent( + textFieldKind = textFieldKind, + initialValue = TextFieldValue("Text", TextRange(4, 4)), + readOnly = true + ) - @Test - fun testOldContextMenuBasicTextField2ReadOnlyPartialSelectionClipboardText() = - runReadOnlyPartialSelectionClipboardTextContextMenuTest( - textFieldKind = EditableTextFieldKind.BasicTextField2, - newContextMenu = false - ) + longPressAndAwaitContextMenu("TextField") + verifyContextMenuItemsVisible(labels = listOf("Select All")) + verifyContextMenuItemsHidden(labels = listOf("Cut", "Copy", "Paste", "Select")) + } @Test - fun testNewContextMenuBasicTextFieldReadOnlyPartialSelectionClipboardText() = - runReadOnlyPartialSelectionClipboardTextContextMenuTest( - textFieldKind = EditableTextFieldKind.BasicTextField, - newContextMenu = true - ) + fun testReadOnlyPartialSelectionClipboardText() = + runComplexTextFieldTest { textFieldKind, _ -> + UIPasteboard.generalPasteboard().string = "Paste text" + setTextFieldContent( + textFieldKind = textFieldKind, + initialValue = TextFieldValue(PARTIAL_SELECTION_TEXT), + readOnly = true + ) - @Test - fun testNewContextMenuBasicTextField2ReadOnlyPartialSelectionClipboardText() = - runReadOnlyPartialSelectionClipboardTextContextMenuTest( - textFieldKind = EditableTextFieldKind.BasicTextField2, - newContextMenu = true - ) + openToolbar("TextField") + verifyContextMenuItemsVisible(labels = listOf("Copy", "Select All")) + verifyContextMenuItemsHidden(labels = listOf("Cut", "Paste", "Select")) + } @Test fun testTapsCountingWithMultiTouch() = runUIKitInstrumentedTest { @@ -731,98 +753,6 @@ class TextFieldEditMenuTest { .testTag("TextField") .focusRequester(focusRequester) - private fun runEditableCollapsedClipboardTextContextMenuTest( - textFieldKind: EditableTextFieldKind, - newContextMenu: Boolean, - ) = runContextMenuTest(newContextMenu) { - val visibleActions = - if (newContextMenu) { - listOf("Paste", "Select All") - } else { - listOf("Paste", "Select", "Select All") - } - val hiddenActions = - if (newContextMenu) { - listOf("Cut", "Copy", "Select") - } else { - listOf("Cut", "Copy") - } - - verifyEditableCollapsedClipboardTextContextMenu( - textFieldKind = textFieldKind, - visibleActions = visibleActions, - hiddenActions = hiddenActions - ) - } - - private fun runEditableCollapsedClipboardEmptyContextMenuTest( - textFieldKind: EditableTextFieldKind, - newContextMenu: Boolean, - ) = runContextMenuTest(newContextMenu) { - val visibleActions = - if (newContextMenu) { - listOf("Select All") - } else { - listOf("Select", "Select All") - } - val hiddenActions = - if (newContextMenu) { - listOf("Cut", "Copy", "Paste", "Select") - } else { - listOf("Cut", "Copy", "Paste") - } - - verifyEditableCollapsedClipboardEmptyContextMenu( - textFieldKind = textFieldKind, - visibleActions = visibleActions, - hiddenActions = hiddenActions - ) - } - - private fun runEditablePartialSelectionClipboardTextContextMenuTest( - textFieldKind: EditableTextFieldKind, - newContextMenu: Boolean, - ) = runContextMenuTest(newContextMenu) { - verifyEditablePartialSelectionClipboardTextContextMenu( - textFieldKind = textFieldKind, - visibleActions = listOf("Cut", "Copy", "Paste", "Select All"), - hiddenActions = listOf("Select") - ) - } - - private fun runEditableFullSelectionClipboardTextContextMenuTest( - textFieldKind: EditableTextFieldKind, - newContextMenu: Boolean, - ) = runContextMenuTest(newContextMenu) { - verifyEditableFullSelectionClipboardTextContextMenu( - textFieldKind = textFieldKind, - visibleActions = listOf("Cut", "Copy", "Paste"), - hiddenActions = listOf("Select", "Select All") - ) - } - - private fun runReadOnlyCollapsedClipboardTextContextMenuTest( - textFieldKind: EditableTextFieldKind, - newContextMenu: Boolean, - ) = runContextMenuTest(newContextMenu) { - verifyReadOnlyCollapsedClipboardTextContextMenu( - textFieldKind = textFieldKind, - visibleActions = listOf("Select All"), - hiddenActions = listOf("Cut", "Copy", "Paste", "Select") - ) - } - - private fun runReadOnlyPartialSelectionClipboardTextContextMenuTest( - textFieldKind: EditableTextFieldKind, - newContextMenu: Boolean, - ) = runContextMenuTest(newContextMenu) { - verifyReadOnlyPartialSelectionClipboardTextContextMenu( - textFieldKind = textFieldKind, - visibleActions = listOf("Copy", "Select All"), - hiddenActions = listOf("Cut", "Paste", "Select") - ) - } - private fun UIKitInstrumentedTest.longPressAndAwaitContextMenu(textFieldTag: String) { val touch = findNodeWithTag(textFieldTag).touchDown() waitUntil { @@ -832,168 +762,6 @@ class TextFieldEditMenuTest { waitForContextMenu() } - private fun UIKitInstrumentedTest.verifyEditableCollapsedClipboardTextContextMenu( - textFieldKind: EditableTextFieldKind, - visibleActions: List, - hiddenActions: List, - ) { - verifyEditableCollapsedContextMenu( - textFieldKind = textFieldKind, - clipboardText = "Paste text", - visibleActions = visibleActions, - hiddenActions = hiddenActions - ) - } - - private fun UIKitInstrumentedTest.verifyEditableCollapsedClipboardEmptyContextMenu( - textFieldKind: EditableTextFieldKind, - visibleActions: List, - hiddenActions: List, - ) { - verifyEditableCollapsedContextMenu( - textFieldKind = textFieldKind, - clipboardText = null, - visibleActions = visibleActions, - hiddenActions = hiddenActions - ) - } - - private fun UIKitInstrumentedTest.verifyEditableCollapsedContextMenu( - textFieldKind: EditableTextFieldKind, - clipboardText: String?, - visibleActions: List, - hiddenActions: List, - ) { - UIPasteboard.generalPasteboard().string = clipboardText - setTextFieldContent( - textFieldKind = textFieldKind, - initialValue = TextFieldValue("Text", TextRange(4, 4)), - readOnly = false - ) - - longPressAndAwaitContextMenu("TextField") - - verifyContextMenuItemsVisible(visibleActions) - verifyContextMenuItemsHidden(hiddenActions) - } - - private fun UIKitInstrumentedTest.verifyEditablePartialSelectionClipboardTextContextMenu( - textFieldKind: EditableTextFieldKind, - visibleActions: List, - hiddenActions: List, - ) { - UIPasteboard.generalPasteboard().string = "Paste text" - setTextFieldContent( - textFieldKind = textFieldKind, - initialValue = TextFieldValue(PARTIAL_SELECTION_TEXT), - readOnly = false - ) - - openToolbar("TextField") - - verifyContextMenuItemsVisible(visibleActions) - verifyContextMenuItemsHidden(hiddenActions) - } - - private fun UIKitInstrumentedTest.verifyReadOnlyCollapsedClipboardTextContextMenu( - textFieldKind: EditableTextFieldKind, - visibleActions: List, - hiddenActions: List, - ) { - UIPasteboard.generalPasteboard().string = "Paste text" - setTextFieldContent( - textFieldKind = textFieldKind, - initialValue = TextFieldValue("Text", TextRange(4, 4)), - readOnly = true - ) - - longPressAndAwaitContextMenu("TextField") - - verifyContextMenuItemsVisible(visibleActions) - verifyContextMenuItemsHidden(hiddenActions) - } - - private fun UIKitInstrumentedTest.verifyReadOnlyPartialSelectionClipboardTextContextMenu( - textFieldKind: EditableTextFieldKind, - visibleActions: List, - hiddenActions: List, - ) { - UIPasteboard.generalPasteboard().string = "Paste text" - setTextFieldContent( - textFieldKind = textFieldKind, - initialValue = TextFieldValue(PARTIAL_SELECTION_TEXT), - readOnly = true - ) - - openToolbar("TextField") - - verifyContextMenuItemsVisible(visibleActions) - verifyContextMenuItemsHidden(hiddenActions) - } - - private fun UIKitInstrumentedTest.verifyEditableFullSelectionClipboardTextContextMenu( - textFieldKind: EditableTextFieldKind, - visibleActions: List, - hiddenActions: List, - ) { - UIPasteboard.generalPasteboard().string = "Paste text" - when (textFieldKind) { - EditableTextFieldKind.BasicTextField -> { - val textFieldValue = mutableStateOf(TextFieldValue("Text", TextRange(4, 4))) - setContent { - val focusRequester = remember { FocusRequester() } - Column(modifier = Modifier.safeDrawingPadding()) { - BasicTextField( - value = textFieldValue.value, - onValueChange = { textFieldValue.value = it }, - modifier = textFieldModifier(focusRequester) - ) - } - LaunchedEffect(focusRequester) { - focusRequester.requestFocus() - } - } - - longPressAndAwaitContextMenu("TextField") - tapContextMenuButton("Select All") - waitUntil("Text field should be fully selected") { - textFieldValue.value.selection.start == 0 && - textFieldValue.value.selection.end == textFieldValue.value.text.length - } - } - EditableTextFieldKind.BasicTextField2 -> { - val textFieldState = TextFieldState("Text", TextRange(4, 4)) - setContent { - val focusRequester = remember { FocusRequester() } - Column(modifier = Modifier.safeDrawingPadding()) { - BasicTextField( - state = textFieldState, - modifier = textFieldModifier(focusRequester) - ) - } - LaunchedEffect(focusRequester) { - focusRequester.requestFocus() - } - } - - longPressAndAwaitContextMenu("TextField") - tapContextMenuButton("Select All") - waitUntil("Text field should be fully selected") { - textFieldState.selection.start == 0 && - textFieldState.selection.end == textFieldState.text.length - } - } - } - - waitUntil("Context menu should update for full selection") { - visibleActions.all { findNodeWithLabelOrNull(it) != null } && - hiddenActions.all { findNodeWithLabelOrNull(it) == null } - } - - verifyContextMenuItemsVisible(visibleActions) - verifyContextMenuItemsHidden(hiddenActions) - } - private fun UIKitInstrumentedTest.setTextFieldContent( textFieldKind: EditableTextFieldKind, initialValue: TextFieldValue,