Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[Testing] Add UITest Stepper actions #25130

Merged
merged 12 commits into from
Oct 14, 2024
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;
}
}
}
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
};
}

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
Loading