Closed powerdude closed 7 months ago
Hi, I've fixed the issue in the ShellContent implementation that causes the automation system to fail to find the button inside the RenderContent callback.
NOTE: Maui shell is somewhat tricky to test. The main problem is that when testing the Dispatcher and the Shell. Current objects aren't available. I'm thinking of a better way to manage it, but in the meaning, you have to grab a reference to the shell and call GotoAsync on that object to actually navigate in a test.
Updating to the latest version 2.0.18 and using code like the following you should be able to test your code:
private MauiControls.Shell _shellRef;
public override VisualNode Render()
=> new Shell(shellRef => _shellRef = shellRef)
{
new FlyoutItem("Page1")
{
new ShellContent()
.RenderContent(() => new ContentPage("Page1"))
.Route("page-1")
}
.AutomationId("FlyoutItem_Page1"),
new FlyoutItem("Page2")
{
new ShellContent()
.RenderContent(() => new ContentPage("Page2")
{
new Button("Goto to Page1")
.HCenter()
.VCenter()
.AutomationId("GotoPage1Button")
.OnClicked(async ()=> await _shellRef.GoToAsync("//page-1"))
})
.Route("page-2")
}
.AutomationId("FlyoutItem_Page2")
}
.AutomationId("MainShell")
.ItemTemplate(RenderItemTemplate);
static VisualNode RenderItemTemplate(MauiControls.BaseShellItem item)
=> new Grid("68", "*")
{
new Label(item.Title)
.VCenter()
.Margin(10,0)
};
var mainPageNode = TemplateHost.Create(new MainPageIssue218());
var shell = mainPageNode.Find<MauiControls.Shell>("MainShell");
var shellItem1 = shell.Find<MauiControls.FlyoutItem>("FlyoutItem_Page1");
var shellItem2 = shell.Find<MauiControls.FlyoutItem>("FlyoutItem_Page2");
shell.CurrentItem.ShouldBe(shellItem1);
shell.CurrentItem = shellItem2;
shell.CurrentItem.ShouldBe(shellItem2);
var gotoPage1Button = mainPageNode.Find<MauiControls.Button>("GotoPage1Button");
gotoPage1Button.SendClicked();
shell.CurrentItem.ShouldBe(shellItem1);
I'm working to add more samples that show how to test components that will be published in the samples repository: https://github.com/adospace/mauireactor-samples/tree/main/Controls/SampleTests
thanks for the update. My sample I posted above wasn't my full use case. I have a FlyoutItem
that actually has multiple ShellContent
in them which is why I placed an AutomationId
on the ShellContent
. So, it would still be helpful to try to test a FlyoutItem
with multiple content in them.
new Shell
{
new FlyoutItem("Page1")
{
new ShellContent()
.RenderContent(() => new ContentPage("Page1a"))
.Route("page-1a"),
new ShellContent()
.RenderContent(() => new ContentPage("Page1b"))
.Route("page-1b"),
}
.AutomationId("FlyoutItem_Page1")
.FlyoutDisplayOptions(FlyoutDisplayOptions.AsMultipleItems),
new ShellContent("Page2")
.RenderContent(() => new ContentPage("Page2"))
.Route("page-2"),
}
added a sample test here: https://github.com/adospace/mauireactor-samples/tree/main/Controls/SampleTests
public override VisualNode Render()
=> Shell(
FlyoutItem(
Tab(
ShellContent("Home")
.Icon("home.png")
.RenderContent(()=> new HomePage())
.AutomationId("home_item"),
ShellContent("Comments")
.Icon("comments.png")
.RenderContent(()=> new CommentsPage())
.AutomationId("comments_item")
)
.Title("Notifications")
.Icon("bell.png")
.AutomationId("tab"),
ShellContent("Database")
.Icon("database.png")
.RenderContent(()=> new DatabasePage())
.AutomationId("database_item"),
ShellContent("Notifications")
.Icon("bell.png")
.RenderContent(()=> new NotificationsPage())
.AutomationId("notifications_item")
)
.AutomationId("flyout_item")
.FlyoutDisplayOptions(MauiControls.FlyoutDisplayOptions.AsMultipleItems),
ShellContent("Settings")
.Icon("gear.png")
.RenderContent(()=> new SettingsPage())
.AutomationId("settings_item")
)
.AutomationId("MainShell");
[Test]
public void TestNavigationMainPage2()
{
var mainPageNode = TemplateHost.Create(new MainPage2());
var shell = mainPageNode.Find<MauiControls.Shell>("MainShell");
var tab = shell.Find<MauiControls.Tab>("tab");
var notifications_item = shell.Find<MauiControls.ShellContent>("notifications_item");
var home_item = shell.Find<MauiControls.ShellContent>("home_item");
var settings_item = shell.Find<MauiControls.ShellContent>("settings_item");
var flyout_item = shell.Find<MauiControls.FlyoutItem>("flyout_item");
var database_item = shell.Find<MauiControls.ShellContent>("database_item");
shell.CurrentItem.ShouldBe(flyout_item);
flyout_item.CurrentItem.ShouldBe(tab);
tab.CurrentItem.ShouldBe(home_item);
//Navigate to database page
flyout_item.CurrentItem = database_item;
flyout_item.CurrentItem.ShouldBe(database_item);
}
Ok, I understand what you've did. The final assertion is testing that CurrentItem
was set, but how would you get a reference to DatabasePage
so that you could click a button or check the value of a label. shell.CurrentPage
is null,
Nevermind, looks like you have to use mainPageNode
which seems a little weird.
This can be closed if your current expectation is that the test should use mainPageNode
to get any child controls that may be on the new page that is created when setting CurrentItem
of the shell.
You can search down from the mainpage node as shown above but also from any other node that is placed below the root in the tree. For example you can use the database_item in the sample above to search for a button that is created inside the database page. The same button is returned searching for example starting from flyout_item as well given that flyout_item contains the database_item.
I'm building some more examples and so far what I described is working using the latest version of MauiReactor.
I will close this ticket in a few days when I'll be confident of the resolution of the issue you found.
Btw thanks for having reported it!
The Find
extension method that takes a TimeSpan
is only available for ITemplateHost
. Can one be added for IElementController
?
Describe the bug Ive created a unit test for a ShellPage and want to
Tap
on the shell content so that I can test that it shows another page. There doesn't appear to be aSendClicked
, or something similar onShellContent
to trigger the navigation.To Reproduce
Expected behavior a way to trigger the click on the shell content and a way to check the page that was navigated to.