Skip to content

Commit

Permalink
Move keyboard device tests to appium (#20670)
Browse files Browse the repository at this point in the history
  • Loading branch information
PureWeen authored Feb 19, 2024
1 parent 89c2646 commit db94a9b
Show file tree
Hide file tree
Showing 4 changed files with 173 additions and 89 deletions.
95 changes: 95 additions & 0 deletions src/Controls/samples/Controls.Sample.UITests/Issues/Issue5724.cs
Original file line number Diff line number Diff line change
@@ -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;
}
}
}
57 changes: 57 additions & 0 deletions src/Controls/tests/UITests/Tests/Issues/Issue5724.cs
Original file line number Diff line number Diff line change
@@ -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());
}
}
}
89 changes: 0 additions & 89 deletions src/Core/tests/DeviceTests/Handlers/Entry/EntryHandlerTests.cs
Original file line number Diff line number Diff line change
Expand Up @@ -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<VerticalStackLayoutStub, LayoutHandler>();
handler.AddHandler<EntryStub, EntryHandler>();
});
});

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<LayoutHandler>(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<VerticalStackLayoutStub, LayoutHandler>();
handler.AddHandler<EntryStub, EntryHandler>();
});
});

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<LayoutHandler>(layout);
await handler.PlatformView.AttachAndRun(async () =>
{
await entry1.SendKeyboardReturnType(ReturnType.Done);
await entry1.WaitForKeyboardToHide();
});
});
}
#endif

[Category(TestCategory.Entry)]
public class EntryTextStyleTests : TextStyleHandlerTests<EntryHandler, EntryStub>
{
Expand Down
21 changes: 21 additions & 0 deletions src/TestUtils/src/UITest.Appium/HelperExtensions.cs
Original file line number Diff line number Diff line change
Expand Up @@ -541,6 +541,27 @@ public static void Back(this IApp app)
app.CommandExecutor.Execute("back", ImmutableDictionary<string, object>.Empty);
}


/// <summary>
/// Check if element has focused
/// </summary>
/// <param name="app">Represents the main gateway to interact with an app.</param>
/// <param name="id">Target element</param>
/// <returns>Returns <see langword="true"/> if focused</returns>
/// <exception cref="InvalidOperationException"></exception>
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<IUIElement> query,
Func<IUIElement, bool> satisfactory,
string? timeoutMessage = null,
Expand Down

0 comments on commit db94a9b

Please sign in to comment.