Skip to content

Commit

Permalink
[Testing] Add UITest Stepper actions (#25130)
Browse files Browse the repository at this point in the history
* Added Stepper UITests

* Added iOS version

* Updated Stepper UITests

* Fix build error

* More changes in the iOS impl

* Added support to Windows

* More changes in the Windows impl

* More changes

* More changes

* Changes to avoid not find MauiStepper container from Appium

* More changes

* More fixes
  • Loading branch information
jsuarezruiz authored Oct 14, 2024
1 parent fc5c375 commit 24c6cd4
Show file tree
Hide file tree
Showing 10 changed files with 394 additions and 14 deletions.
Original file line number Diff line number Diff line change
@@ -1,18 +1,31 @@
using Microsoft.Maui.Controls;

namespace Maui.Controls.Sample;

internal class StepperCoreGalleryPage : CoreGalleryPage<Stepper>
internal class StepperCoreGalleryPage : ContentPage
{
protected override bool SupportsFocus => false;
protected override bool SupportsTapGestureRecognizer => false;

protected override void InitializeElement(Stepper element)
public StepperCoreGalleryPage()
{
}
var layout = new StackLayout
{
Padding = new Thickness(12)
};

protected override void Build()
{
base.Build();
// Default
var defaultLabel = new Label { AutomationId = "DefaultLabel", Text = "Default" };
var defaultStepper = new Stepper { AutomationId = "DefaultStepper" };
var defaultLabelValue = new Label
{
AutomationId = "DefaultLabelValue",
Text = defaultStepper.Value.ToString()
};
layout.Add(defaultLabel);
layout.Add(defaultStepper);
layout.Add(defaultLabelValue);

defaultStepper.ValueChanged += (s, e) =>
{
defaultLabelValue.Text = e.NewValue.ToString();
};

Content = layout;
}
}
}
82 changes: 82 additions & 0 deletions src/Controls/tests/TestCases.Shared.Tests/Tests/StepperUITests.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,82 @@
#if ANDROID || IOS || WINDOWS
using NUnit.Framework;
using NUnit.Framework.Legacy;
using UITest.Appium;
using UITest.Core;

namespace Microsoft.Maui.TestCases.Tests
{
[Category(UITestCategories.Stepper)]
public class StepperUITests : UITest
{
public const string StepperGallery = "Stepper Gallery";

public StepperUITests(TestDevice device)
: base(device)
{
}

protected override void FixtureSetup()
{
base.FixtureSetup();
App.NavigateToGallery(StepperGallery);
}

[Test]
[Category(UITestCategories.Stepper)]
[Description("Increase the Stepper value")]
public void IncreaseStepper()
{
const string titleAutomationId = "DefaultLabel";
const string stepperAutomationId = "DefaultStepper";
const string valueAutomationId = "DefaultLabelValue";

App.WaitForElement(titleAutomationId);

// 1. Check the current value.
var step1Value = App.FindElement(valueAutomationId).GetText();
ClassicAssert.AreEqual("0", step1Value);

// 2. Increase the value.
App.IncreaseStepper(stepperAutomationId);
App.Screenshot("Increase the Stepper value");

// 3. Verify that the value has increased.
var step3Value = App.FindElement(valueAutomationId).GetText();
ClassicAssert.AreEqual("1", step3Value);
}

[Test]
[Category(UITestCategories.Stepper)]
[Description("Decrease the Stepper value")]
public void DecreaseStepper()
{
const string titleAutomationId = "DefaultLabel";
const string stepperAutomationId = "DefaultStepper";
const string valueAutomationId = "DefaultLabelValue";

App.WaitForElement(titleAutomationId);

// 1. Check the current value.
var step1Value = App.FindElement(valueAutomationId).GetText();
ClassicAssert.AreEqual("0", step1Value);

// 2. Increase the value.
App.IncreaseStepper(stepperAutomationId);
App.Screenshot("Increase the Stepper value");

// 3. Verify that the value has increased.
var step3Value = App.FindElement(valueAutomationId).GetText();
ClassicAssert.AreEqual("1", step3Value);

// 4. Decrease the value.
App.DecreaseStepper(stepperAutomationId);
App.Screenshot("Decrease the Stepper value");

// 5. Verify that the value has decreased.
var step5Value = App.FindElement(valueAutomationId).GetText();
ClassicAssert.AreEqual("0", step5Value);
}
}
}
#endif
10 changes: 9 additions & 1 deletion src/Core/src/Platform/Windows/MauiStepper.cs
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@
using System.Linq;
using Microsoft.Maui.Graphics;
using Microsoft.UI.Xaml;
using Microsoft.UI.Xaml.Automation;
using Microsoft.UI.Xaml.Controls;
using Microsoft.UI.Xaml.Media;
using WBrush = Microsoft.UI.Xaml.Media.Brush;
Expand Down Expand Up @@ -98,14 +99,21 @@ protected override void OnApplyTemplate()
{
base.OnApplyTemplate();

var mauiStepperAutomationId = AutomationProperties.GetAutomationId(this);

_plus = GetTemplateChild("Plus") as Button;
if (_plus != null)
{
AutomationProperties.SetAutomationId(_plus, mauiStepperAutomationId + "Plus");
_plus.Click += OnPlusClicked;
}

_minus = GetTemplateChild("Minus") as Button;
if (_minus != null)
{
AutomationProperties.SetAutomationId(_minus, mauiStepperAutomationId + "Minus");
_minus.Click += OnMinusClicked;

}
UpdateEnabled(Value);
UpdateButtonBackground();
}
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,94 @@
using OpenQA.Selenium.Appium;
using UITest.Core;

