diff --git a/src/Controls/samples/Controls.Sample.UITests/Issues/Issue5724.cs b/src/Controls/samples/Controls.Sample.UITests/Issues/Issue5724.cs new file mode 100644 index 000000000000..a7ef6fb313cd --- /dev/null +++ b/src/Controls/samples/Controls.Sample.UITests/Issues/Issue5724.cs @@ -0,0 +1,95 @@ +using System.Threading; +using Microsoft.Maui; +using Microsoft.Maui.Controls; +using Microsoft.Maui.Platform; + +namespace Maui.Controls.Sample.Issues +{ + [Issue(IssueTracker.Github, 5724, "Next Moves To Next Entry and Done Closes Input View", PlatformAffected.Android)] + public class Issue5724 : TestContentPage + { + protected override void Init() + { + var layout = new VerticalStackLayout(); + + var entry1 = new Entry + { + Text = "Entry 1", + ReturnType = ReturnType.Next, + AutomationId = "Entry1" + }; + + entry1.Focused += async (_, _) => + { + // Make sure keyboard opens + await entry1.ShowSoftInputAsync(CancellationToken.None); + }; + + var entry2 = new Entry + { + Text = "Entry 2", + ReturnType = ReturnType.Next, + AutomationId = "Entry2" + }; + + layout.Add(entry1); + layout.Add(entry2); + + var entry3 = new Entry() + { + Text = "Entry Done", + ReturnType = ReturnType.Done, + AutomationId = "EntryDone" + }; + + entry3.Focused += async (_, _) => + { + // Make sure keyboard opens + await entry3.ShowSoftInputAsync(CancellationToken.None); + }; + + layout.Add(entry3); + + layout.Add(new Entry() + { + Text = "Entry Done", + ReturnType = ReturnType.Done, + AutomationId = "EntryDone2" + }); + + layout.Add(new Button() + { + Text = "Send Next Button", + AutomationId = "SendNext", + Command = new Command(() => + { +#if ANDROID + Handler.MauiContext.Context + .GetActivity() + .CurrentFocus + ?.OnCreateInputConnection(new Android.Views.InputMethods.EditorInfo()) + ?.PerformEditorAction(Android.Views.InputMethods.ImeAction.Next); +#endif + }) + }); + + layout.Add(new Button() + { + Text = "Send Done Button", + AutomationId = "SendDone", + Command = new Command(() => + { +#if ANDROID + Handler.MauiContext.Context + .GetActivity() + .CurrentFocus + ?.OnCreateInputConnection(new Android.Views.InputMethods.EditorInfo()) + ?.PerformEditorAction(Android.Views.InputMethods.ImeAction.Done); +#endif + }) + }); + + Content = layout; + } + } +} diff --git a/src/Controls/tests/UITests/Tests/Issues/Issue5724.cs b/src/Controls/tests/UITests/Tests/Issues/Issue5724.cs new file mode 100644 index 000000000000..4705168bed63 --- /dev/null +++ b/src/Controls/tests/UITests/Tests/Issues/Issue5724.cs @@ -0,0 +1,57 @@ +using NUnit.Framework; +using OpenQA.Selenium.Appium.Android; +using UITest.Appium; +using UITest.Core; + +namespace Microsoft.Maui.AppiumTests.Issues +{ + public class Issue5724 : _IssuesUITest + { + public Issue5724(TestDevice device) : base(device) + { + } + + public override string Issue => "Next Moves To Next Entry and Done Closes Input View"; + + [Test] + public async Task TappingNextMovesToNextElement() + { + this.IgnoreIfPlatforms(new[] + { + TestDevice.Mac, + TestDevice.iOS, + TestDevice.Windows, + }, "Send Keys only works on Android which is why we are ignoring these other platforms"); + + App.WaitForElement("Entry1"); + App.Click("Entry1"); + + await Task.Yield(); + + App.Click("SendNext"); + await Task.Yield(); + + Assert.True(App.IsFocused("Entry2")); + } + + [Test] + public async Task TappingDoneClosesKeyboard() + { + this.IgnoreIfPlatforms(new[] + { + TestDevice.Mac, + TestDevice.iOS, + TestDevice.Windows, + }, "Send Keys only works on Android which is why we are ignoring these other platforms"); + + App.WaitForElement("EntryDone"); + App.Click("EntryDone"); + + await Task.Yield(); + Assert.True(App.IsKeyboardShown()); + App.Click("SendDone"); + await Task.Yield(); + Assert.False(App.IsKeyboardShown()); + } + } +} diff --git a/src/Core/tests/DeviceTests/Handlers/Entry/EntryHandlerTests.cs b/src/Core/tests/DeviceTests/Handlers/Entry/EntryHandlerTests.cs index 0385fed0a0c9..dd6324880389 100644 --- a/src/Core/tests/DeviceTests/Handlers/Entry/EntryHandlerTests.cs +++ b/src/Core/tests/DeviceTests/Handlers/Entry/EntryHandlerTests.cs @@ -675,95 +675,6 @@ public async Task VerticalTextAlignmentInitializesCorrectly(TextAlignment textAl Assert.Equal(platformAlignment, values.PlatformViewValue); } -#if ANDROID - [Fact] - public async Task NextMovesToNextEntrySuccessfully() - { - EnsureHandlerCreated(builder => - { - builder.ConfigureMauiHandlers(handler => - { - handler.AddHandler(); - handler.AddHandler(); - }); - }); - - var layout = new VerticalStackLayoutStub(); - - var entry1 = new EntryStub - { - Text = "Entry 1", - ReturnType = ReturnType.Next - }; - - var entry2 = new EntryStub - { - Text = "Entry 2", - ReturnType = ReturnType.Next - }; - - layout.Add(entry1); - layout.Add(entry2); - - layout.Width = 100; - layout.Height = 150; - - await InvokeOnMainThreadAsync(async () => - { - var contentViewHandler = CreateHandler(layout); - await contentViewHandler.PlatformView.AttachAndRun(async () => - { - await entry1.SendKeyboardReturnType(ReturnType.Next); - await entry2.WaitForFocused(); - Assert.True(entry2.IsFocused); - }); - }); - } - - [Fact(Skip = "https://github.com/dotnet/maui/issues/20533")] - public async Task DoneClosesKeyboard() - { - EnsureHandlerCreated(builder => - { - builder.ConfigureMauiHandlers(handler => - { - handler.AddHandler(); - handler.AddHandler(); - }); - }); - - var layout = new VerticalStackLayoutStub(); - - var entry1 = new EntryStub - { - Text = "Entry 1", - ReturnType = ReturnType.Done - }; - - var entry2 = new EntryStub - { - Text = "Entry 2", - ReturnType = ReturnType.Done - }; - - layout.Add(entry1); - layout.Add(entry2); - - layout.Width = 100; - layout.Height = 150; - - await InvokeOnMainThreadAsync(async () => - { - var handler = CreateHandler(layout); - await handler.PlatformView.AttachAndRun(async () => - { - await entry1.SendKeyboardReturnType(ReturnType.Done); - await entry1.WaitForKeyboardToHide(); - }); - }); - } -#endif - [Category(TestCategory.Entry)] public class EntryTextStyleTests : TextStyleHandlerTests { diff --git a/src/TestUtils/src/UITest.Appium/HelperExtensions.cs b/src/TestUtils/src/UITest.Appium/HelperExtensions.cs index a274bfadcdc8..f195477c1a94 100644 --- a/src/TestUtils/src/UITest.Appium/HelperExtensions.cs +++ b/src/TestUtils/src/UITest.Appium/HelperExtensions.cs @@ -541,6 +541,27 @@ public static void Back(this IApp app) app.CommandExecutor.Execute("back", ImmutableDictionary.Empty); } + + /// + /// Check if element has focused + /// + /// Represents the main gateway to interact with an app. + /// Target element + /// Returns if focused + /// + public static bool IsFocused(this IApp app, string id) + { + if (app is not AppiumApp aaa) + { + throw new InvalidOperationException($"IsFocused is only supported on AppiumApp"); + } + + var activeElement = aaa.Driver.SwitchTo().ActiveElement(); + var element = (AppiumDriverElement)app.WaitForElement(id); + + return element.AppiumElement.Equals(activeElement); + } + static IUIElement Wait(Func query, Func satisfactory, string? timeoutMessage = null,