Skip to content

Commit

Permalink
Squashed commit of the following: (#19629)
Browse files Browse the repository at this point in the history
commit f6c3bfa
Merge: d0b3f84 3143629
Author: Matthew Leibowitz <mattleibow@live.com>
Date:   Mon Jun 17 19:58:40 2024 +0800

    Merge remote-tracking branch 'origin/main' into dev/macos-actionsheet

commit d0b3f84
Author: Matthew Leibowitz <mattleibow@live.com>
Date:   Tue Jun 11 05:00:38 2024 +0800

    Fix the older macOS testing

commit 3dc6b4d
Author: Matthew Leibowitz <mattleibow@live.com>
Date:   Mon Jun 10 23:40:40 2024 +0800

    macOS 13 things

commit e3e48e4
Author: Matthew Leibowitz <mattleibow@live.com>
Date:   Sat Jun 8 02:15:55 2024 +0800

    docs

commit 693d79c
Merge: 3dbce49 a3c872d
Author: Matthew Leibowitz <mattleibow@live.com>
Date:   Sat Jun 8 02:08:31 2024 +0800

    Merge remote-tracking branch 'origin/main' into dev/macos-actionsheet

commit 3dbce49
Merge: 17ea9c6 93a1bc4
Author: Matthew Leibowitz <mattleibow@live.com>
Date:   Sat Jun 8 02:06:16 2024 +0800

    Merge remote-tracking branch 'origin/main' into dev/macos-actionsheet

commit 17ea9c6
Author: Matthew Leibowitz <mattleibow@live.com>
Date:   Sat Jun 8 02:05:42 2024 +0800

    Fix the tests

commit 026da41
Author: Matthew Leibowitz <mattleibow@live.com>
Date:   Fri Jun 7 03:56:26 2024 +0800

    fixes

commit d2b85d5
Author: Matthew Leibowitz <mattleibow@live.com>
Date:   Thu Jun 6 23:58:33 2024 +0800

    namespaces

commit 9fa77cd
Merge: 3f9596b 9d71d32
Author: Matthew Leibowitz <mattleibow@live.com>
Date:   Thu Jun 6 23:57:00 2024 +0800

    Merge branch 'main' into dev/macos-actionsheet

    # Conflicts:
    #	src/Controls/samples/Controls.Sample.UITests/Test.cs
    #	src/Controls/src/Core/Platform/AlertManager/AlertManager.iOS.cs
    #	src/Controls/tests/TestCases.Shared.Tests/Tests/Concepts/AlertsGalleryTests.cs
    #	src/Controls/tests/TestCases/Concepts/AlertsGalleryPage.cs
    #	src/TestUtils/src/UITest.Appium/AppiumCatalystApp.cs
    #	src/TestUtils/src/UITest.Appium/HelperExtensions.cs

commit 3f9596b
Author: Matthew Leibowitz <mattleibow@live.com>
Date:   Sat Dec 30 09:29:31 2023 +0200

    Add some UI tests

    Done: iOS/macOS/Android. TODO: Windows

commit 68c930f
Author: Matthew Leibowitz <mattleibow@live.com>
Date:   Tue Dec 19 18:15:51 2023 +0200

    macOS does not use PopoverPresentationController

    Fixes #18156
  • Loading branch information
mattleibow authored Jun 20, 2024
1 parent b368e8b commit a984765
Show file tree
Hide file tree
Showing 16 changed files with 632 additions and 8 deletions.
2 changes: 1 addition & 1 deletion src/Controls/src/Core/Page/Page.cs
Original file line number Diff line number Diff line change
Expand Up @@ -282,7 +282,7 @@ public Task<string> DisplayActionSheet(string title, string cancel, string destr
/// Displays a platform action sheet, allowing the application user to choose from several buttons.
/// </summary>
/// <param name="title">Title of the displayed action sheet. Can be <see langword="null"/> to hide the title.</param>
/// <param name="cancel">Text to be displayed in the 'Cancel' button. Can be null to hide the <see langword="null"/> action.</param>
/// <param name="cancel">Text to be displayed in the 'Cancel' button. Can be null to hide the cancel action.</param>
/// <param name="destruction">Text to be displayed in the 'Destruct' button. Can be <see langword="null"/> to hide the destructive option.</param>
/// <param name="flowDirection">The flow direction to be used by the action sheet.</param>
/// <param name="buttons">Text labels for additional buttons.</param>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -187,12 +187,15 @@ static void PresentPopUp(Page sender, Window virtualView, UIWindow platformView,
presentingWindow = senderPageWindow;
}

if (UIDevice.CurrentDevice.UserInterfaceIdiom == UIUserInterfaceIdiom.Pad && arguments != null)
if (UIDevice.CurrentDevice.UserInterfaceIdiom == UIUserInterfaceIdiom.Pad &&
arguments is not null &&
alert.PopoverPresentationController is not null &&
platformView.RootViewController?.View is not null)
{
var topViewController = GetTopUIViewController(presentingWindow);
UIDevice.CurrentDevice.BeginGeneratingDeviceOrientationNotifications();
var observer = NSNotificationCenter.DefaultCenter.AddObserver(UIDevice.OrientationDidChangeNotification,
n => { alert.PopoverPresentationController.SourceRect = topViewController.View.Bounds; });
n => alert.PopoverPresentationController.SourceRect = topViewController.View.Bounds);

arguments.Result.Task.ContinueWith(t =>
{
Expand All @@ -216,7 +219,7 @@ static void PresentPopUp(Page sender, Window virtualView, UIWindow platformView,
static UIViewController GetTopUIViewController(UIWindow platformWindow)
{
var topUIViewController = platformWindow.RootViewController;
while (topUIViewController.PresentedViewController is not null)
while (topUIViewController?.PresentedViewController is not null)
{
topUIViewController = topUIViewController.PresentedViewController;
}
Expand Down
10 changes: 10 additions & 0 deletions src/Controls/tests/CustomAttributes/Test.cs
Original file line number Diff line number Diff line change
Expand Up @@ -744,6 +744,16 @@ public enum InputTransparency
CascadeTransLayoutOverlayWithButton,
}

public enum Alerts
{
AlertCancel,
AlertAcceptCancelClickAccept,
AlertAcceptCancelClickCancel,
ActionSheetClickItem,
ActionSheetClickCancel,
ActionSheetClickDestroy,
}

public static class InputTransparencyMatrix
{
// this is both for color diff and cols
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,149 @@
using NUnit.Framework;
using NUnit.Framework.Legacy;
using UITest.Appium;
using UITest.Core;

namespace Microsoft.Maui.TestCases.Tests
{
public class AlertsGalleryTests : CoreGalleryBasePageTest
{
public AlertsGalleryTests(TestDevice device)
: base(device)
{
}

protected override void NavigateToGallery()
{
App.NavigateToGallery("Alerts Gallery");
}

// TODO: UI testing alert code is not yet implemented on Windows.
#if !WINDOWS
[Test]
public void AlertCancel()
{
var test = Test.Alerts.AlertCancel;

var remote = new EventViewContainerRemote(UITestContext, test);
remote.GoTo(test.ToString());

var textBeforeClick = remote.GetEventLabel().GetText();
ClassicAssert.AreEqual($"Event: {test} (none)", textBeforeClick);

remote.TapView();

var alert = App.WaitForElement(() => App.GetAlert());
ClassicAssert.NotNull(alert);

var alertText = alert.GetAlertText();
CollectionAssert.Contains(alertText, "Alert Title Here");
CollectionAssert.Contains(alertText, "Alert Message Here");

var buttons = alert.GetAlertButtons();
CollectionAssert.IsNotEmpty(buttons);
ClassicAssert.True(buttons.Count == 1, $"Expected 1 buttonText, found {buttons.Count}.");

var cancel = buttons.First();
ClassicAssert.AreEqual("CANCEL", cancel.GetText());

cancel.Click();

App.WaitForNoElement(() => App.GetAlert());

var textAfterClick = remote.GetEventLabel().GetText();
ClassicAssert.AreEqual($"Event: {test} (SUCCESS 1)", textAfterClick);
}

[Test]
[TestCase(Test.Alerts.AlertAcceptCancelClickAccept, "ACCEPT")]
[TestCase(Test.Alerts.AlertAcceptCancelClickCancel, "CANCEL")]
public void AlertAcceptCancel(Test.Alerts test, string buttonText)
{
var remote = new EventViewContainerRemote(UITestContext, test);
remote.GoTo(test.ToString());

var textBeforeClick = remote.GetEventLabel().GetText();
ClassicAssert.AreEqual($"Event: {test} (none)", textBeforeClick);

remote.TapView();

var alert = App.WaitForElement(() => App.GetAlert());
ClassicAssert.NotNull(alert);

var alertText = alert.GetAlertText();
CollectionAssert.Contains(alertText, "Alert Title Here");
CollectionAssert.Contains(alertText, "Alert Message Here");

var buttons = alert.GetAlertButtons()
.Select(b => (Element: b, Text: b.GetText()))
.ToList();
CollectionAssert.IsNotEmpty(buttons);
ClassicAssert.True(buttons.Count == 2, $"Expected 2 buttons, found {buttons.Count}.");
CollectionAssert.Contains(buttons.Select(b => b.Text), "ACCEPT");
CollectionAssert.Contains(buttons.Select(b => b.Text), "CANCEL");

var button = buttons.Single(b => b.Text == buttonText);
button.Element.Click();

App.WaitForNoElement(() => App.GetAlert());

var textAfterClick = remote.GetEventLabel().GetText();
ClassicAssert.AreEqual($"Event: {test} (SUCCESS 1)", textAfterClick);
}

[Test]
[TestCase(Test.Alerts.ActionSheetClickItem, "ITEM 2")]
[TestCase(Test.Alerts.ActionSheetClickCancel, "CANCEL")]
[TestCase(Test.Alerts.ActionSheetClickDestroy, "DESTROY")]
public void ActionSheetClickItem(Test.Alerts test, string itemText)
{
var remote = new EventViewContainerRemote(UITestContext, test);
remote.GoTo(test.ToString());

var textBeforeClick = remote.GetEventLabel().GetText();
ClassicAssert.AreEqual($"Event: {test} (none)", textBeforeClick);

remote.TapView();

var alert = App.WaitForElement(() => App.GetAlert());
ClassicAssert.NotNull(alert);

var alertText = alert.GetAlertText();
CollectionAssert.Contains(alertText, "Action Sheet Title Here");

var buttons = alert.GetAlertButtons()
.Select(b => (Element: b, Text: b.GetText()))
.ToList();
CollectionAssert.IsNotEmpty(buttons);
ClassicAssert.True(buttons.Count >= 4 && buttons.Count <= 5, $"Expected 4 or 5 buttons, found {buttons.Count}.");
CollectionAssert.Contains(buttons.Select(b => b.Text), "DESTROY");
CollectionAssert.Contains(buttons.Select(b => b.Text), "ITEM 1");
CollectionAssert.Contains(buttons.Select(b => b.Text), "ITEM 2");
CollectionAssert.Contains(buttons.Select(b => b.Text), "ITEM 3");

// handle the case where the dismiss button is an actual button
if (buttons.Count == 5)
CollectionAssert.Contains(buttons.Select(b => b.Text), "CANCEL");

if (buttons.Count == 4 && itemText == "CANCEL")
{
// handle the case where the dismiss button is a "click outside the popup"

alert.DismissAlert();
}
else
{
// handle the case where the dismiss button is an actual button

var button = buttons.Single(b => b.Text == itemText);
button.Element.Click();
}

App.WaitForNoElement(() => App.GetAlert());

var textAfterClick = remote.GetEventLabel().GetText();
ClassicAssert.AreEqual($"Event: {test} (SUCCESS 1)", textAfterClick);
}
#endif
}
}
96 changes: 96 additions & 0 deletions src/Controls/tests/TestCases/Concepts/AlertsGalleryPage.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,96 @@
using System;
using System.Threading.Tasks;
using Microsoft.Maui.Controls;

namespace Maui.Controls.Sample
{
internal class AlertsGalleryPage : CoreGalleryBasePage
{
protected override void Build()
{
// ALERTS

// Test with a single button alert that can be dismissed by tapping the button
Add(Test.Alerts.AlertCancel, async t =>
{
await DisplayAlert(
"Alert Title Here",
"Alert Message Here",
"CANCEL");
t.ReportSuccessEvent();
});

// Test alert with options to Accept or Cancel, Accept is the correct option
Add(Test.Alerts.AlertAcceptCancelClickAccept, async t =>
{
var result = await DisplayAlert(
"Alert Title Here",
"Alert Message Here",
"ACCEPT", "CANCEL");
if (result)
t.ReportSuccessEvent();
else
t.ReportFailEvent();
});

// Test alert with options to Accept or Cancel, Cancel is the correct option
Add(Test.Alerts.AlertAcceptCancelClickCancel, async t =>
{
var result = await DisplayAlert(
"Alert Title Here",
"Alert Message Here",
"ACCEPT", "CANCEL");
if (result)
t.ReportFailEvent();
else
t.ReportSuccessEvent();
});

// ACTION SHEETS

// Test action sheet with items and Cancel, Item 2 is the correct option
Add(Test.Alerts.ActionSheetClickItem, async t =>
{
var result = await DisplayActionSheet(
"Action Sheet Title Here",
"CANCEL", "DESTROY",
"ITEM 1", "ITEM 2", "ITEM 3");
if (result == "ITEM 2")
t.ReportSuccessEvent();
else
t.ReportFailEvent();
});

// Test action sheet with items and Cancel, Cancel is the correct option
Add(Test.Alerts.ActionSheetClickCancel, async t =>
{
var result = await DisplayActionSheet(
"Action Sheet Title Here",
"CANCEL", "DESTROY",
"ITEM 1", "ITEM 2", "ITEM 3");
if (result == "CANCEL")
t.ReportSuccessEvent();
else
t.ReportFailEvent();
});

// Test action sheet with items and Cancel, Destroy is the correct option
Add(Test.Alerts.ActionSheetClickDestroy, async t =>
{
var result = await DisplayActionSheet(
"Action Sheet Title Here",
"CANCEL", "DESTROY",
"ITEM 1", "ITEM 2", "ITEM 3");
if (result == "DESTROY")
t.ReportSuccessEvent();
else
t.ReportFailEvent();
});
}

ExpectedEventViewContainer<Button>
Add(Test.Alerts test, Func<ExpectedEventViewContainer<Button>, Task> action) =>
Add(new ExpectedEventViewContainer<Button>(test, new Button { Text = "Click Me!" }))
.With(t => t.View.Clicked += (_, _) => action(t));
}
}
1 change: 1 addition & 0 deletions src/Controls/tests/TestCases/CoreViews/CorePageView.cs
Original file line number Diff line number Diff line change
Expand Up @@ -51,6 +51,7 @@ public override string ToString()
new GalleryPageFactory(() => new GestureRecognizerGallery(), "Gesture Recognizer Gallery"),
new GalleryPageFactory(() => new InputTransparencyGalleryPage(), "Input Transparency Gallery"),
new GalleryPageFactory(() => new ImageLoadingGalleryPage(), "Image Loading Gallery"),
new GalleryPageFactory(() => new AlertsGalleryPage(), "Alerts Gallery"),
// Elements
new GalleryPageFactory(() => new ActivityIndicatorCoreGalleryPage(), "ActivityIndicator Gallery"),
new GalleryPageFactory(() => new BoxViewCoreGalleryPage(), "Box Gallery"),
Expand Down
Loading

0 comments on commit a984765

Please sign in to comment.