namespace UITest.Appium;

public class AppiumAndroidStepperActions : ICommandExecutionGroup
{
const string IncreaseCommand = "increaseStepper";
const string DecreaseCommand = "decreaseStepper";

readonly List<string> _commands = new()
{
IncreaseCommand,
DecreaseCommand
};
readonly AppiumApp _appiumApp;

public AppiumAndroidStepperActions(AppiumApp appiumApp)
{
_appiumApp = appiumApp;
}

public bool IsCommandSupported(string commandName)
{
return _commands.Contains(commandName, StringComparer.OrdinalIgnoreCase);
}

public CommandResponse Execute(string commandName, IDictionary<string, object> parameters)
{
return commandName switch
{
IncreaseCommand => Increase(parameters),
DecreaseCommand => Decrease(parameters),
_ => CommandResponse.FailedEmptyResponse,
};
}

CommandResponse Increase(IDictionary<string, object> parameters)
{
string? elementId = parameters["elementId"].ToString();

if (elementId is null)
return CommandResponse.FailedEmptyResponse;

var element = _appiumApp.FindElement(elementId);
var stepper = GetAppiumElement(element);

if (stepper is null)
return CommandResponse.FailedEmptyResponse;

var buttons = AppiumQuery.ByClass("android.widget.Button").FindElements(stepper, _appiumApp);

if(buttons is not null && buttons.Count > 1)
{
var increaseButton = buttons.LastOrDefault();
increaseButton?.Tap();
}

return CommandResponse.SuccessEmptyResponse;
}

CommandResponse Decrease(IDictionary<string, object> parameters)
{
string? elementId = parameters["elementId"].ToString();

if (elementId is null)
return CommandResponse.FailedEmptyResponse;

var element = _appiumApp.FindElement(elementId);
var stepper = GetAppiumElement(element);

if (stepper is null)
return CommandResponse.FailedEmptyResponse;

var buttons = AppiumQuery.ByClass("android.widget.Button").FindElements(stepper, _appiumApp);

if (buttons is not null && buttons.Count > 1)
{
var decreaseButton = buttons.FirstOrDefault();
decreaseButton?.Tap();
}

return CommandResponse.SuccessEmptyResponse;
}

static AppiumElement? GetAppiumElement(object element) =>
element switch
{
AppiumElement appiumElement => appiumElement,
AppiumDriverElement driverElement => driverElement.AppiumElement,
_ => null
};
}

94 changes: 94 additions & 0 deletions src/TestUtils/src/UITest.Appium/Actions/AppiumIOSStepperActions.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,94 @@
using OpenQA.Selenium.Appium;
using UITest.Core;

namespace UITest.Appium;

class AppiumIOSStepperActions : ICommandExecutionGroup
{
const string IncreaseCommand = "increaseStepper";
const string DecreaseCommand = "decreaseStepper";

readonly List<string> _commands = new()
{
IncreaseCommand,
DecreaseCommand
};

readonly AppiumApp _appiumApp;

public AppiumIOSStepperActions(AppiumApp appiumApp)
{
_appiumApp = appiumApp;
}

public bool IsCommandSupported(string commandName)
{
return _commands.Contains(commandName, StringComparer.OrdinalIgnoreCase);
}

public CommandResponse Execute(string commandName, IDictionary<string, object> parameters)
{
return commandName switch
{
IncreaseCommand => Increase(parameters),
DecreaseCommand => Decrease(parameters),
_ => CommandResponse.FailedEmptyResponse,
};
}

CommandResponse Increase(IDictionary<string, object> parameters)
{
string? elementId = parameters["elementId"].ToString();

if (elementId is null)
return CommandResponse.FailedEmptyResponse;

var element = _appiumApp.FindElement(elementId);
var stepper = GetAppiumElement(element);

if (stepper is null)
return CommandResponse.FailedEmptyResponse;

var buttons = AppiumQuery.ByClass("XCUIElementTypeButton").FindElements(stepper, _appiumApp);

if (buttons is not null && buttons.Count > 1)
{
var increaseButton = buttons.LastOrDefault();
increaseButton?.Tap();
}

return CommandResponse.SuccessEmptyResponse;
}

CommandResponse Decrease(IDictionary<string, object> parameters)
{
string? elementId = parameters["elementId"].ToString();

if (elementId is null)
return CommandResponse.FailedEmptyResponse;

var element = _appiumApp.FindElement(elementId);
var stepper = GetAppiumElement(element);

if (stepper is null)
return CommandResponse.FailedEmptyResponse;

var buttons = AppiumQuery.ByClass("XCUIElementTypeButton").FindElements(stepper, _appiumApp);

if (buttons is not null && buttons.Count > 1)
{
var decreaseButton = buttons.FirstOrDefault();
decreaseButton?.Tap();
}

return CommandResponse.SuccessEmptyResponse;
}

static AppiumElement? GetAppiumElement(object element) =>
element switch
{
AppiumElement appiumElement => appiumElement,
AppiumDriverElement driverElement => driverElement.AppiumElement,
_ => null
};
}
Loading

0 comments on commit 24c6cd4

Please sign in to comment.