From e905502a213063356071e5af164545922b4bd14d Mon Sep 17 00:00:00 2001 From: BagavathiPerumal Date: Wed, 15 Apr 2026 20:10:09 +0530 Subject: [PATCH 1/2] fix-34917: Made code changes to fix the SwipeView.Open() ArgumentException on the second programmatic call for RightItems/BottomItems on iOS/Mac Catalyst. --- .../TestCases.HostApp/Issues/Issue34917.cs | 117 ++++++++++++++++++ .../Tests/Issues/Issue34917.cs | 51 ++++++++ src/Core/src/Platform/iOS/MauiSwipeView.cs | 3 +- 3 files changed, 169 insertions(+), 2 deletions(-) create mode 100644 src/Controls/tests/TestCases.HostApp/Issues/Issue34917.cs create mode 100644 src/Controls/tests/TestCases.Shared.Tests/Tests/Issues/Issue34917.cs diff --git a/src/Controls/tests/TestCases.HostApp/Issues/Issue34917.cs b/src/Controls/tests/TestCases.HostApp/Issues/Issue34917.cs new file mode 100644 index 000000000000..e96dad78a3aa --- /dev/null +++ b/src/Controls/tests/TestCases.HostApp/Issues/Issue34917.cs @@ -0,0 +1,117 @@ +namespace Maui.Controls.Sample.Issues; + +[Issue(IssueTracker.Github, 34917, "[net 11.0][iOS,MacCatalyst] SwipeView.Open() throws ArgumentException on second programmatic call", PlatformAffected.iOS | PlatformAffected.macOS)] +public class Issue34917 : ContentPage +{ + const string OpenRightButtonId = "OpenSwipeButton"; + const string OpenBottomButtonId = "OpenBottomSwipeButton"; + const string CloseButtonId = "CloseSwipeButton"; + const string StatusLabelId = "StatusLabel"; + + readonly SwipeView _swipeView; + + public Issue34917() + { + var openRightButton = new Button + { + Text = "Open RightItems", + AutomationId = OpenRightButtonId + }; + + var openBottomButton = new Button + { + Text = "Open BottomItems", + AutomationId = OpenBottomButtonId + }; + + var closeButton = new Button + { + Text = "Close SwipeView", + AutomationId = CloseButtonId + }; + + var statusLabel = new Label + { + Text = "Ready", + AutomationId = StatusLabelId, + HorizontalOptions = LayoutOptions.Center + }; + + var rightSwipeItem = new SwipeItem + { + Text = "Right Action", + BackgroundColor = Colors.LightBlue + }; + + var bottomSwipeItem = new SwipeItem + { + Text = "Bottom Action", + BackgroundColor = Colors.LightGreen + }; + + _swipeView = new SwipeView + { + HeightRequest = 60, + RightItems = new SwipeItems { rightSwipeItem }, + BottomItems = new SwipeItems { bottomSwipeItem }, + Content = new Grid + { + BackgroundColor = Colors.LightGray, + Children = + { + new Label + { + Text = "Swipe content", + HorizontalOptions = LayoutOptions.Center, + VerticalOptions = LayoutOptions.Center + } + } + } + }; + + openRightButton.Clicked += (s, e) => + { + try + { + _swipeView.Open(OpenSwipeItem.RightItems); + statusLabel.Text = "Success"; + } + catch (Exception ex) + { + statusLabel.Text = $"Error: {ex.GetType().Name}"; + } + }; + + openBottomButton.Clicked += (s, e) => + { + try + { + _swipeView.Open(OpenSwipeItem.BottomItems); + statusLabel.Text = "Success"; + } + catch (Exception ex) + { + statusLabel.Text = $"Error: {ex.GetType().Name}"; + } + }; + + closeButton.Clicked += (s, e) => + { + _swipeView.Close(); + }; + + Content = new VerticalStackLayout + { + Spacing = 12, + Padding = new Thickness(20), + Children = + { + openRightButton, + openBottomButton, + closeButton, + _swipeView, + statusLabel + } + }; + } +} diff --git a/src/Controls/tests/TestCases.Shared.Tests/Tests/Issues/Issue34917.cs b/src/Controls/tests/TestCases.Shared.Tests/Tests/Issues/Issue34917.cs new file mode 100644 index 000000000000..5779238432f9 --- /dev/null +++ b/src/Controls/tests/TestCases.Shared.Tests/Tests/Issues/Issue34917.cs @@ -0,0 +1,51 @@ +using NUnit.Framework; +using UITest.Appium; +using UITest.Core; + +namespace Microsoft.Maui.TestCases.Tests.Issues; + +public class Issue34917 : _IssuesUITest +{ + public Issue34917(TestDevice device) : base(device) { } + + public override string Issue => "[net 11.0][iOS,MacCatalyst] SwipeView.Open() throws ArgumentException on second programmatic call"; + + [Test] + [Category(UITestCategories.SwipeView)] + public void SwipeViewOpenRightDoesNotThrowOnSecondCall() + { + App.WaitForElement(OpenRightButtonId); + + App.Tap(OpenRightButtonId); + App.WaitForElement(StatusLabelId); + Assert.That(App.FindElement(StatusLabelId).GetText(), Is.EqualTo("Success"), + "First Open(RightItems) call should succeed."); + + App.Tap(OpenRightButtonId); + Assert.That(App.FindElement(StatusLabelId).GetText(), Is.EqualTo("Success"), + "Second consecutive Open(RightItems) call should not throw an exception."); + } + + [Test] + [Category(UITestCategories.SwipeView)] + public void SwipeViewOpenBottomDoesNotThrowOnSecondCall() + { + App.WaitForElement(OpenBottomButtonId); + + App.Tap(CloseButtonId); + + App.Tap(OpenBottomButtonId); + App.WaitForElement(StatusLabelId); + Assert.That(App.FindElement(StatusLabelId).GetText(), Is.EqualTo("Success"), + "First Open(BottomItems) call should succeed."); + + App.Tap(OpenBottomButtonId); + Assert.That(App.FindElement(StatusLabelId).GetText(), Is.EqualTo("Success"), + "Second consecutive Open(BottomItems) call should not throw an exception."); + } + + const string OpenRightButtonId = "OpenSwipeButton"; + const string OpenBottomButtonId = "OpenBottomSwipeButton"; + const string CloseButtonId = "CloseSwipeButton"; + const string StatusLabelId = "StatusLabel"; +} diff --git a/src/Core/src/Platform/iOS/MauiSwipeView.cs b/src/Core/src/Platform/iOS/MauiSwipeView.cs index b7f316953625..8eb53ed2e59d 100644 --- a/src/Core/src/Platform/iOS/MauiSwipeView.cs +++ b/src/Core/src/Platform/iOS/MauiSwipeView.cs @@ -295,6 +295,7 @@ void UpdateSwipeItems() return; _swipeItemsRect = new List(); + _swipeItems.Clear(); double swipeItemsWidth; @@ -1165,8 +1166,6 @@ internal void ProgrammaticallyOpenSwipeItem(OpenSwipeItem openSwipeItem, bool an } Swipe(animated); - - _swipeOffset = Math.Abs(_swipeOffset); } void UpdateOffset(double swipeOffset) From 6eefdf6b67dc7b570f5f1a0017ce7c4eb84f5939 Mon Sep 17 00:00:00 2001 From: BagavathiPerumal Date: Thu, 16 Apr 2026 12:54:49 +0530 Subject: [PATCH 2/2] fix-34917-Test script updated. --- .../tests/TestCases.Shared.Tests/Tests/Issues/Issue34917.cs | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/src/Controls/tests/TestCases.Shared.Tests/Tests/Issues/Issue34917.cs b/src/Controls/tests/TestCases.Shared.Tests/Tests/Issues/Issue34917.cs index 5779238432f9..7a9633b29add 100644 --- a/src/Controls/tests/TestCases.Shared.Tests/Tests/Issues/Issue34917.cs +++ b/src/Controls/tests/TestCases.Shared.Tests/Tests/Issues/Issue34917.cs @@ -18,10 +18,12 @@ public void SwipeViewOpenRightDoesNotThrowOnSecondCall() App.Tap(OpenRightButtonId); App.WaitForElement(StatusLabelId); + App.WaitForTextToBePresentInElement(StatusLabelId, "Success"); Assert.That(App.FindElement(StatusLabelId).GetText(), Is.EqualTo("Success"), "First Open(RightItems) call should succeed."); App.Tap(OpenRightButtonId); + App.WaitForTextToBePresentInElement(StatusLabelId, "Success"); Assert.That(App.FindElement(StatusLabelId).GetText(), Is.EqualTo("Success"), "Second consecutive Open(RightItems) call should not throw an exception."); } @@ -31,15 +33,18 @@ public void SwipeViewOpenRightDoesNotThrowOnSecondCall() public void SwipeViewOpenBottomDoesNotThrowOnSecondCall() { App.WaitForElement(OpenBottomButtonId); + App.WaitForElement(CloseButtonId); App.Tap(CloseButtonId); App.Tap(OpenBottomButtonId); App.WaitForElement(StatusLabelId); + App.WaitForTextToBePresentInElement(StatusLabelId, "Success"); Assert.That(App.FindElement(StatusLabelId).GetText(), Is.EqualTo("Success"), "First Open(BottomItems) call should succeed."); App.Tap(OpenBottomButtonId); + App.WaitForTextToBePresentInElement(StatusLabelId, "Success"); Assert.That(App.FindElement(StatusLabelId).GetText(), Is.EqualTo("Success"), "Second consecutive Open(BottomItems) call should not throw an exception."); }