diff --git a/src/Legerity.Android/AndroidByExtras.cs b/src/Legerity.Android/AndroidByExtras.cs index 92a3dfaf..85c2e8e0 100644 --- a/src/Legerity.Android/AndroidByExtras.cs +++ b/src/Legerity.Android/AndroidByExtras.cs @@ -1,32 +1,31 @@ -namespace Legerity.Android -{ - using OpenQA.Selenium; - using OpenQA.Selenium.Appium; - using OpenQA.Selenium.Appium.Android.UiAutomator; +namespace Legerity.Android; + +using OpenQA.Selenium; +using OpenQA.Selenium.Appium; +using OpenQA.Selenium.Appium.Android.UiAutomator; +/// +/// Defines a collection of extra locator constraints for . +/// +public static class AndroidByExtras +{ /// - /// Defines a collection of extra locator constraints for . + /// Gets a mechanism to find elements by an Android content description. /// - public static class AndroidByExtras + /// The content description to match exactly on. + /// A object the driver can use to find elements. + public static By ContentDescription(string contentDesc) { - /// - /// Gets a mechanism to find elements by an Android content description. - /// - /// The content description to match exactly on. - /// A object the driver can use to find elements. - public static By ContentDescription(string contentDesc) - { - return new ByAndroidUIAutomator(new AndroidUiSelector().DescriptionEquals(contentDesc)); - } + return new ByAndroidUIAutomator(new AndroidUiSelector().DescriptionEquals(contentDesc)); + } - /// - /// Gets a mechanism to find elements by an Android partial content description. - /// - /// The partial content description to match on. - /// A object the driver can use to find elements. - public static By PartialContentDescription(string contentDesc) - { - return new ByAndroidUIAutomator(new AndroidUiSelector().DescriptionContains(contentDesc)); - } + /// + /// Gets a mechanism to find elements by an Android partial content description. + /// + /// The partial content description to match on. + /// A object the driver can use to find elements. + public static By PartialContentDescription(string contentDesc) + { + return new ByAndroidUIAutomator(new AndroidUiSelector().DescriptionContains(contentDesc)); } } \ No newline at end of file diff --git a/src/Legerity.Android/Elements/AndroidElementWrapper.cs b/src/Legerity.Android/Elements/AndroidElementWrapper.cs index 2104e559..51eef248 100644 --- a/src/Legerity.Android/Elements/AndroidElementWrapper.cs +++ b/src/Legerity.Android/Elements/AndroidElementWrapper.cs @@ -80,13 +80,22 @@ public static implicit operator AndroidElementWrapper(RemoteWebElement element) /// /// The amount of time the driver should wait when searching for the if it is not immediately present. /// + /// Thrown when an element is not shown for the expected locator. + /// Thrown when no element matches the expected locator. protected void VerifyDriverElementShown(By locator, TimeSpan? timeout) { if (timeout == null) { - if (this.Driver.FindElement(locator) == null) + try { - throw new ElementNotShownException(locator.ToString()); + if (this.Driver.FindElement(locator) == null) + { + throw new ElementNotShownException(locator.ToString()); + } + } + catch (NoSuchElementException ex) + { + throw new ElementNotShownException(locator.ToString(), ex); } } else @@ -105,13 +114,14 @@ protected void VerifyDriverElementShown(By locator, TimeSpan? timeout) /// /// The amount of time the driver should wait when searching for the if it is not immediately present. /// + /// Thrown when no elements are shown for the expected locator. protected void VerifyDriverElementsShown(By locator, TimeSpan? timeout) { if (timeout == null) { if (this.Driver.FindElements(locator).Count == 0) { - throw new ElementNotShownException(locator.ToString()); + throw new ElementsNotShownException(locator.ToString()); } } else diff --git a/src/Legerity.Android/Elements/Core/Button.cs b/src/Legerity.Android/Elements/Core/Button.cs index d02fec3f..6f8a4fab 100644 --- a/src/Legerity.Android/Elements/Core/Button.cs +++ b/src/Legerity.Android/Elements/Core/Button.cs @@ -1,66 +1,65 @@ -namespace Legerity.Android.Elements.Core -{ - using Legerity.Android.Elements; - using OpenQA.Selenium.Appium; - using OpenQA.Selenium.Appium.Android; - using OpenQA.Selenium.Remote; +namespace Legerity.Android.Elements.Core; + +using Legerity.Android.Elements; +using OpenQA.Selenium.Appium; +using OpenQA.Selenium.Appium.Android; +using OpenQA.Selenium.Remote; +/// +/// Defines a wrapper for the core Android Button control. +/// +public class Button : AndroidElementWrapper +{ /// - /// Defines a wrapper for the core Android Button control. + /// Initializes a new instance of the class. /// - public class Button : AndroidElementWrapper + /// + /// The reference. + /// + public Button(AndroidElement element) + : base(element) { - /// - /// Initializes a new instance of the class. - /// - /// - /// The reference. - /// - public Button(AndroidElement element) - : base(element) - { - } + } - /// - /// Allows conversion of a to the without direct casting. - /// - /// - /// The . - /// - /// - /// The . - /// - public static implicit operator Button(AndroidElement element) - { - return new Button(element); - } + /// + /// Allows conversion of a to the without direct casting. + /// + /// + /// The . + /// + /// + /// The . + /// + public static implicit operator Button(AndroidElement element) + { + return new Button(element); + } - /// - /// Allows conversion of a to the without direct casting. - /// - /// - /// The . - /// - /// - /// The . - /// - public static implicit operator Button(AppiumWebElement element) - { - return new Button(element as AndroidElement); - } + /// + /// Allows conversion of a to the without direct casting. + /// + /// + /// The . + /// + /// + /// The . + /// + public static implicit operator Button(AppiumWebElement element) + { + return new Button(element as AndroidElement); + } - /// - /// Allows conversion of a to the without direct casting. - /// - /// - /// The . - /// - /// - /// The . - /// - public static implicit operator Button(RemoteWebElement element) - { - return new Button(element as AndroidElement); - } + /// + /// Allows conversion of a to the without direct casting. + /// + /// + /// The . + /// + /// + /// The . + /// + public static implicit operator Button(RemoteWebElement element) + { + return new Button(element as AndroidElement); } } \ No newline at end of file diff --git a/src/Legerity.Android/Elements/Core/CheckBox.cs b/src/Legerity.Android/Elements/Core/CheckBox.cs index bcd30468..978c5456 100644 --- a/src/Legerity.Android/Elements/Core/CheckBox.cs +++ b/src/Legerity.Android/Elements/Core/CheckBox.cs @@ -1,98 +1,104 @@ -namespace Legerity.Android.Elements.Core -{ - using OpenQA.Selenium.Appium; - using OpenQA.Selenium.Appium.Android; - using OpenQA.Selenium.Remote; +namespace Legerity.Android.Elements.Core; + +using Extensions; +using OpenQA.Selenium; +using OpenQA.Selenium.Appium; +using OpenQA.Selenium.Appium.Android; +using OpenQA.Selenium.Remote; +/// +/// Defines a wrapper for the core Android CheckBox control. +/// +public class CheckBox : AndroidElementWrapper +{ /// - /// Defines a wrapper for the core Android CheckBox control. + /// Initializes a new instance of the class. /// - public class CheckBox : AndroidElementWrapper + /// + /// The reference. + /// + public CheckBox(AndroidElement element) + : base(element) { - private const string CheckedValue = "true"; + } - /// - /// Initializes a new instance of the class. - /// - /// - /// The reference. - /// - public CheckBox(AndroidElement element) - : base(element) - { - } + /// + /// Gets a value indicating whether the check box is in the checked state. + /// + /// Thrown when an element is no longer valid in the document DOM. + public virtual bool IsChecked => this.GetCheckedState(); - /// - /// Gets a value indicating whether the check box is in the checked state. - /// - public virtual bool IsChecked => this.GetAttribute("Checked") == CheckedValue; + /// + /// Allows conversion of a to the without direct casting. + /// + /// + /// The . + /// + /// + /// The . + /// + public static implicit operator CheckBox(AndroidElement element) + { + return new CheckBox(element); + } - /// - /// Allows conversion of a to the without direct casting. - /// - /// - /// The . - /// - /// - /// The . - /// - public static implicit operator CheckBox(AndroidElement element) - { - return new CheckBox(element); - } + /// + /// Allows conversion of a to the without direct casting. + /// + /// + /// The . + /// + /// + /// The . + /// + public static implicit operator CheckBox(AppiumWebElement element) + { + return new CheckBox(element as AndroidElement); + } - /// - /// Allows conversion of a to the without direct casting. - /// - /// - /// The . - /// - /// - /// The . - /// - public static implicit operator CheckBox(AppiumWebElement element) - { - return new CheckBox(element as AndroidElement); - } + /// + /// Allows conversion of a to the without direct casting. + /// + /// + /// The . + /// + /// + /// The . + /// + public static implicit operator CheckBox(RemoteWebElement element) + { + return new CheckBox(element as AndroidElement); + } - /// - /// Allows conversion of a to the without direct casting. - /// - /// - /// The . - /// - /// - /// The . - /// - public static implicit operator CheckBox(RemoteWebElement element) + /// + /// Checks the check box on. + /// + /// Thrown when an element is not enabled. + /// Thrown when an element is not visible. + /// Thrown when an element is no longer valid in the document DOM. + public virtual void CheckOn() + { + if (this.IsChecked) { - return new CheckBox(element as AndroidElement); + return; } - /// - /// Checks the check box on. - /// - public virtual void CheckOn() - { - if (this.IsChecked) - { - return; - } - - this.Click(); - } + this.Click(); + } - /// - /// Checks the check box off. - /// - public virtual void CheckOff() + /// + /// Checks the check box off. + /// + /// Thrown when an element is not enabled. + /// Thrown when an element is not visible. + /// Thrown when an element is no longer valid in the document DOM. + public virtual void CheckOff() + { + if (!this.IsChecked) { - if (!this.IsChecked) - { - return; - } - - this.Click(); + return; } + + this.Click(); } } \ No newline at end of file diff --git a/src/Legerity.Android/Elements/Core/DatePicker.cs b/src/Legerity.Android/Elements/Core/DatePicker.cs index b44d5e05..e7f0d06d 100644 --- a/src/Legerity.Android/Elements/Core/DatePicker.cs +++ b/src/Legerity.Android/Elements/Core/DatePicker.cs @@ -1,174 +1,186 @@ -namespace Legerity.Android.Elements.Core +namespace Legerity.Android.Elements.Core; + +using System; +using System.Collections.Generic; +using System.Linq; +using OpenQA.Selenium; +using OpenQA.Selenium.Appium; +using OpenQA.Selenium.Appium.Android; +using OpenQA.Selenium.Remote; + +/// +/// Defines a wrapper for the core Android DatePicker control. +/// +public class DatePicker : AndroidElementWrapper { - using System; - using System.Collections.Generic; - using System.Linq; - using OpenQA.Selenium; - using OpenQA.Selenium.Appium; - using OpenQA.Selenium.Appium.Android; - using OpenQA.Selenium.Remote; + private readonly Dictionary months = new() + { + { "Jan", "01" }, + { "Feb", "02" }, + { "Mar", "03" }, + { "Apr", "04" }, + { "May", "05" }, + { "Jun", "06" }, + { "Jul", "07" }, + { "Aug", "08" }, + { "Sep", "09" }, + { "Oct", "10" }, + { "Nov", "11" }, + { "Dec", "12" }, + }; /// - /// Defines a wrapper for the core Android DatePicker control. + /// Initializes a new instance of the class. /// - public class DatePicker : AndroidElementWrapper + /// + /// The reference. + /// + public DatePicker(AndroidElement element) + : base(element) { - private readonly Dictionary months = new Dictionary() - { - { "Jan", "01" }, - { "Feb", "02" }, - { "Mar", "03" }, - { "Apr", "04" }, - { "May", "05" }, - { "Jun", "06" }, - { "Jul", "07" }, - { "Aug", "08" }, - { "Sep", "09" }, - { "Oct", "10" }, - { "Nov", "11" }, - { "Dec", "12" }, - }; - - /// - /// Initializes a new instance of the class. - /// - /// - /// The reference. - /// - public DatePicker(AndroidElement element) - : base(element) - { - } + } - /// - /// Gets the element associated with the date text. - /// - /// This will be in the format, 'ddd, MMM d'. - /// - /// - public virtual TextView DateTextView => this.Element.FindElement(By.Id("android:id/date_picker_header_date")); - - /// - /// Gets the element associated with the year text. - /// - /// This will be in the format, 'YYYY'. - /// - /// - public virtual TextView YearTextView => this.Element.FindElement(By.Id("android:id/date_picker_header_year")); - - /// - /// Gets the element associated with the day picker. - /// - public virtual View DayPickerView => this.Element.FindElement(By.Id("android:id/day_picker_view_pager")); - - /// - /// Gets the element associated with the next month button. - /// - public virtual Button NextMonthButton => this.Element.FindElementByAndroidUIAutomator("UiSelector().description(\"Next month\")"); - - /// - /// Gets the element associated with the previous month button. - /// - public virtual Button PreviousMonthButton => this.Element.FindElementByAndroidUIAutomator("UiSelector().description(\"Previous month\")"); - - /// - /// Gets the selected date/time value. - /// - public virtual DateTime SelectedDate => this.GetCurrentViewDate(); - - /// - /// Allows conversion of a to the without direct casting. - /// - /// - /// The . - /// - /// - /// The . - /// - public static implicit operator DatePicker(AndroidElement element) - { - return new DatePicker(element); - } + /// + /// Gets the element associated with the date text. + /// + /// This will be in the format, 'ddd, MMM d'. + /// + /// + /// Thrown when no element matches the expected locator. + public virtual TextView DateTextView => this.FindElement(By.Id("android:id/date_picker_header_date")); - /// - /// Allows conversion of a to the without direct casting. - /// - /// - /// The . - /// - /// - /// The . - /// - public static implicit operator DatePicker(AppiumWebElement element) - { - return new DatePicker(element as AndroidElement); - } + /// + /// Gets the element associated with the year text. + /// + /// This will be in the format, 'YYYY'. + /// + /// + /// Thrown when no element matches the expected locator. + public virtual TextView YearTextView => this.FindElement(By.Id("android:id/date_picker_header_year")); - /// - /// Allows conversion of a to the without direct casting. - /// - /// - /// The . - /// - /// - /// The . - /// - public static implicit operator DatePicker(RemoteWebElement element) - { - return new DatePicker(element as AndroidElement); - } + /// + /// Gets the element associated with the day picker. + /// + /// Thrown when no element matches the expected locator. + public virtual View DayPickerView => this.FindElement(By.Id("android:id/day_picker_view_pager")); - /// - /// Sets the selected date of the date picker. - /// - /// The date to set to. - public virtual void SetDate(DateTime date) - { - DateTime currentViewDate = this.GetCurrentViewDate(); + /// + /// Gets the element associated with the next month button. + /// + /// Thrown when no element matches the expected locator. + public virtual Button NextMonthButton => this.Element.FindElementByAndroidUIAutomator("UiSelector().description(\"Next month\")"); + + /// + /// Gets the element associated with the previous month button. + /// + /// Thrown when no element matches the expected locator. + public virtual Button PreviousMonthButton => this.Element.FindElementByAndroidUIAutomator("UiSelector().description(\"Previous month\")"); + + /// + /// Gets the selected date/time value. + /// + /// Thrown when an element is no longer valid in the document DOM. + /// Thrown when no element matches the expected locator. + public virtual DateTime SelectedDate => this.GetCurrentViewDate(); + + /// + /// Allows conversion of a to the without direct casting. + /// + /// + /// The . + /// + /// + /// The . + /// + public static implicit operator DatePicker(AndroidElement element) + { + return new DatePicker(element); + } + + /// + /// Allows conversion of a to the without direct casting. + /// + /// + /// The . + /// + /// + /// The . + /// + public static implicit operator DatePicker(AppiumWebElement element) + { + return new DatePicker(element as AndroidElement); + } - int monthDifference = ((date.Year - currentViewDate.Year) * 12) + date.Month - currentViewDate.Month; + /// + /// Allows conversion of a to the without direct casting. + /// + /// + /// The . + /// + /// + /// The . + /// + public static implicit operator DatePicker(RemoteWebElement element) + { + return new DatePicker(element as AndroidElement); + } + + /// + /// Sets the selected date of the date picker. + /// + /// The date to set to. + /// Thrown when an element is not enabled. + /// Thrown when an element is not visible. + /// Thrown when an element is no longer valid in the document DOM. + /// Thrown when no element matches the expected locator. + public virtual void SetDate(DateTime date) + { + DateTime currentViewDate = this.GetCurrentViewDate(); - if (monthDifference > 0) + int monthDifference = ((date.Year - currentViewDate.Year) * 12) + date.Month - currentViewDate.Month; + + if (monthDifference > 0) + { + for (int i = 0; i < monthDifference; i++) { - for (int i = 0; i < monthDifference; i++) - { - this.NextMonthButton.Click(); - } + this.NextMonthButton.Click(); } - else + } + else + { + for (int i = 0; i < Math.Abs(monthDifference); i++) { - for (int i = 0; i < Math.Abs(monthDifference); i++) - { - this.PreviousMonthButton.Click(); - } + this.PreviousMonthButton.Click(); } - - View item = this.DayPickerView.Element.FindElementByAndroidUIAutomator($"UiSelector().text(\"{date.Day}\")"); - item.Click(); } - private DateTime GetCurrentViewDate() - { - string currentYear = this.YearTextView.Text; - string currentDate = this.DateTextView.Text; - return this.GetCurrentViewDate(currentDate, currentYear); - } + View item = this.DayPickerView.Element.FindElementByAndroidUIAutomator($"UiSelector().text(\"{date.Day}\")"); + item.Click(); + } - private DateTime GetCurrentViewDate(string currentDate, string currentYear) - { - string day = string.Join(string.Empty, currentDate.Where(char.IsDigit)).Trim(); + /// Thrown when no element matches the expected locator. + /// Thrown when an element is no longer valid in the document DOM. + private DateTime GetCurrentViewDate() + { + string currentYear = this.YearTextView.Text; + string currentDate = this.DateTextView.Text; + return this.GetCurrentViewDate(currentDate, currentYear); + } - var currentDateSplit = currentDate.Split(',').ToList(); - string currentMonthPart = currentDateSplit.LastOrDefault(); + private DateTime GetCurrentViewDate(string currentDate, string currentYear) + { + string day = string.Join(string.Empty, currentDate.Where(char.IsDigit)).Trim(); - this.months.TryGetValue( - string.Join(string.Empty, (currentMonthPart ?? string.Empty).Where(char.IsLetter)).Trim(), - out string month); + var currentDateSplit = currentDate.Split(',').ToList(); + string currentMonthPart = currentDateSplit.LastOrDefault(); - string year = string.Join(string.Empty, currentYear.Where(char.IsDigit)).Trim(); + this.months.TryGetValue( + string.Join(string.Empty, (currentMonthPart ?? string.Empty).Where(char.IsLetter)).Trim(), + out string month); - string dateString = $"{day}/{month}/{year}"; - return DateTime.ParseExact(dateString, @"d/MM/yyyy", System.Globalization.CultureInfo.InvariantCulture); - } + string year = string.Join(string.Empty, currentYear.Where(char.IsDigit)).Trim(); + + string dateString = $"{day}/{month}/{year}"; + return DateTime.ParseExact(dateString, @"d/MM/yyyy", System.Globalization.CultureInfo.InvariantCulture); } } \ No newline at end of file diff --git a/src/Legerity.Android/Elements/Core/EditText.cs b/src/Legerity.Android/Elements/Core/EditText.cs index 1a8371de..7a837e00 100644 --- a/src/Legerity.Android/Elements/Core/EditText.cs +++ b/src/Legerity.Android/Elements/Core/EditText.cs @@ -1,97 +1,106 @@ -namespace Legerity.Android.Elements.Core -{ - using OpenQA.Selenium.Appium; - using OpenQA.Selenium.Appium.Android; - using OpenQA.Selenium.Remote; +namespace Legerity.Android.Elements.Core; + +using OpenQA.Selenium; +using OpenQA.Selenium.Appium; +using OpenQA.Selenium.Appium.Android; +using OpenQA.Selenium.Remote; +/// +/// Defines a wrapper for the core Android EditText control. +/// +public class EditText : AndroidElementWrapper +{ /// - /// Defines a wrapper for the core Android EditText control. + /// Initializes a new instance of the class. /// - public class EditText : AndroidElementWrapper + /// The representing the element. + public EditText(AndroidElement element) + : base(element) { - /// - /// Initializes a new instance of the class. - /// - /// The representing the element. - public EditText(AndroidElement element) - : base(element) - { - } + } - /// - /// Gets the text value of the text box. - /// - public virtual string Text => this.Element.Text; + /// + /// Gets the text value of the text box. + /// + public virtual string Text => this.Element.Text; - /// - /// Allows conversion of a to the without direct casting. - /// - /// - /// The . - /// - /// - /// The . - /// - public static implicit operator EditText(AndroidElement element) - { - return new EditText(element); - } + /// + /// Allows conversion of a to the without direct casting. + /// + /// + /// The . + /// + /// + /// The . + /// + public static implicit operator EditText(AndroidElement element) + { + return new EditText(element); + } - /// - /// Allows conversion of a to the without direct casting. - /// - /// - /// The . - /// - /// - /// The . - /// - public static implicit operator EditText(AppiumWebElement element) - { - return new EditText(element as AndroidElement); - } + /// + /// Allows conversion of a to the without direct casting. + /// + /// + /// The . + /// + /// + /// The . + /// + public static implicit operator EditText(AppiumWebElement element) + { + return new EditText(element as AndroidElement); + } - /// - /// Allows conversion of a to the without direct casting. - /// - /// - /// The . - /// - /// - /// The . - /// - public static implicit operator EditText(RemoteWebElement element) - { - return new EditText(element as AndroidElement); - } + /// + /// Allows conversion of a to the without direct casting. + /// + /// + /// The . + /// + /// + /// The . + /// + public static implicit operator EditText(RemoteWebElement element) + { + return new EditText(element as AndroidElement); + } - /// - /// Sets the text of the text box to the specified text. - /// - /// The text to display. - public virtual void SetText(string text) - { - this.ClearText(); - this.AppendText(text); - } + /// + /// Sets the text of the text box to the specified text. + /// + /// The text to display. + /// Thrown when an element is no longer valid in the document DOM. + /// Thrown when an element is not enabled. + /// Thrown when an element is not visible. + public virtual void SetText(string text) + { + this.ClearText(); + this.AppendText(text); + } - /// - /// Appends the specified text to the text box. - /// - /// The text to append. - public virtual void AppendText(string text) - { - this.Click(); - this.Element.SendKeys(text); - } + /// + /// Appends the specified text to the text box. + /// + /// The text to append. + /// Thrown when an element is not enabled. + /// Thrown when an element is not visible. + /// Thrown when an element is no longer valid in the document DOM. + public virtual void AppendText(string text) + { + this.Click(); + this.Element.SendKeys(text); + } - /// - /// Clears the text from the text box. - /// - public virtual void ClearText() - { - this.Click(); - this.Element.Clear(); - } + /// + /// Clears the text from the text box. + /// + /// Thrown when an element is not enabled. + /// Thrown when an element is not visible. + /// Thrown when an element is no longer valid in the document DOM. + public virtual void ClearText() + { + this.Click(); + this.Element.Clear(); } } \ No newline at end of file diff --git a/src/Legerity.Android/Elements/Core/RadioButton.cs b/src/Legerity.Android/Elements/Core/RadioButton.cs index b7dd32d7..d3935645 100644 --- a/src/Legerity.Android/Elements/Core/RadioButton.cs +++ b/src/Legerity.Android/Elements/Core/RadioButton.cs @@ -1,72 +1,72 @@ -namespace Legerity.Android.Elements.Core -{ - using System; - using OpenQA.Selenium.Appium; - using OpenQA.Selenium.Appium.Android; - using OpenQA.Selenium.Remote; +namespace Legerity.Android.Elements.Core; + +using Extensions; +using OpenQA.Selenium; +using OpenQA.Selenium.Appium; +using OpenQA.Selenium.Appium.Android; +using OpenQA.Selenium.Remote; +/// +/// Defines a wrapper for the core Android RadioButton control. +/// +public class RadioButton : Button +{ /// - /// Defines a wrapper for the core Android RadioButton control. + /// Initializes a new instance of the class. /// - public class RadioButton : Button + /// + /// The reference. + /// + public RadioButton(AndroidElement element) + : base(element) { - /// - /// Initializes a new instance of the class. - /// - /// - /// The reference. - /// - public RadioButton(AndroidElement element) - : base(element) - { - } + } - /// - /// Gets a value indicating whether the radio button is selected. - /// - public virtual bool IsSelected => - this.GetAttribute("Checked").Equals("True", StringComparison.CurrentCultureIgnoreCase); + /// + /// Gets a value indicating whether the radio button is selected. + /// + /// Thrown when an element is no longer valid in the document DOM. + public virtual bool IsSelected => this.GetCheckedState(); - /// - /// Allows conversion of a to the without direct casting. - /// - /// - /// The . - /// - /// - /// The . - /// - public static implicit operator RadioButton(AndroidElement element) - { - return new RadioButton(element); - } + /// + /// Allows conversion of a to the without direct casting. + /// + /// + /// The . + /// + /// + /// The . + /// + public static implicit operator RadioButton(AndroidElement element) + { + return new RadioButton(element); + } - /// - /// Allows conversion of a to the without direct casting. - /// - /// - /// The . - /// - /// - /// The . - /// - public static implicit operator RadioButton(AppiumWebElement element) - { - return new RadioButton(element as AndroidElement); - } + /// + /// Allows conversion of a to the without direct casting. + /// + /// + /// The . + /// + /// + /// The . + /// + public static implicit operator RadioButton(AppiumWebElement element) + { + return new RadioButton(element as AndroidElement); + } - /// - /// Allows conversion of a to the without direct casting. - /// - /// - /// The . - /// - /// - /// The . - /// - public static implicit operator RadioButton(RemoteWebElement element) - { - return new RadioButton(element as AndroidElement); - } + /// + /// Allows conversion of a to the without direct casting. + /// + /// + /// The . + /// + /// + /// The . + /// + public static implicit operator RadioButton(RemoteWebElement element) + { + return new RadioButton(element as AndroidElement); } } \ No newline at end of file diff --git a/src/Legerity.Android/Elements/Core/Spinner.cs b/src/Legerity.Android/Elements/Core/Spinner.cs index d38247e5..590ddfe0 100644 --- a/src/Legerity.Android/Elements/Core/Spinner.cs +++ b/src/Legerity.Android/Elements/Core/Spinner.cs @@ -1,111 +1,120 @@ -namespace Legerity.Android.Elements.Core -{ - using OpenQA.Selenium; - using OpenQA.Selenium.Appium; - using OpenQA.Selenium.Appium.Android; - using OpenQA.Selenium.Remote; +namespace Legerity.Android.Elements.Core; + +using OpenQA.Selenium; +using OpenQA.Selenium.Appium; +using OpenQA.Selenium.Appium.Android; +using OpenQA.Selenium.Remote; +/// +/// Defines a wrapper for the core Android Spinner control. +/// +public class Spinner : AndroidElementWrapper +{ /// - /// Defines a wrapper for the core Android Spinner control. + /// Initializes a new instance of the class. /// - public class Spinner : AndroidElementWrapper + /// + /// The reference. + /// + public Spinner(AndroidElement element) + : base(element) { - /// - /// Initializes a new instance of the class. - /// - /// - /// The reference. - /// - public Spinner(AndroidElement element) - : base(element) - { - } + } - /// - /// Gets the currently selected item. - /// - public virtual string SelectedItem => this.GetSelectedItem(); + /// + /// Gets the currently selected item. + /// + /// Thrown when no element matches the expected locator. + public virtual string SelectedItem => this.GetSelectedItem(); - /// - /// Allows conversion of a to the without direct casting. - /// - /// - /// The . - /// - /// - /// The . - /// - public static implicit operator Spinner(AndroidElement element) - { - return new Spinner(element); - } + /// + /// Allows conversion of a to the without direct casting. + /// + /// + /// The . + /// + /// + /// The . + /// + public static implicit operator Spinner(AndroidElement element) + { + return new Spinner(element); + } - /// - /// Allows conversion of a to the without direct casting. - /// - /// - /// The . - /// - /// - /// The . - /// - public static implicit operator Spinner(AppiumWebElement element) - { - return new Spinner(element as AndroidElement); - } + /// + /// Allows conversion of a to the without direct casting. + /// + /// + /// The . + /// + /// + /// The . + /// + public static implicit operator Spinner(AppiumWebElement element) + { + return new Spinner(element as AndroidElement); + } - /// - /// Allows conversion of a to the without direct casting. - /// - /// - /// The . - /// - /// - /// The . - /// - public static implicit operator Spinner(RemoteWebElement element) - { - return new Spinner(element as AndroidElement); - } + /// + /// Allows conversion of a to the without direct casting. + /// + /// + /// The . + /// + /// + /// The . + /// + public static implicit operator Spinner(RemoteWebElement element) + { + return new Spinner(element as AndroidElement); + } - /// - /// Selects an item in the combo-box with the specified item name. - /// - /// - /// The name of the item to select. - /// - public virtual void SelectItem(string name) - { - this.Click(); + /// + /// Selects an item in the combo-box with the specified item name. + /// + /// + /// The name of the item to select. + /// + /// Thrown when an element is not enabled. + /// Thrown when an element is not visible. + /// Thrown when an element is no longer valid in the document DOM. + /// Thrown when no element matches the expected locator. + public virtual void SelectItem(string name) + { + this.Click(); - var locator = - new ByAndroidUIAutomator( - $"new UiScrollable(new UiSelector()).scrollIntoView(new UiSelector().text(\"{name}\"));"); - AndroidElement item = this.Driver.FindElement(locator); + var locator = + new ByAndroidUIAutomator( + $"new UiScrollable(new UiSelector()).scrollIntoView(new UiSelector().text(\"{name}\"));"); + AndroidElement item = this.Driver.FindElement(locator); - item.Click(); - } + item.Click(); + } - /// - /// Selects an item in the combo-box with the specified partial item name. - /// - /// The partial name match for the item to select. - public virtual void SelectItemByPartialName(string partialName) - { - this.Click(); + /// + /// Selects an item in the combo-box with the specified partial item name. + /// + /// The partial name match for the item to select. + /// Thrown when an element is not enabled. + /// Thrown when an element is not visible. + /// Thrown when an element is no longer valid in the document DOM. + /// Thrown when no element matches the expected locator. + public virtual void SelectItemByPartialName(string partialName) + { + this.Click(); - var locator = - new ByAndroidUIAutomator( - $"new UiScrollable(new UiSelector()).scrollIntoView(new UiSelector().textContains(\"{partialName}\"));"); - AndroidElement item = this.Driver.FindElement(locator); + var locator = + new ByAndroidUIAutomator( + $"new UiScrollable(new UiSelector()).scrollIntoView(new UiSelector().textContains(\"{partialName}\"));"); + AndroidElement item = this.Driver.FindElement(locator); - item.Click(); - } + item.Click(); + } - private string GetSelectedItem() - { - TextView textElement = this.Element.FindElement(By.ClassName("android.widget.TextView")); - return textElement.Text; - } + /// Thrown when no element matches the expected locator. + private string GetSelectedItem() + { + TextView textElement = this.FindElement(By.ClassName("android.widget.TextView")); + return textElement.Text; } } \ No newline at end of file diff --git a/src/Legerity.Android/Elements/Core/Switch.cs b/src/Legerity.Android/Elements/Core/Switch.cs index 66f02788..66e592ae 100644 --- a/src/Legerity.Android/Elements/Core/Switch.cs +++ b/src/Legerity.Android/Elements/Core/Switch.cs @@ -1,97 +1,104 @@ -namespace Legerity.Android.Elements.Core +namespace Legerity.Android.Elements.Core; + +using Extensions; +using OpenQA.Selenium; +using OpenQA.Selenium.Appium; +using OpenQA.Selenium.Appium.Android; +using OpenQA.Selenium.Remote; + +/// +/// Defines a wrapper for the core Android Switch control. +/// +public class Switch : AndroidElementWrapper { - using System; - using OpenQA.Selenium.Appium; - using OpenQA.Selenium.Appium.Android; - using OpenQA.Selenium.Remote; + /// + /// Initializes a new instance of the class. + /// + /// + /// The reference. + /// + public Switch(AndroidElement element) + : base(element) + { + } + + /// + /// Gets a value indicating whether the toggle switch is in the on position. + /// + /// Thrown when an element is no longer valid in the document DOM. + public virtual bool IsOn => this.GetCheckedState(); /// - /// Defines a wrapper for the core Android Switch control. + /// Allows conversion of a to the without direct casting. /// - public class Switch : AndroidElementWrapper + /// + /// The . + /// + /// + /// The . + /// + public static implicit operator Switch(AndroidElement element) { - /// - /// Initializes a new instance of the class. - /// - /// - /// The reference. - /// - public Switch(AndroidElement element) - : base(element) - { - } + return new Switch(element); + } - /// - /// Gets a value indicating whether the toggle switch is in the on position. - /// - public virtual bool IsOn => this.GetAttribute("Checked").Equals("True", StringComparison.CurrentCultureIgnoreCase); + /// + /// Allows conversion of a to the without direct casting. + /// + /// + /// The . + /// + /// + /// The . + /// + public static implicit operator Switch(AppiumWebElement element) + { + return new Switch(element as AndroidElement); + } - /// - /// Allows conversion of a to the without direct casting. - /// - /// - /// The . - /// - /// - /// The . - /// - public static implicit operator Switch(AndroidElement element) - { - return new Switch(element); - } + /// + /// Allows conversion of a to the without direct casting. + /// + /// + /// The . + /// + /// + /// The . + /// + public static implicit operator Switch(RemoteWebElement element) + { + return new Switch(element as AndroidElement); + } - /// - /// Allows conversion of a to the without direct casting. - /// - /// - /// The . - /// - /// - /// The . - /// - public static implicit operator Switch(AppiumWebElement element) + /// + /// Toggles the switch on. + /// + /// Thrown when an element is not enabled. + /// Thrown when an element is not visible. + /// Thrown when an element is no longer valid in the document DOM. + public virtual void ToggleOn() + { + if (this.IsOn) { - return new Switch(element as AndroidElement); + return; } - /// - /// Allows conversion of a to the without direct casting. - /// - /// - /// The . - /// - /// - /// The . - /// - public static implicit operator Switch(RemoteWebElement element) - { - return new Switch(element as AndroidElement); - } + this.Click(); + } - /// - /// Toggles the switch on. - /// - public virtual void ToggleOn() + /// + /// Toggles the switch off. + /// + /// Thrown when an element is not enabled. + /// Thrown when an element is not visible. + /// Thrown when an element is no longer valid in the document DOM. + public virtual void ToggleOff() + { + if (!this.IsOn) { - if (this.IsOn) - { - return; - } - - this.Click(); + return; } - /// - /// Toggles the switch off. - /// - public virtual void ToggleOff() - { - if (!this.IsOn) - { - return; - } - - this.Click(); - } + this.Click(); } } \ No newline at end of file diff --git a/src/Legerity.Android/Elements/Core/TextView.cs b/src/Legerity.Android/Elements/Core/TextView.cs index 264429f0..e3ff3850 100644 --- a/src/Legerity.Android/Elements/Core/TextView.cs +++ b/src/Legerity.Android/Elements/Core/TextView.cs @@ -1,70 +1,71 @@ -namespace Legerity.Android.Elements.Core -{ - using OpenQA.Selenium.Appium; - using OpenQA.Selenium.Appium.Android; - using OpenQA.Selenium.Remote; +namespace Legerity.Android.Elements.Core; + +using OpenQA.Selenium; +using OpenQA.Selenium.Appium; +using OpenQA.Selenium.Appium.Android; +using OpenQA.Selenium.Remote; +/// +/// Defines a wrapper for the core Android TextView control. +/// +public class TextView : AndroidElementWrapper +{ /// - /// Defines a wrapper for the core Android TextView control. + /// Initializes a new instance of the class. /// - public class TextView : AndroidElementWrapper + /// + /// The reference. + /// + public TextView(AndroidElement element) + : base(element) { - /// - /// Initializes a new instance of the class. - /// - /// - /// The reference. - /// - public TextView(AndroidElement element) - : base(element) - { - } + } - /// - /// Gets the text value of the text view. - /// - public virtual string Text => this.Element.Text; + /// + /// Gets the text value of the text view. + /// + /// Thrown when an element is no longer valid in the document DOM. + public virtual string Text => this.Element.Text; - /// - /// Allows conversion of a to the without direct casting. - /// - /// - /// The . - /// - /// - /// The . - /// - public static implicit operator TextView(AndroidElement element) - { - return new TextView(element); - } + /// + /// Allows conversion of a to the without direct casting. + /// + /// + /// The . + /// + /// + /// The . + /// + public static implicit operator TextView(AndroidElement element) + { + return new TextView(element); + } - /// - /// Allows conversion of a to the without direct casting. - /// - /// - /// The . - /// - /// - /// The . - /// - public static implicit operator TextView(AppiumWebElement element) - { - return new TextView(element as AndroidElement); - } + /// + /// Allows conversion of a to the without direct casting. + /// + /// + /// The . + /// + /// + /// The . + /// + public static implicit operator TextView(AppiumWebElement element) + { + return new TextView(element as AndroidElement); + } - /// - /// Allows conversion of a to the without direct casting. - /// - /// - /// The . - /// - /// - /// The . - /// - public static implicit operator TextView(RemoteWebElement element) - { - return new TextView(element as AndroidElement); - } + /// + /// Allows conversion of a to the without direct casting. + /// + /// + /// The . + /// + /// + /// The . + /// + public static implicit operator TextView(RemoteWebElement element) + { + return new TextView(element as AndroidElement); } } \ No newline at end of file diff --git a/src/Legerity.Android/Elements/Core/ToggleButton.cs b/src/Legerity.Android/Elements/Core/ToggleButton.cs index a28db5b5..044325e2 100644 --- a/src/Legerity.Android/Elements/Core/ToggleButton.cs +++ b/src/Legerity.Android/Elements/Core/ToggleButton.cs @@ -1,97 +1,104 @@ -namespace Legerity.Android.Elements.Core +namespace Legerity.Android.Elements.Core; + +using Extensions; +using OpenQA.Selenium; +using OpenQA.Selenium.Appium; +using OpenQA.Selenium.Appium.Android; +using OpenQA.Selenium.Remote; + +/// +/// Defines a wrapper for the core Android ToggleButton control. +/// +public class ToggleButton : Button { - using System; - using OpenQA.Selenium.Appium; - using OpenQA.Selenium.Appium.Android; - using OpenQA.Selenium.Remote; + /// + /// Initializes a new instance of the class. + /// + /// + /// The reference. + /// + public ToggleButton(AndroidElement element) + : base(element) + { + } + + /// + /// Gets a value indicating whether the toggle button is in the on position. + /// + /// Thrown when an element is no longer valid in the document DOM. + public virtual bool IsOn => this.GetCheckedState(); /// - /// Defines a wrapper for the core Android ToggleButton control. + /// Allows conversion of a to the without direct casting. /// - public class ToggleButton : Button + /// + /// The . + /// + /// + /// The . + /// + public static implicit operator ToggleButton(AndroidElement element) { - /// - /// Initializes a new instance of the class. - /// - /// - /// The reference. - /// - public ToggleButton(AndroidElement element) - : base(element) - { - } + return new ToggleButton(element); + } - /// - /// Gets a value indicating whether the toggle button is in the on position. - /// - public virtual bool IsOn => this.GetAttribute("Checked").Equals("True", StringComparison.CurrentCultureIgnoreCase); + /// + /// Allows conversion of a to the without direct casting. + /// + /// + /// The . + /// + /// + /// The . + /// + public static implicit operator ToggleButton(AppiumWebElement element) + { + return new ToggleButton(element as AndroidElement); + } - /// - /// Allows conversion of a to the without direct casting. - /// - /// - /// The . - /// - /// - /// The . - /// - public static implicit operator ToggleButton(AndroidElement element) - { - return new ToggleButton(element); - } + /// + /// Allows conversion of a to the without direct casting. + /// + /// + /// The . + /// + /// + /// The . + /// + public static implicit operator ToggleButton(RemoteWebElement element) + { + return new ToggleButton(element as AndroidElement); + } - /// - /// Allows conversion of a to the without direct casting. - /// - /// - /// The . - /// - /// - /// The . - /// - public static implicit operator ToggleButton(AppiumWebElement element) + /// + /// Toggles the button on. + /// + /// Thrown when an element is not enabled. + /// Thrown when an element is not visible. + /// Thrown when an element is no longer valid in the document DOM. + public virtual void ToggleOn() + { + if (this.IsOn) { - return new ToggleButton(element as AndroidElement); + return; } - /// - /// Allows conversion of a to the without direct casting. - /// - /// - /// The . - /// - /// - /// The . - /// - public static implicit operator ToggleButton(RemoteWebElement element) - { - return new ToggleButton(element as AndroidElement); - } + this.Click(); + } - /// - /// Toggles the button on. - /// - public virtual void ToggleOn() + /// + /// Toggles the button off. + /// + /// Thrown when an element is not enabled. + /// Thrown when an element is not visible. + /// Thrown when an element is no longer valid in the document DOM. + public virtual void ToggleOff() + { + if (!this.IsOn) { - if (this.IsOn) - { - return; - } - - this.Click(); + return; } - /// - /// Toggles the button off. - /// - public virtual void ToggleOff() - { - if (!this.IsOn) - { - return; - } - - this.Click(); - } + this.Click(); } } \ No newline at end of file diff --git a/src/Legerity.Android/Elements/Core/View.cs b/src/Legerity.Android/Elements/Core/View.cs index 0ec5774f..856c85cd 100644 --- a/src/Legerity.Android/Elements/Core/View.cs +++ b/src/Legerity.Android/Elements/Core/View.cs @@ -1,66 +1,65 @@ -namespace Legerity.Android.Elements.Core -{ - using Legerity.Android.Elements; - using OpenQA.Selenium.Appium; - using OpenQA.Selenium.Appium.Android; - using OpenQA.Selenium.Remote; +namespace Legerity.Android.Elements.Core; + +using Legerity.Android.Elements; +using OpenQA.Selenium.Appium; +using OpenQA.Selenium.Appium.Android; +using OpenQA.Selenium.Remote; +/// +/// Defines a wrapper for the core Android View base control. +/// +public class View : AndroidElementWrapper +{ /// - /// Defines a wrapper for the core Android View base control. + /// Initializes a new instance of the class. /// - public class View : AndroidElementWrapper + /// + /// The reference. + /// + public View(AndroidElement element) + : base(element) { - /// - /// Initializes a new instance of the class. - /// - /// - /// The reference. - /// - public View(AndroidElement element) - : base(element) - { - } + } - /// - /// Allows conversion of a to the without direct casting. - /// - /// - /// The . - /// - /// - /// The . - /// - public static implicit operator View(AndroidElement element) - { - return new View(element); - } + /// + /// Allows conversion of a to the without direct casting. + /// + /// + /// The . + /// + /// + /// The . + /// + public static implicit operator View(AndroidElement element) + { + return new View(element); + } - /// - /// Allows conversion of a to the without direct casting. - /// - /// - /// The . - /// - /// - /// The . - /// - public static implicit operator View(AppiumWebElement element) - { - return new View(element as AndroidElement); - } + /// + /// Allows conversion of a to the without direct casting. + /// + /// + /// The . + /// + /// + /// The . + /// + public static implicit operator View(AppiumWebElement element) + { + return new View(element as AndroidElement); + } - /// - /// Allows conversion of a to the without direct casting. - /// - /// - /// The . - /// - /// - /// The . - /// - public static implicit operator View(RemoteWebElement element) - { - return new View(element as AndroidElement); - } + /// + /// Allows conversion of a to the without direct casting. + /// + /// + /// The . + /// + /// + /// The . + /// + public static implicit operator View(RemoteWebElement element) + { + return new View(element as AndroidElement); } } \ No newline at end of file diff --git a/src/Legerity.Android/Extensions/AndroidElementWrapperExtensions.cs b/src/Legerity.Android/Extensions/AndroidElementWrapperExtensions.cs index 19d33cc5..7e1bc936 100644 --- a/src/Legerity.Android/Extensions/AndroidElementWrapperExtensions.cs +++ b/src/Legerity.Android/Extensions/AndroidElementWrapperExtensions.cs @@ -21,6 +21,7 @@ public static class AndroidElementWrapperExtensions /// The type of . /// The type of expected result from the wait condition. /// Whether the wait was a success. + /// Thrown when the callback throws an exception. public static bool TryWaitUntil( this TElementWrapper element, Func condition, @@ -52,7 +53,8 @@ public static bool TryWaitUntil( /// The type of . /// The type of expected result from the wait condition. /// The of the wait until operation. - /// Thrown if the condition is not met in the allocated timeout period. + /// Thrown when the condition is not met in the allocated timeout period. + /// Thrown when the callback throws an exception. public static TResult WaitUntil( this TElementWrapper element, Func condition, diff --git a/src/Legerity.Android/Extensions/AttributeExtensions.cs b/src/Legerity.Android/Extensions/AttributeExtensions.cs index 329ca9b9..2bee18ff 100644 --- a/src/Legerity.Android/Extensions/AttributeExtensions.cs +++ b/src/Legerity.Android/Extensions/AttributeExtensions.cs @@ -1,34 +1,62 @@ -namespace Legerity.Android.Extensions +namespace Legerity.Android.Extensions; + +using System; +using OpenQA.Selenium; + +/// +/// Defines a collection of extensions for retrieving element attributes. +/// +public static class AttributeExtensions { - using OpenQA.Selenium; + /// + /// Gets the value of the Android content description for this element. + /// + /// The element to retrieve a content description for. + /// The element's content description. + /// Thrown when an element is no longer valid in the document DOM. + public static string GetContentDescription(this IWebElement element) + { + return element.GetAttribute("content-desc"); + } /// - /// Defines a collection of extensions for retrieving element attributes. + /// Gets the value of the Android content description for this element. /// - public static class AttributeExtensions + /// + /// The type of . + /// + /// The to retrieve a content description for. + /// The element's content description. + /// Thrown when an element is no longer valid in the document DOM. + public static string GetContentDescription(this IElementWrapper element) + where TElement : IWebElement { - /// - /// Gets the value of the Android content description for this element. - /// - /// The element to retrieve a content description for. - /// The element's content description. - public static string GetContentDescription(this IWebElement element) - { - return element.GetAttribute("content-desc"); - } + return GetContentDescription(element.Element); + } - /// - /// Gets the value of the Android content description for this element. - /// - /// - /// The type of . - /// - /// The to retrieve a content description for. - /// The element's content description. - public static string GetContentDescription(this IElementWrapper element) - where TElement : IWebElement - { - return GetContentDescription(element.Element); - } + /// + /// Gets the value of the Android checked state for this element. + /// + /// The element to retrieve the value from. + /// True if the element is checked; otherwise, false. + /// Thrown when an element is no longer valid in the document DOM. + public static bool GetCheckedState(this IWebElement element) + { + return element.GetAttribute("Checked").Equals("True", StringComparison.CurrentCultureIgnoreCase); + } + + /// + /// Gets the value of the Android checked state for this element. + /// + /// + /// The type of . + /// + /// The to retrieve the value from. + /// True if the element is checked; otherwise, false. + /// Thrown when an element is no longer valid in the document DOM. + public static bool GetCheckedState(this IElementWrapper element) + where TElement : IWebElement + { + return GetCheckedState(element.Element); } } \ No newline at end of file diff --git a/src/Legerity.Android/Extensions/LegerityTestClassExtensions.cs b/src/Legerity.Android/Extensions/LegerityTestClassExtensions.cs index 30464e9a..6c87eed6 100644 --- a/src/Legerity.Android/Extensions/LegerityTestClassExtensions.cs +++ b/src/Legerity.Android/Extensions/LegerityTestClassExtensions.cs @@ -1,70 +1,80 @@ -namespace Legerity.Android.Extensions -{ - using System; - using OpenQA.Selenium; - using OpenQA.Selenium.Appium.Android; +namespace Legerity.Android.Extensions; + +using System; +using Exceptions; +using OpenQA.Selenium; +using OpenQA.Selenium.Appium.Android; +/// +/// Defines a collection of extensions for instances. +/// +public static class LegerityTestClassExtensions +{ /// - /// Defines a collection of extensions for instances. + /// Starts the Android application ready for testing. /// - public static class LegerityTestClassExtensions + /// + /// The test class to launch an Android application for. + /// + /// + /// An optional condition of the driver to wait on until it is met. + /// + /// + /// An optional timeout wait on the conditional wait until being true. If not set, the wait will run immediately, and if not valid, will throw an exception. + /// + /// + /// An optional count of retries after a timeout on the wait until condition before accepting the failure. + /// + /// The configured and running application driver. + /// Thrown when the application is null, the session ID is null once initialized, or the driver fails to configure correctly before returning. + /// Thrown when the wait until condition is not met in the allocated timeout period if provided. + /// Thrown when: + /// - The Appium server could not be found when running with true. + /// + public static AndroidDriver StartAndroidApp( + this LegerityTestClass testClass, + Func waitUntil = default, + TimeSpan? waitUntilTimeout = default, + int waitUntilRetries = 0) { - /// - /// Starts the Android application ready for testing. - /// - /// - /// The test class to launch an Android application for. - /// - /// - /// An optional condition of the driver to wait on until it is met. - /// - /// - /// An optional timeout wait on the conditional wait until being true. If not set, the wait will run immediately, and if not valid, will throw an exception. - /// - /// - /// An optional count of retries after a timeout on the wait until condition before accepting the failure. - /// - /// The configured and running application driver. - public static AndroidDriver StartAndroidApp( - this LegerityTestClass testClass, - Func waitUntil = default, - TimeSpan? waitUntilTimeout = default, - int waitUntilRetries = 0) - { - return testClass.StartApp(waitUntil, waitUntilTimeout, waitUntilRetries) as AndroidDriver; - } + return testClass.StartApp(waitUntil, waitUntilTimeout, waitUntilRetries) as AndroidDriver; + } - /// - /// Starts the Android application ready for testing. - /// - /// - /// The test class to launch an Android application for. - /// - /// - /// The optional options to configure the driver with. - /// - /// Settings this will override the if previously set. - /// - /// - /// - /// An optional condition of the driver to wait on until it is met. - /// - /// - /// An optional timeout wait on the conditional wait until being true. If not set, the wait will run immediately, and if not valid, will throw an exception. - /// - /// - /// An optional count of retries after a timeout on the wait until condition before accepting the failure. - /// - /// The configured and running application driver. - public static AndroidDriver StartAndroidApp( - this LegerityTestClass testClass, - AndroidAppManagerOptions options, - Func waitUntil = default, - TimeSpan? waitUntilTimeout = default, - int waitUntilRetries = 0) - { - return testClass.StartApp(options, waitUntil, waitUntilTimeout, waitUntilRetries) as - AndroidDriver; - } + /// + /// Starts the Android application ready for testing. + /// + /// + /// The test class to launch an Android application for. + /// + /// + /// The optional options to configure the driver with. + /// + /// Settings this will override the if previously set. + /// + /// + /// + /// An optional condition of the driver to wait on until it is met. + /// + /// + /// An optional timeout wait on the conditional wait until being true. If not set, the wait will run immediately, and if not valid, will throw an exception. + /// + /// + /// An optional count of retries after a timeout on the wait until condition before accepting the failure. + /// + /// The configured and running application driver. + /// Thrown when the application is null, the session ID is null once initialized, or the driver fails to configure correctly before returning. + /// Thrown when the wait until condition is not met in the allocated timeout period if provided. + /// Thrown when: + /// - The Appium server could not be found when running with true. + /// + public static AndroidDriver StartAndroidApp( + this LegerityTestClass testClass, + AndroidAppManagerOptions options, + Func waitUntil = default, + TimeSpan? waitUntilTimeout = default, + int waitUntilRetries = 0) + { + return testClass.StartApp(options, waitUntil, waitUntilTimeout, waitUntilRetries) as + AndroidDriver; } } \ No newline at end of file diff --git a/src/Legerity.Core/Android/AndroidAppManagerOptions.cs b/src/Legerity.Core/Android/AndroidAppManagerOptions.cs index f61661b0..07971c2e 100644 --- a/src/Legerity.Core/Android/AndroidAppManagerOptions.cs +++ b/src/Legerity.Core/Android/AndroidAppManagerOptions.cs @@ -1,316 +1,315 @@ -namespace Legerity.Android +namespace Legerity.Android; + +using System; +using System.Collections.Generic; +using OpenQA.Selenium.Appium; +using OpenQA.Selenium.Appium.Enums; + +/// +/// Defines a specific for an Android application. +/// +public class AndroidAppManagerOptions : AppiumManagerOptions { - using System; - using System.Collections.Generic; - using OpenQA.Selenium.Appium; - using OpenQA.Selenium.Appium.Enums; + /// + /// Initializes a new instance of the class. + /// + public AndroidAppManagerOptions() + { + } /// - /// Defines a specific for an Android application. + /// Initializes a new instance of the class. /// - public class AndroidAppManagerOptions : AppiumManagerOptions + /// + /// The path of the application under test, e.g. c:/users/legerity/source/myapp/com.instagram.android.apk. + /// + public AndroidAppManagerOptions(string appPath) + : this(null, null, appPath, null, null, null, null) { - /// - /// Initializes a new instance of the class. - /// - public AndroidAppManagerOptions() - { - } + } - /// - /// Initializes a new instance of the class. - /// - /// - /// The path of the application under test, e.g. c:/users/legerity/source/myapp/com.instagram.android.apk. - /// - public AndroidAppManagerOptions(string appPath) - : this(null, null, appPath, null, null, null, null) - { - } + /// + /// Initializes a new instance of the class. + /// + /// + /// The path of the application under test, e.g. c:/users/legerity/source/myapp/com.instagram.android.apk. + /// + /// + /// The additional options to apply to the . + /// + public AndroidAppManagerOptions( + string appPath, + params (string, object)[] additionalOptions) + : this(null, null, appPath, null, null, null, additionalOptions) + { + } - /// - /// Initializes a new instance of the class. - /// - /// - /// The path of the application under test, e.g. c:/users/legerity/source/myapp/com.instagram.android.apk. - /// - /// - /// The additional options to apply to the . - /// - public AndroidAppManagerOptions( - string appPath, - params (string, object)[] additionalOptions) - : this(null, null, appPath, null, null, null, additionalOptions) - { - } + /// + /// Initializes a new instance of the class. + /// + /// + /// The ID of the application under test, e.g. com.instagram.android. + /// + /// + /// The activity of the application to start, e.g. com.instagram.android.activity.MainTabActivity. + /// + public AndroidAppManagerOptions( + string appId, + string appActivity) + : this(appId, appActivity, null, null, null, null, null) + { + } + + /// + /// Initializes a new instance of the class. + /// + /// + /// The ID of the application under test, e.g. com.instagram.android. + /// + /// + /// The activity of the application to start, e.g. com.instagram.android.activity.MainTabActivity. + /// + /// + /// The additional options to apply to the . + /// + public AndroidAppManagerOptions( + string appId, + string appActivity, + params (string, object)[] additionalOptions) + : this(appId, appActivity, null, null, null, null, additionalOptions) + { + } + + /// + /// Initializes a new instance of the class. + /// + /// + /// The ID of the application under test, e.g. com.instagram.android. + /// + /// + /// The activity of the application to start, e.g. com.instagram.android.activity.MainTabActivity. + /// + /// + /// The version of Android to run the application on. + /// + /// + /// The name of the Android device to run the application on. + /// + /// + /// The ID of the Android device to run the application on. + /// + [Obsolete("This constructor will be removed in a future major release. Please use the (string appId, string appActivity) instead and provide optional parameters for configuring for the device needed.")] + public AndroidAppManagerOptions( + string appId, + string appActivity, + string osVersion, + string deviceName, + string deviceId) + : this(appId, appActivity, null, osVersion, deviceName, deviceId, null) + { + } + + /// + /// Initializes a new instance of the class. + /// + /// + /// The ID of the application under test, e.g. com.instagram.android. + /// + /// + /// The activity of the application to start, e.g. com.instagram.android.activity.MainTabActivity. + /// + /// + /// The version of Android to run the application on. + /// + /// + /// The name of the Android device to run the application on. + /// + /// + /// The ID of the Android device to run the application on. + /// + /// + /// The additional options to apply to the . + /// + [Obsolete("This constructor will be removed in a future major release. Please use the (string appId, string appActivity, params (string, object)[] additionalOptions) instead and provide optional parameters for configuring for the device needed.")] + public AndroidAppManagerOptions( + string appId, + string appActivity, + string osVersion, + string deviceName, + string deviceId, + params (string, object)[] additionalOptions) + : this(appId, appActivity, null, osVersion, deviceName, deviceId, additionalOptions) + { + } + + /// + /// Initializes a new instance of the class. + /// + /// + /// The ID of the application under test, e.g. com.instagram.android. + /// + /// + /// The activity of the application to start, e.g. com.instagram.android.activity.MainTabActivity. + /// + /// + /// The path of the application under test, e.g. c:/users/legerity/source/myapp/com.instagram.android.apk. + /// + /// + /// The version of Android to run the application on. + /// + /// + /// The name of the Android device to run the application on. + /// + /// + /// The ID of the Android device to run the application on. + /// + /// + /// The additional options to apply to the . + /// + public AndroidAppManagerOptions( + string appId, + string appActivity, + string appPath, + string osVersion, + string deviceName, + string deviceId, + params (string, object)[] additionalOptions) + { + this.AppId = appId; + this.AppActivity = appActivity; + this.AppPath = appPath; + this.OSVersion = osVersion; + this.DeviceName = deviceName; + this.DeviceId = deviceId; + this.AdditionalOptions = additionalOptions; + } + + /// + /// Gets or sets the ID of the application under test. + /// + public string AppId { get; set; } + + /// + /// Gets or sets the activity of the application to start, e.g. com.instagram.android.activity.MainTabActivity. + /// + public string AppActivity { get; set; } + + /// + /// Gets or sets the path of the application under test, e.g. c:/users/legerity/source/myapp/com.instagram.android.apk. + /// + public string AppPath { get; set; } + + /// + /// Gets or sets the version of Android to run the application on. + /// + public string OSVersion { get; set; } + + /// + /// Gets or sets the name of the Android device to run the application on. + /// + public string DeviceName { get; set; } + + /// + /// Gets or sets the ID of the Android device to run the application on. + /// + public string DeviceId { get; set; } + + /// + /// Gets or sets a value indicating whether to launch the Appium server instance. + /// + public bool LaunchAppiumServer { get; set; } - /// - /// Initializes a new instance of the class. - /// - /// - /// The ID of the application under test, e.g. com.instagram.android. - /// - /// - /// The activity of the application to start, e.g. com.instagram.android.activity.MainTabActivity. - /// - public AndroidAppManagerOptions( - string appId, - string appActivity) - : this(appId, appActivity, null, null, null, null, null) + /// + /// Configures the with the specified additional options. + /// + public override void Configure() + { + base.Configure(); + + this.AppiumOptions.AddAdditionalCapability(MobileCapabilityType.PlatformName, "Android"); + + if (!string.IsNullOrWhiteSpace(this.OSVersion)) { + this.AppiumOptions.AddAdditionalCapability(MobileCapabilityType.PlatformVersion, this.OSVersion); } - /// - /// Initializes a new instance of the class. - /// - /// - /// The ID of the application under test, e.g. com.instagram.android. - /// - /// - /// The activity of the application to start, e.g. com.instagram.android.activity.MainTabActivity. - /// - /// - /// The additional options to apply to the . - /// - public AndroidAppManagerOptions( - string appId, - string appActivity, - params (string, object)[] additionalOptions) - : this(appId, appActivity, null, null, null, null, additionalOptions) + if (!string.IsNullOrWhiteSpace(this.DeviceName)) { + this.AppiumOptions.AddAdditionalCapability(MobileCapabilityType.DeviceName, this.DeviceName); } - /// - /// Initializes a new instance of the class. - /// - /// - /// The ID of the application under test, e.g. com.instagram.android. - /// - /// - /// The activity of the application to start, e.g. com.instagram.android.activity.MainTabActivity. - /// - /// - /// The version of Android to run the application on. - /// - /// - /// The name of the Android device to run the application on. - /// - /// - /// The ID of the Android device to run the application on. - /// - [Obsolete("This constructor will be removed in a future major release. Please use the (string appId, string appActivity) instead and provide optional parameters for configuring for the device needed.")] - public AndroidAppManagerOptions( - string appId, - string appActivity, - string osVersion, - string deviceName, - string deviceId) - : this(appId, appActivity, null, osVersion, deviceName, deviceId, null) + if (!string.IsNullOrWhiteSpace(this.DeviceId)) { + this.AppiumOptions.AddAdditionalCapability(MobileCapabilityType.Udid, this.DeviceId); } - /// - /// Initializes a new instance of the class. - /// - /// - /// The ID of the application under test, e.g. com.instagram.android. - /// - /// - /// The activity of the application to start, e.g. com.instagram.android.activity.MainTabActivity. - /// - /// - /// The version of Android to run the application on. - /// - /// - /// The name of the Android device to run the application on. - /// - /// - /// The ID of the Android device to run the application on. - /// - /// - /// The additional options to apply to the . - /// - [Obsolete("This constructor will be removed in a future major release. Please use the (string appId, string appActivity, params (string, object)[] additionalOptions) instead and provide optional parameters for configuring for the device needed.")] - public AndroidAppManagerOptions( - string appId, - string appActivity, - string osVersion, - string deviceName, - string deviceId, - params (string, object)[] additionalOptions) - : this(appId, appActivity, null, osVersion, deviceName, deviceId, additionalOptions) + if (!string.IsNullOrWhiteSpace(this.AppId)) { + this.AppiumOptions.AddAdditionalCapability("appPackage", this.AppId); } - /// - /// Initializes a new instance of the class. - /// - /// - /// The ID of the application under test, e.g. com.instagram.android. - /// - /// - /// The activity of the application to start, e.g. com.instagram.android.activity.MainTabActivity. - /// - /// - /// The path of the application under test, e.g. c:/users/legerity/source/myapp/com.instagram.android.apk. - /// - /// - /// The version of Android to run the application on. - /// - /// - /// The name of the Android device to run the application on. - /// - /// - /// The ID of the Android device to run the application on. - /// - /// - /// The additional options to apply to the . - /// - public AndroidAppManagerOptions( - string appId, - string appActivity, - string appPath, - string osVersion, - string deviceName, - string deviceId, - params (string, object)[] additionalOptions) + if (!string.IsNullOrWhiteSpace(this.AppActivity)) { - this.AppId = appId; - this.AppActivity = appActivity; - this.AppPath = appPath; - this.OSVersion = osVersion; - this.DeviceName = deviceName; - this.DeviceId = deviceId; - this.AdditionalOptions = additionalOptions; + this.AppiumOptions.AddAdditionalCapability("appActivity", this.AppActivity); } - /// - /// Gets or sets the ID of the application under test. - /// - public string AppId { get; set; } - - /// - /// Gets or sets the activity of the application to start, e.g. com.instagram.android.activity.MainTabActivity. - /// - public string AppActivity { get; set; } - - /// - /// Gets or sets the path of the application under test, e.g. c:/users/legerity/source/myapp/com.instagram.android.apk. - /// - public string AppPath { get; set; } - - /// - /// Gets or sets the version of Android to run the application on. - /// - public string OSVersion { get; set; } - - /// - /// Gets or sets the name of the Android device to run the application on. - /// - public string DeviceName { get; set; } - - /// - /// Gets or sets the ID of the Android device to run the application on. - /// - public string DeviceId { get; set; } - - /// - /// Gets or sets a value indicating whether to launch the Appium server instance. - /// - public bool LaunchAppiumServer { get; set; } - - /// - /// Configures the with the specified additional options. - /// - public override void Configure() + if (!string.IsNullOrWhiteSpace(this.AppPath)) { - base.Configure(); - - this.AppiumOptions.AddAdditionalCapability(MobileCapabilityType.PlatformName, "Android"); - - if (!string.IsNullOrWhiteSpace(this.OSVersion)) - { - this.AppiumOptions.AddAdditionalCapability(MobileCapabilityType.PlatformVersion, this.OSVersion); - } - - if (!string.IsNullOrWhiteSpace(this.DeviceName)) - { - this.AppiumOptions.AddAdditionalCapability(MobileCapabilityType.DeviceName, this.DeviceName); - } + this.AppiumOptions.AddAdditionalCapability("app", this.AppPath); + } + } - if (!string.IsNullOrWhiteSpace(this.DeviceId)) - { - this.AppiumOptions.AddAdditionalCapability(MobileCapabilityType.Udid, this.DeviceId); - } + /// + /// Configures the with the specified additional options. + /// + /// + /// The additional options to apply to the . + /// + public void Configure((string, object)[] additionalOptions) + { + this.AdditionalOptions = additionalOptions; + this.Configure(); + } - if (!string.IsNullOrWhiteSpace(this.AppId)) - { - this.AppiumOptions.AddAdditionalCapability("appPackage", this.AppId); - } + /// Returns a string that represents the current object. + /// A string that represents the current object. + public override string ToString() + { + return $"Platform [Android], {base.ToString()}, {this.GetOptionDetails()}"; + } - if (!string.IsNullOrWhiteSpace(this.AppActivity)) - { - this.AppiumOptions.AddAdditionalCapability("appActivity", this.AppActivity); - } + private string GetOptionDetails() + { + var options = new List(); - if (!string.IsNullOrWhiteSpace(this.AppPath)) - { - this.AppiumOptions.AddAdditionalCapability("app", this.AppPath); - } + if (!string.IsNullOrWhiteSpace(this.AppId)) + { + options.Add($"App ID [{this.AppId}]"); } - /// - /// Configures the with the specified additional options. - /// - /// - /// The additional options to apply to the . - /// - public void Configure((string, object)[] additionalOptions) + if (!string.IsNullOrWhiteSpace(this.AppPath)) { - this.AdditionalOptions = additionalOptions; - this.Configure(); + options.Add($"App Path [{this.AppPath}]"); } - /// Returns a string that represents the current object. - /// A string that represents the current object. - public override string ToString() + if (!string.IsNullOrWhiteSpace(this.DeviceId)) { - return $"Platform [Android], {base.ToString()}, {this.GetOptionDetails()}"; + options.Add($"Device ID [{this.DeviceId}]"); } - private string GetOptionDetails() + if (!string.IsNullOrWhiteSpace(this.DeviceName)) { - var options = new List(); - - if (!string.IsNullOrWhiteSpace(this.AppId)) - { - options.Add($"App ID [{this.AppId}]"); - } - - if (!string.IsNullOrWhiteSpace(this.AppPath)) - { - options.Add($"App Path [{this.AppPath}]"); - } - - if (!string.IsNullOrWhiteSpace(this.DeviceId)) - { - options.Add($"Device ID [{this.DeviceId}]"); - } - - if (!string.IsNullOrWhiteSpace(this.DeviceName)) - { - options.Add($"Device Name [{this.DeviceName}]"); - } + options.Add($"Device Name [{this.DeviceName}]"); + } - if (this.AdditionalOptions != null) + if (this.AdditionalOptions != null) + { + foreach ((string name, object value) in this.AdditionalOptions) { - foreach ((string name, object value) in this.AdditionalOptions) - { - options.Add($"{name} [{value}]"); - } + options.Add($"{name} [{value}]"); } - - return string.Join(", ", options); } + + return string.Join(", ", options); } -} +} \ No newline at end of file diff --git a/src/Legerity.Core/AppManager.cs b/src/Legerity.Core/AppManager.cs index 5e4fabfd..98ca141d 100644 --- a/src/Legerity.Core/AppManager.cs +++ b/src/Legerity.Core/AppManager.cs @@ -1,296 +1,298 @@ -namespace Legerity +namespace Legerity; + +using System; +using System.Collections.Generic; +using Legerity.Android; +using Legerity.Exceptions; +using Legerity.Extensions; +using Legerity.Helpers; +using Legerity.IOS; +using Legerity.Web; +using Legerity.Windows; +using Legerity.Windows.Helpers; +using OpenQA.Selenium; +using OpenQA.Selenium.Appium.Android; +using OpenQA.Selenium.Appium.iOS; +using OpenQA.Selenium.Appium.Windows; +using OpenQA.Selenium.Chrome; +using OpenQA.Selenium.Edge; +using OpenQA.Selenium.Firefox; +using OpenQA.Selenium.IE; +using OpenQA.Selenium.Opera; +using OpenQA.Selenium.Remote; +using OpenQA.Selenium.Safari; + +/// +/// Defines a manager for the application under test. +/// +public static class AppManager { - using System; - using System.Collections.Generic; - using Legerity.Android; - using Legerity.Exceptions; - using Legerity.Extensions; - using Legerity.Helpers; - using Legerity.IOS; - using Legerity.Web; - using Legerity.Windows; - using Legerity.Windows.Helpers; - using OpenQA.Selenium; - using OpenQA.Selenium.Appium.Android; - using OpenQA.Selenium.Appium.iOS; - using OpenQA.Selenium.Appium.Windows; - using OpenQA.Selenium.Chrome; - using OpenQA.Selenium.Edge; - using OpenQA.Selenium.Firefox; - using OpenQA.Selenium.IE; - using OpenQA.Selenium.Opera; - using OpenQA.Selenium.Remote; - using OpenQA.Selenium.Safari; + private static readonly List StartedApps = new(); /// - /// Defines a manager for the application under test. + /// Gets the instance of the started Windows application. /// - public static class AppManager + /// + /// This instance should not be used in parallelized test runs. Instead, use the instance returned by the method. + /// + public static WindowsDriver WindowsApp => App as WindowsDriver; + + /// + /// Gets the instance of the started Android application. + /// + /// + /// This instance should not be used in parallelized test runs. Instead, use the instance returned by the method. + /// + public static AndroidDriver AndroidApp => App as AndroidDriver; + + /// + /// Gets the instance of the started iOS application. + /// + /// + /// This instance should not be used in parallelized test runs. Instead, use the instance returned by the method. + /// + public static IOSDriver IOSApp => App as IOSDriver; + + /// + /// Gets the instance of the started web application. + /// + /// + /// This instance should not be used in parallelized test runs. Instead, use the instance returned by the method. + /// + public static RemoteWebDriver WebApp => App; + + /// + /// Gets or sets the instance of the started application. + /// + /// This could be a , , , or web driver. + /// + /// + /// + /// This instance should not be used in parallelized test runs. Instead, use the instance returned by the method. + /// + public static RemoteWebDriver App { get; set; } + + /// + /// Gets the instances of started applications. + /// + public static IReadOnlyCollection Apps => StartedApps; + + /// + /// Starts the application ready for testing. + /// + /// + /// The options to configure the driver with. + /// + /// + /// An optional condition of the driver to wait on until it is met. + /// + /// + /// An optional timeout wait on the conditional wait until being true. If not set, the wait will run immediately, and if not valid, will throw an exception. + /// + /// + /// An optional count of retries after a timeout on the wait until condition before accepting the failure. + /// + /// + /// Thrown when the application is null, the session ID is null once initialized, or the driver fails to configure correctly before returning. + /// + /// Thrown when the wait until condition is not met in the allocated timeout period if provided. + /// The configured and running application driver. + /// + /// Thrown when: + /// - The Appium server could not be found when running with or true. + /// - The WinAppDriver could not be found when running with true. + /// - The WinAppDriver failed to load when running with true. + /// + public static RemoteWebDriver StartApp( + AppManagerOptions opts, + Func waitUntil = default, + TimeSpan? waitUntilTimeout = default, + int waitUntilRetries = 0) { - private static readonly List StartedApps = new(); - - /// - /// Gets the instance of the started Windows application. - /// - /// - /// This instance should not be used in parallelized test runs. Instead, use the instance returned by the method. - /// - public static WindowsDriver WindowsApp => App as WindowsDriver; - - /// - /// Gets the instance of the started Android application. - /// - /// - /// This instance should not be used in parallelized test runs. Instead, use the instance returned by the method. - /// - public static AndroidDriver AndroidApp => App as AndroidDriver; - - /// - /// Gets the instance of the started iOS application. - /// - /// - /// This instance should not be used in parallelized test runs. Instead, use the instance returned by the method. - /// - public static IOSDriver IOSApp => App as IOSDriver; - - /// - /// Gets the instance of the started web application. - /// - /// - /// This instance should not be used in parallelized test runs. Instead, use the instance returned by the method. - /// - public static RemoteWebDriver WebApp => App; - - /// - /// Gets or sets the instance of the started application. - /// - /// This could be a , , , or web driver. - /// - /// - /// - /// This instance should not be used in parallelized test runs. Instead, use the instance returned by the method. - /// - public static RemoteWebDriver App { get; set; } - - /// - /// Gets or sets the instances of started applications. - /// - public static IReadOnlyCollection Apps => StartedApps; - - /// - /// Starts the application ready for testing. - /// - /// - /// The options to configure the driver with. - /// - /// - /// An optional condition of the driver to wait on until it is met. - /// - /// - /// An optional timeout wait on the conditional wait until being true. If not set, the wait will run immediately, and if not valid, will throw an exception. - /// - /// - /// An optional count of retries after a timeout on the wait until condition before accepting the failure. - /// - /// - /// Thrown if the application is null, the session ID is null once initialized, or the driver fails to configure correctly before returning. - /// - /// Thrown if the Appium server could not be found when running with or true. - /// Thrown if the WinAppDriver could not be found when running with true. - /// Thrown if the WinAppDriver failed to load when running with true. - /// Thrown if the wait until condition is not met in the allocated timeout period if provided. - /// The configured and running application driver. - public static RemoteWebDriver StartApp( - AppManagerOptions opts, - Func waitUntil = default, - TimeSpan? waitUntilTimeout = default, - int waitUntilRetries = 0) + RemoteWebDriver app = null; + + if (opts is AppiumManagerOptions appiumOpts) { - RemoteWebDriver app = null; + appiumOpts.Configure(); + } - if (opts is AppiumManagerOptions appiumOpts) + try + { + switch (opts) { - appiumOpts.Configure(); - } + case WebAppManagerOptions webOpts: + { + app = webOpts.DriverType switch + { + WebAppDriverType.Chrome => new ChromeDriver( + webOpts.DriverUri, + webOpts.DriverOptions as ChromeOptions ?? new ChromeOptions()), + WebAppDriverType.Firefox => new FirefoxDriver( + webOpts.DriverUri, + webOpts.DriverOptions as FirefoxOptions ?? new FirefoxOptions()), + WebAppDriverType.Opera => new OperaDriver( + webOpts.DriverUri, + webOpts.DriverOptions as OperaOptions ?? new OperaOptions()), + WebAppDriverType.Safari => new SafariDriver( + webOpts.DriverUri, + webOpts.DriverOptions as SafariOptions ?? new SafariOptions()), + WebAppDriverType.Edge => new EdgeDriver( + webOpts.DriverUri, + webOpts.DriverOptions as EdgeOptions ?? new EdgeOptions()), + WebAppDriverType.InternetExplorer => new InternetExplorerDriver( + webOpts.DriverUri, + webOpts.DriverOptions as InternetExplorerOptions ?? new InternetExplorerOptions()), + WebAppDriverType.EdgeChromium => new Microsoft.Edge.SeleniumTools.EdgeDriver( + webOpts.DriverUri, + webOpts.DriverOptions as Microsoft.Edge.SeleniumTools.EdgeOptions ?? + new Microsoft.Edge.SeleniumTools.EdgeOptions { UseChromium = true }), + _ => null + }; + + VerifyAppDriver(app, webOpts); + + if (webOpts.Maximize) + { + app.Manage().Window.Maximize(); + } + else + { + app.Manage().Window.Size = webOpts.DesiredSize; + } + + app.Url = webOpts.Url; + break; + } - try - { - switch (opts) + case WindowsAppManagerOptions winOpts: { - case WebAppManagerOptions webOpts: - { - app = webOpts.DriverType switch - { - WebAppDriverType.Chrome => new ChromeDriver( - webOpts.DriverUri, - webOpts.DriverOptions as ChromeOptions ?? new ChromeOptions()), - WebAppDriverType.Firefox => new FirefoxDriver( - webOpts.DriverUri, - webOpts.DriverOptions as FirefoxOptions ?? new FirefoxOptions()), - WebAppDriverType.Opera => new OperaDriver( - webOpts.DriverUri, - webOpts.DriverOptions as OperaOptions ?? new OperaOptions()), - WebAppDriverType.Safari => new SafariDriver( - webOpts.DriverUri, - webOpts.DriverOptions as SafariOptions ?? new SafariOptions()), - WebAppDriverType.Edge => new EdgeDriver( - webOpts.DriverUri, - webOpts.DriverOptions as EdgeOptions ?? new EdgeOptions()), - WebAppDriverType.InternetExplorer => new InternetExplorerDriver( - webOpts.DriverUri, - webOpts.DriverOptions as InternetExplorerOptions ?? new InternetExplorerOptions()), - WebAppDriverType.EdgeChromium => new Microsoft.Edge.SeleniumTools.EdgeDriver( - webOpts.DriverUri, - webOpts.DriverOptions as Microsoft.Edge.SeleniumTools.EdgeOptions ?? - new Microsoft.Edge.SeleniumTools.EdgeOptions { UseChromium = true }), - _ => null - }; - - VerifyAppDriver(app, webOpts); - - if (webOpts.Maximize) - { - app.Manage().Window.Maximize(); - } - else - { - app.Manage().Window.Size = webOpts.DesiredSize; - } - - app.Url = webOpts.Url; - break; - } - - case WindowsAppManagerOptions winOpts: - { - if (winOpts.LaunchWinAppDriver) - { - WinAppDriverHelper.Run(); - } - - app = new WindowsDriver( - new Uri(winOpts.DriverUri), - winOpts.AppiumOptions); - - VerifyAppDriver(app, winOpts); - - if (winOpts.Maximize) - { - app.Manage().Window.Maximize(); - } - - break; - } - - case AndroidAppManagerOptions androidOpts: - { - if (androidOpts.LaunchAppiumServer) - { - AppiumServerHelper.Run(); - } - - app = new AndroidDriver( - new Uri(androidOpts.DriverUri), - androidOpts.AppiumOptions); - - VerifyAppDriver(app, androidOpts); - break; - } - - case IOSAppManagerOptions iosOpts: - { - if (iosOpts.LaunchAppiumServer) - { - AppiumServerHelper.Run(); - } - - app = new IOSDriver(new Uri(iosOpts.DriverUri), iosOpts.AppiumOptions); - - VerifyAppDriver(app, iosOpts); - break; - } - - default: - VerifyAppDriver(null, opts); - break; + if (winOpts.LaunchWinAppDriver) + { + WinAppDriverHelper.Run(); + } + + app = new WindowsDriver( + new Uri(winOpts.DriverUri), + winOpts.AppiumOptions); + + VerifyAppDriver(app, winOpts); + + if (winOpts.Maximize) + { + app.Manage().Window.Maximize(); + } + + break; } - } - catch (Exception ex) - { - app?.Quit(); - if (ex is LegerityException) + case AndroidAppManagerOptions androidOpts: + { + if (androidOpts.LaunchAppiumServer) + { + AppiumServerHelper.Run(); + } + + app = new AndroidDriver( + new Uri(androidOpts.DriverUri), + androidOpts.AppiumOptions); + + VerifyAppDriver(app, androidOpts); + break; + } + + case IOSAppManagerOptions iosOpts: { - throw; + if (iosOpts.LaunchAppiumServer) + { + AppiumServerHelper.Run(); + } + + app = new IOSDriver(new Uri(iosOpts.DriverUri), iosOpts.AppiumOptions); + + VerifyAppDriver(app, iosOpts); + break; } - throw new DriverLoadFailedException(opts, ex); + default: + VerifyAppDriver(null, opts); + break; } + } + catch (Exception ex) + { + app?.Quit(); - if (waitUntil != null) + if (ex is LegerityException le) { - app.WaitUntil(waitUntil, waitUntilTimeout, waitUntilRetries); + throw le; } - App = app; - StartedApps.Add(app); - return app; + throw new DriverLoadFailedException(opts, ex); } - /// - /// Stops the , with an option to stop the running Appium or WinAppDriver server. - /// - /// - /// An optional value indicating whether to stop the running Appium or WinAppDriver server. Default, true. - /// - public static void StopApp(bool stopServer = true) + if (waitUntil != null) { - StopApp(App, stopServer); - App = null; + app.WaitUntil(waitUntil, waitUntilTimeout, waitUntilRetries); } - /// - /// Stops an application driver, with an option to stop the running Appium or WinAppDriver server. - /// - /// - /// The instance to stop running. - /// - /// - /// An optional value indicating whether to stop the running Appium or WinAppDriver server. Default, false. - /// - public static void StopApp(RemoteWebDriver app, bool stopServer = false) - { - app?.Quit(); - StartedApps.Remove(app); + App = app; + StartedApps.Add(app); + return app; + } - if (!stopServer) - { - return; - } + /// + /// Stops the , with an option to stop the running Appium or WinAppDriver server. + /// + /// + /// An optional value indicating whether to stop the running Appium or WinAppDriver server. Default, true. + /// + public static void StopApp(bool stopServer = true) + { + StopApp(App, stopServer); + App = null; + } - WinAppDriverHelper.Stop(); - AppiumServerHelper.Stop(); - } + /// + /// Stops an application driver, with an option to stop the running Appium or WinAppDriver server. + /// + /// + /// The instance to stop running. + /// + /// + /// An optional value indicating whether to stop the running Appium or WinAppDriver server. Default, false. + /// + public static void StopApp(RemoteWebDriver app, bool stopServer = false) + { + app?.Quit(); + StartedApps.Remove(app); - /// - /// Stops all running application drivers. - /// - public static void StopApps() + if (!stopServer) { - StartedApps.ForEach(driver => driver?.Quit()); - StartedApps.Clear(); + return; } - /// Condition. - private static void VerifyAppDriver(RemoteWebDriver app, AppManagerOptions opts) - { - if (app?.SessionId == null) - { - throw new DriverLoadFailedException(opts); - } + WinAppDriverHelper.Stop(); + AppiumServerHelper.Stop(); + } - // Set implicit timeout to 2 seconds to make element search to retry every 500 ms for at most three times. - app.Manage().Timeouts().ImplicitWait = opts.ImplicitWait; + /// + /// Stops all running application drivers. + /// + public static void StopApps() + { + StartedApps.ForEach(driver => driver?.Quit()); + StartedApps.Clear(); + } + + /// Thrown when the driver could not be verified. + private static void VerifyAppDriver(RemoteWebDriver app, AppManagerOptions opts) + { + if (app?.SessionId == null) + { + throw new DriverLoadFailedException(opts); } + + // Set implicit timeout to 2 seconds to make element search to retry every 500 ms for at most three times. + app.Manage().Timeouts().ImplicitWait = opts.ImplicitWait; } } \ No newline at end of file diff --git a/src/Legerity.Core/AppManagerOptions.cs b/src/Legerity.Core/AppManagerOptions.cs index 8166f7da..9659f3aa 100644 --- a/src/Legerity.Core/AppManagerOptions.cs +++ b/src/Legerity.Core/AppManagerOptions.cs @@ -1,39 +1,38 @@ -namespace Legerity -{ - using System; - using OpenQA.Selenium; +namespace Legerity; + +using System; +using OpenQA.Selenium; +/// +/// Defines a base model that represents configuration options for the . +/// +public abstract class AppManagerOptions +{ /// - /// Defines a base model that represents configuration options for the . + /// Gets or sets the URI to the application driver. + /// + /// For native apps, this would be the application driver URL. For web apps, this would be the path to where the driver tool exists. + /// /// - public abstract class AppManagerOptions - { - /// - /// Gets or sets the URI to the application driver. - /// - /// For native apps, this would be the application driver URL. For web apps, this would be the path to where the driver tool exists. - /// - /// - public string DriverUri { get; set; } + public string DriverUri { get; set; } - /// - /// Gets or sets the implicit wait timeout, which is the amount of time the driver should wait when searching for an element if it is not immediately present. - /// - /// By default, the wait time will be 2 seconds. - /// - /// - public TimeSpan ImplicitWait { get; set; } = TimeSpan.FromSeconds(2); + /// + /// Gets or sets the implicit wait timeout, which is the amount of time the driver should wait when searching for an element if it is not immediately present. + /// + /// By default, the wait time will be 2 seconds. + /// + /// + public TimeSpan ImplicitWait { get; set; } = TimeSpan.FromSeconds(2); - /// - /// Gets or sets the additional options to configure the driver. - /// - public DriverOptions DriverOptions { get; set; } + /// + /// Gets or sets the additional options to configure the driver. + /// + public DriverOptions DriverOptions { get; set; } - /// Returns a string that represents the current object. - /// A string that represents the current object. - public override string ToString() - { - return $"Driver URI [{this.DriverUri}]"; - } + /// Returns a string that represents the current object. + /// A string that represents the current object. + public override string ToString() + { + return $"Driver URI [{this.DriverUri}]"; } } \ No newline at end of file diff --git a/src/Legerity.Core/AppiumManagerOptions.cs b/src/Legerity.Core/AppiumManagerOptions.cs index cddf82b4..5da86e58 100644 --- a/src/Legerity.Core/AppiumManagerOptions.cs +++ b/src/Legerity.Core/AppiumManagerOptions.cs @@ -1,46 +1,45 @@ -namespace Legerity +namespace Legerity; + +using OpenQA.Selenium.Appium; + +/// +/// Defines a base model that represents Appium specific configuration options for the . +/// +public abstract class AppiumManagerOptions : AppManagerOptions { - using OpenQA.Selenium.Appium; + /// + /// Gets or sets the additional options to apply to the . + /// + public (string, object)[] AdditionalOptions { get; set; } /// - /// Defines a base model that represents Appium specific configuration options for the . + /// Gets or sets the options to configure the Appium driver. + /// + /// This property is null until the method is called. + /// is called automatically when calling the method. + /// /// - public abstract class AppiumManagerOptions : AppManagerOptions + public AppiumOptions AppiumOptions { - /// - /// Gets or sets the additional options to apply to the . - /// - public (string, object)[] AdditionalOptions { get; set; } + get => this.DriverOptions as AppiumOptions; + set => this.DriverOptions = value; + } - /// - /// Gets or sets the options to configure the Appium driver. - /// - /// This property is null until the method is called. - /// is called automatically when calling the method. - /// - /// - public AppiumOptions AppiumOptions + /// + /// Configures the with the specified additional options. + /// + public virtual void Configure() + { + this.AppiumOptions = new AppiumOptions(); + + if (this.AdditionalOptions == null) { - get => this.DriverOptions as AppiumOptions; - set => this.DriverOptions = value; + return; } - /// - /// Configures the with the specified additional options. - /// - public virtual void Configure() + foreach ((string capabilityName, object capabilityValue) in this.AdditionalOptions) { - this.AppiumOptions = new AppiumOptions(); - - if (this.AdditionalOptions == null) - { - return; - } - - foreach ((string capabilityName, object capabilityValue) in this.AdditionalOptions) - { - this.AppiumOptions.AddAdditionalCapability(capabilityName, capabilityValue); - } + this.AppiumOptions.AddAdditionalCapability(capabilityName, capabilityValue); } } } \ No newline at end of file diff --git a/src/Legerity.Core/ByAll.cs b/src/Legerity.Core/ByAll.cs index c9e29a9a..6dc54a09 100644 --- a/src/Legerity.Core/ByAll.cs +++ b/src/Legerity.Core/ByAll.cs @@ -33,13 +33,13 @@ public ByAll(params By[] locators) /// Finds the first element matching the criteria. /// An object to use to search for the elements. /// The first matching on the current context. - /// Unable to find element using the by locators. + /// Thrown when no element matches the expected locator. public override IWebElement FindElement(ISearchContext context) { ReadOnlyCollection elements = this.FindElements(context); if (elements.Count == 0) { - throw new NoSuchElementException($"Unable to find element using {this}"); + throw new NoSuchElementException($"No element could be located using locator: {this}"); } return elements[0]; diff --git a/src/Legerity.Core/ByExtras.cs b/src/Legerity.Core/ByExtras.cs index 509672a2..6c5dfd60 100644 --- a/src/Legerity.Core/ByExtras.cs +++ b/src/Legerity.Core/ByExtras.cs @@ -1,30 +1,29 @@ -namespace Legerity -{ - using OpenQA.Selenium; +namespace Legerity; + +using OpenQA.Selenium; +/// +/// Defines a collection of extra locator constraints for . +/// +public static class ByExtras +{ /// - /// Defines a collection of extra locator constraints for . + /// Gets a mechanism to find elements by the text content. /// - public static class ByExtras + /// The text to find. + /// A object the driver can use to find elements. + public static By Text(string text) { - /// - /// Gets a mechanism to find elements by the text content. - /// - /// The text to find. - /// A object the driver can use to find elements. - public static By Text(string text) - { - return By.XPath($".//*[text()='{text}']"); - } + return By.XPath($".//*[text()='{text}']"); + } - /// - /// Gets a mechanism to find elements by partial text content. - /// - /// The text to find. - /// A object the driver can use to find elements. - public static By PartialText(string text) - { - return By.XPath($".//*[contains(text(),'{text}')]"); - } + /// + /// Gets a mechanism to find elements by partial text content. + /// + /// The text to find. + /// A object the driver can use to find elements. + public static By PartialText(string text) + { + return By.XPath($".//*[contains(text(),'{text}')]"); } -} +} \ No newline at end of file diff --git a/src/Legerity.Core/ByNested.cs b/src/Legerity.Core/ByNested.cs index 381c8c18..dbe0ad4c 100644 --- a/src/Legerity.Core/ByNested.cs +++ b/src/Legerity.Core/ByNested.cs @@ -30,13 +30,13 @@ public ByNested(params By[] locators) /// Finds the first element matching the criteria. /// An object to use to search for the elements. /// The first matching on the current context. - /// Unable to find element using the by locators. + /// Thrown when no element matches the expected locator. public override IWebElement FindElement(ISearchContext context) { ReadOnlyCollection elements = this.FindElements(context); if (elements.Count == 0) { - throw new NoSuchElementException($"Unable to find element using {this}"); + throw new NoSuchElementException($"No element could be located using locator: {this}"); } return elements[0]; diff --git a/src/Legerity.Core/ElementWrapper`1.cs b/src/Legerity.Core/ElementWrapper`1.cs index d4ac567f..e86c5d1b 100644 --- a/src/Legerity.Core/ElementWrapper`1.cs +++ b/src/Legerity.Core/ElementWrapper`1.cs @@ -1,174 +1,191 @@ -namespace Legerity +namespace Legerity; + +using System; + +using Legerity.Exceptions; + +using OpenQA.Selenium; +using OpenQA.Selenium.Appium; +using OpenQA.Selenium.Support.UI; + +/// +/// Defines a base wrapper for elements to expose platform element logic. +/// +/// +/// The type of . +/// +public abstract class ElementWrapper : IElementWrapper + where TElement : AppiumWebElement { - using System; + private readonly WeakReference elementReference; + + /// + /// Initializes a new instance of the class. + /// + /// + /// The reference. + /// + protected ElementWrapper(TElement element) + { + this.elementReference = new WeakReference(element); + } - using Legerity.Exceptions; + /// Gets the original reference object. + public TElement Element => + this.elementReference is { IsAlive: true } + ? this.elementReference.Target as TElement + : null; - using OpenQA.Selenium; - using OpenQA.Selenium.Appium; - using OpenQA.Selenium.Support.UI; + /// + /// Gets the driver used to find this element. + /// + public IWebDriver ElementDriver => this.Element.WrappedDriver; + + /// + /// Gets a value indicating whether the element is visible. + /// + /// Thrown when an element is no longer valid in the document DOM. + public virtual bool IsVisible => this.Element.Displayed; /// - /// Defines a base wrapper for elements to expose platform element logic. + /// Gets a value indicating whether the element is enabled. /// - /// - /// The type of . - /// - public abstract class ElementWrapper : IElementWrapper - where TElement : AppiumWebElement + /// Thrown when an element is no longer valid in the document DOM. + public virtual bool IsEnabled => this.Element.Enabled; + + /// + /// Clicks the element. + /// + /// Thrown when an element is not enabled. + /// Thrown when an element is not visible. + /// Thrown when an element is no longer valid in the document DOM. + public virtual void Click() { - private readonly WeakReference elementReference; - - /// - /// Initializes a new instance of the class. - /// - /// - /// The reference. - /// - protected ElementWrapper(TElement element) - { - this.elementReference = new WeakReference(element); - } + this.Element.Click(); + } - /// Gets the original reference object. - public TElement Element => - this.elementReference is { IsAlive: true } - ? this.elementReference.Target as TElement - : null; - - /// - /// Gets the driver used to find this element. - /// - public IWebDriver ElementDriver => this.Element.WrappedDriver; - - /// - /// Gets a value indicating whether the element is visible. - /// - public virtual bool IsVisible => this.Element.Displayed; - - /// - /// Gets a value indicating whether the element is enabled. - /// - public virtual bool IsEnabled => this.Element.Enabled; - - /// - /// Clicks the element. - /// - public virtual void Click() - { - this.Element.Click(); - } + /// + /// Gets the value of the specified attribute for this element. + /// + /// The name of the attribute. + /// The attribute's current value if it exists; otherwise, null. + /// Thrown when an element is no longer valid in the document DOM. + public string GetAttribute(string attributeName) + { + return this.Element.GetAttribute(attributeName); + } - /// - /// Gets the value of the specified attribute for this element. - /// - /// The name of the attribute. - /// The attribute's current value if it exists; otherwise, null. - public string GetAttribute(string attributeName) - { - return this.Element.GetAttribute(attributeName); - } + /// + /// Finds a child element by the specified locator. + /// + /// The locator to find a child element by. + /// The . + /// Thrown when no element matches the expected locator. + public AppiumWebElement FindElement(By locator) + { + return this.Element.FindElement(locator); + } - /// - /// Finds a child element by the specified locator. - /// - /// The locator to find a child element by. - /// The . - public AppiumWebElement FindElement(By locator) + /// + /// Determines whether the given element is not shown. + /// + /// + /// The locator for the element to locate. + /// + /// Thrown when the element is shown for the expected locator. + /// Thrown when no element matches the expected locator. + public void VerifyElementNotShown(By locator) + { + try { - return this.Element.FindElement(locator); + this.VerifyElementShown(locator); + throw new ElementShownException(locator.ToString()); } - - /// - /// Determines whether the given element is not shown. - /// - /// - /// The locator for the element to locate. - /// - public void VerifyElementNotShown(By locator) + catch (ElementNotShownException) { - try - { - this.VerifyElementShown(locator); - throw new ElementShownException(locator.ToString()); - } - catch (ElementNotShownException) - { - } } + } - /// - /// Determines whether the given element is shown. - /// - /// - /// The locator for the element to find. - /// - /// Thrown if the element is not shown. - public void VerifyElementShown(By locator) - { - this.VerifyElementShown(locator, null); - } + /// + /// Determines whether the given element is shown. + /// + /// + /// The locator for the element to find. + /// + /// Thrown when an element is not shown for the expected locator. + /// Thrown when no element matches the expected locator. + public void VerifyElementShown(By locator) + { + this.VerifyElementShown(locator, null); + } - /// - /// Determines whether the specified element is shown with the specified timeout. - /// - /// The locator to find a specific element. - /// - /// The amount of time the driver should wait when searching for the if it is not immediately present. - /// - /// Thrown if the element is not shown. - public void VerifyElementShown(By locator, TimeSpan? timeout) + /// + /// Determines whether the specified element is shown with the specified timeout. + /// + /// The locator to find a specific element. + /// + /// The amount of time the driver should wait when searching for the if it is not immediately present. + /// + /// Thrown when an element is not shown for the expected locator. + /// Thrown when no element matches the expected locator. + public void VerifyElementShown(By locator, TimeSpan? timeout) + { + if (timeout == null) { - if (timeout == null) + try { if (this.Element.FindElement(locator) == null) { throw new ElementNotShownException(locator.ToString()); } } - else + catch (NoSuchElementException ex) { - var wait = new WebDriverWait(this.Element.WrappedDriver, timeout.Value); - wait.Until(driver => driver.FindElement(locator) != null); + throw new ElementNotShownException(locator.ToString(), ex); } } - - /// - /// Determines whether the specified elements are shown. - /// - /// - /// The locator for the element to find. - /// - /// Thrown if the elements are not shown. - public void VerifyElementsShown(By locator) + else { - this.VerifyElementsShown(locator, null); + var wait = new WebDriverWait(this.Element.WrappedDriver, timeout.Value); + wait.Until(driver => driver.FindElement(locator) != null); } + } - /// - /// Determines whether the specified elements are shown with the specified timeout. - /// - /// - /// The locator to find a collection of elements. - /// - /// - /// The amount of time the driver should wait when searching for the if it is not immediately present. - /// - /// Thrown if the elements are not shown. - public void VerifyElementsShown(By locator, TimeSpan? timeout) + /// + /// Determines whether the specified elements are shown. + /// + /// + /// The locator for the element to find. + /// + /// Thrown when no elements are shown for the expected locator. + public void VerifyElementsShown(By locator) + { + this.VerifyElementsShown(locator, null); + } + + /// + /// Determines whether the specified elements are shown with the specified timeout. + /// + /// + /// The locator to find a collection of elements. + /// + /// + /// The amount of time the driver should wait when searching for the if it is not immediately present. + /// + /// Thrown when no elements are shown for the expected locator. + public void VerifyElementsShown(By locator, TimeSpan? timeout) + { + if (timeout == null) { - if (timeout == null) - { - if (this.Element.FindElements(locator).Count == 0) - { - throw new ElementNotShownException(locator.ToString()); - } - } - else + if (this.Element.FindElements(locator).Count == 0) { - var wait = new WebDriverWait(this.Element.WrappedDriver, timeout.Value); - wait.Until(driver => driver.FindElements(locator).Count != 0); + throw new ElementsNotShownException(locator.ToString()); } } + else + { + var wait = new WebDriverWait(this.Element.WrappedDriver, timeout.Value); + wait.Until(driver => driver.FindElements(locator).Count != 0); + } } } \ No newline at end of file diff --git a/src/Legerity.Core/Exceptions/AppiumServerLoadFailedException.cs b/src/Legerity.Core/Exceptions/AppiumServerLoadFailedException.cs index 5c92b695..2b561b1b 100644 --- a/src/Legerity.Core/Exceptions/AppiumServerLoadFailedException.cs +++ b/src/Legerity.Core/Exceptions/AppiumServerLoadFailedException.cs @@ -1,19 +1,18 @@ -namespace Legerity.Exceptions -{ - using System; +namespace Legerity.Exceptions; + +using System; +/// +/// Defines an exception for when the Appium sever could not be loaded. +/// +public class AppiumServerLoadFailedException : LegerityException +{ /// - /// Defines an exception for when the Appium sever could not be loaded. + /// Initializes a new instance of the class. /// - public class AppiumServerLoadFailedException : LegerityException + /// The inner exception thrown as a result of the Appium server load failure. + internal AppiumServerLoadFailedException(Exception innerException) + : base("The Appium server could not be loaded", innerException) { - /// - /// Initializes a new instance of the class. - /// - /// The inner exception thrown as a result of the Appium server load failure. - internal AppiumServerLoadFailedException(Exception exception) - : base("The Appium server could not be loaded.", exception) - { - } } } \ No newline at end of file diff --git a/src/Legerity.Core/Exceptions/DriverLoadFailedException.cs b/src/Legerity.Core/Exceptions/DriverLoadFailedException.cs index 59fabbac..6da7f8ec 100644 --- a/src/Legerity.Core/Exceptions/DriverLoadFailedException.cs +++ b/src/Legerity.Core/Exceptions/DriverLoadFailedException.cs @@ -1,40 +1,38 @@ -namespace Legerity.Exceptions -{ - using System; +namespace Legerity.Exceptions; + +using System; +/// +/// Defines an exception thrown if the Appium driver fails to load the requested application. +/// +public class DriverLoadFailedException : LegerityException +{ /// - /// Defines an exception thrown if the Appium driver fails to load the requested application. + /// Initializes a new instance of the class. /// - public class DriverLoadFailedException : LegerityException + /// + /// The app manager options used to initialize the driver. + /// + internal DriverLoadFailedException(AppManagerOptions opts) + : this(opts, null) { - /// - /// Initializes a new instance of the class. - /// - /// - /// The app manager options used to initialize the driver. - /// - internal DriverLoadFailedException(AppManagerOptions opts) - : base($"The application driver could not be initialized with the specified app manager options. {opts}") - { - this.AppManagerOptions = opts; - } - - /// - /// Initializes a new instance of the class. - /// - /// - /// The app manager options used to initialize the driver. - /// - /// The exception that is the cause of the current exception, or a null reference (Nothing in Visual Basic) if no inner exception is specified. - internal DriverLoadFailedException(AppManagerOptions opts, Exception innerException) - : base($"The application driver could not be initialized with the specified app manager options. {opts}", innerException) - { - this.AppManagerOptions = opts; - } + } - /// - /// Gets the app manager options used to initialize the driver. - /// - internal AppManagerOptions AppManagerOptions { get; } + /// + /// Initializes a new instance of the class. + /// + /// + /// The app manager options used to initialize the driver. + /// + /// The exception that is the cause of the current exception, or a null reference (Nothing in Visual Basic) if no inner exception is specified. + internal DriverLoadFailedException(AppManagerOptions opts, Exception innerException) + : base($"The application driver could not be initialized with the specified app manager options: {opts}", innerException) + { + this.AppManagerOptions = opts; } + + /// + /// Gets the app manager options used to initialize the driver. + /// + internal AppManagerOptions AppManagerOptions { get; } } \ No newline at end of file diff --git a/src/Legerity.Core/Exceptions/DriverNotInitializedException.cs b/src/Legerity.Core/Exceptions/DriverNotInitializedException.cs index f0012715..338c8859 100644 --- a/src/Legerity.Core/Exceptions/DriverNotInitializedException.cs +++ b/src/Legerity.Core/Exceptions/DriverNotInitializedException.cs @@ -1,17 +1,16 @@ -namespace Legerity.Exceptions +namespace Legerity.Exceptions; + +/// +/// Defines an exception thrown when an attempt is made to access a driver which has not been initialized. +/// +public class DriverNotInitializedException : LegerityException { /// - /// Defines an exception thrown when an attempt is made to access a driver which has not been initialized. + /// Initializes a new instance of the class. /// - public class DriverNotInitializedException : LegerityException + /// The message that describes the error. + internal DriverNotInitializedException(string message) + : base(message) { - /// - /// Initializes a new instance of the class. - /// - /// The message that describes the error. - internal DriverNotInitializedException(string message) - : base(message) - { - } } } \ No newline at end of file diff --git a/src/Legerity.Core/Exceptions/ElementNotShownException.cs b/src/Legerity.Core/Exceptions/ElementNotShownException.cs index 0889413a..f4552a01 100644 --- a/src/Legerity.Core/Exceptions/ElementNotShownException.cs +++ b/src/Legerity.Core/Exceptions/ElementNotShownException.cs @@ -1,25 +1,45 @@ -namespace Legerity.Exceptions +namespace Legerity.Exceptions; + +using System; + +/// +/// Defines an exception for when an element is not shown. +/// +public class ElementNotShownException : LegerityException { /// - /// Defines an exception for when an element is not shown. + /// Initializes a new instance of the class. /// - public class ElementNotShownException : LegerityException + /// + /// The locator used to locate the element. + /// + public ElementNotShownException(string locator) + : this(locator, null) { - /// - /// Initializes a new instance of the class. - /// - /// - /// The name of the element that was not shown. - /// - public ElementNotShownException(string elementName) - : base($"'{elementName}' is not shown when it should") - { - this.ElementName = elementName; - } + } - /// - /// Gets the name of the element that was not shown. - /// - public string ElementName { get; } + /// + /// Initializes a new instance of the class. + /// + /// + /// The locator used to locate the element. + /// + /// The exception that is the cause of the current exception, or a null reference (Nothing in Visual Basic) if no inner exception is specified. + public ElementNotShownException(string locator, Exception innerException) + : base($"No element could be located using locator: {locator}", innerException) + { + this.ElementName = locator; + this.Locator = locator; } + + /// + /// Gets the locator used to locate the element. + /// + public string Locator { get; } + + /// + /// Gets the name of the element that was not shown. + /// + [Obsolete("ElementName will be removed in a future major release. Please use the Locator instead.")] + public string ElementName { get; } } \ No newline at end of file diff --git a/src/Legerity.Core/Exceptions/ElementShownException.cs b/src/Legerity.Core/Exceptions/ElementShownException.cs index 74a10ba3..bd1fcec3 100644 --- a/src/Legerity.Core/Exceptions/ElementShownException.cs +++ b/src/Legerity.Core/Exceptions/ElementShownException.cs @@ -1,25 +1,45 @@ -namespace Legerity.Exceptions +namespace Legerity.Exceptions; + +using System; + +/// +/// Defines an exception for when an element is shown when it shouldn't be. +/// +public class ElementShownException : LegerityException { /// - /// Defines an exception for when an element is shown when it shouldn't be. + /// Initializes a new instance of the class. /// - public class ElementShownException : LegerityException + /// + /// The locator used to locate the element. + /// + public ElementShownException(string locator) + : this(locator, null) { - /// - /// Initializes a new instance of the class. - /// - /// - /// The name of the element that was shown. - /// - public ElementShownException(string elementName) - : base($"'{elementName}' is shown when it shouldn't") - { - this.ElementName = elementName; - } + } - /// - /// Gets the name of the element that was shown. - /// - public string ElementName { get; } + /// + /// Initializes a new instance of the class. + /// + /// + /// The locator used to locate the element. + /// + /// The exception that is the cause of the current exception, or a null reference (Nothing in Visual Basic) if no inner exception is specified. + public ElementShownException(string locator, Exception innerException) + : base($"An element was located using locator: {locator}", innerException) + { + this.ElementName = locator; + this.Locator = locator; } + + /// + /// Gets the locator used to locate the element. + /// + public string Locator { get; } + + /// + /// Gets the name of the element that was shown. + /// + [Obsolete("ElementName will be removed in a future major release. Please use the Locator instead.")] + public string ElementName { get; } } \ No newline at end of file diff --git a/src/Legerity.Core/Exceptions/ElementsNotShownException.cs b/src/Legerity.Core/Exceptions/ElementsNotShownException.cs new file mode 100644 index 00000000..705402ba --- /dev/null +++ b/src/Legerity.Core/Exceptions/ElementsNotShownException.cs @@ -0,0 +1,38 @@ +namespace Legerity.Exceptions; + +using System; + +/// +/// Defines an exception for when expected elements are not shown. +/// +public class ElementsNotShownException : LegerityException +{ + /// + /// Initializes a new instance of the class. + /// + /// + /// The locator used to locate the element. + /// + public ElementsNotShownException(string locator) + : this(locator, null) + { + } + + /// + /// Initializes a new instance of the class. + /// + /// + /// The locator used to locate the element. + /// + /// The exception that is the cause of the current exception, or a null reference (Nothing in Visual Basic) if no inner exception is specified. + public ElementsNotShownException(string locator, Exception innerException) + : base($"No elements could be located using locator: {locator}", innerException) + { + this.Locator = locator; + } + + /// + /// Gets the locator used to locate the elements. + /// + public string Locator { get; } +} \ No newline at end of file diff --git a/src/Legerity.Core/Exceptions/LegerityException.cs b/src/Legerity.Core/Exceptions/LegerityException.cs index 5e61f897..34b4fa6a 100644 --- a/src/Legerity.Core/Exceptions/LegerityException.cs +++ b/src/Legerity.Core/Exceptions/LegerityException.cs @@ -1,36 +1,34 @@ -namespace Legerity -{ - using System; +namespace Legerity; + +using System; +/// +/// Defines a framework specific base exception. +/// +public class LegerityException : Exception +{ /// - /// Defines a framework specific base exception. + /// Initializes a new instance of the class. /// - public class LegerityException : Exception + internal LegerityException() { - /// - /// Initializes a new instance of the class. - /// - internal LegerityException() - : base() - { - } + } - /// - /// Initializes a new instance of the class with a specified error message. - /// The message that describes the error. - internal LegerityException(string message) - : base(message) - { - } + /// + /// Initializes a new instance of the class with a specified error message. + /// The message that describes the error. + internal LegerityException(string message) + : base(message) + { + } - /// - /// Initializes a new instance of the class with a specified error message and a reference to the inner exception that is the cause of this exception. - /// - /// The error message that explains the reason for the exception. - /// The exception that is the cause of the current exception, or a null reference (Nothing in Visual Basic) if no inner exception is specified. - internal LegerityException(string message, Exception innerException) - : base(message, innerException) - { - } + /// + /// Initializes a new instance of the class with a specified error message and a reference to the inner exception that is the cause of this exception. + /// + /// The error message that explains the reason for the exception. + /// The exception that is the cause of the current exception, or a null reference (Nothing in Visual Basic) if no inner exception is specified. + internal LegerityException(string message, Exception innerException) + : base(message, innerException) + { } } \ No newline at end of file diff --git a/src/Legerity.Core/Exceptions/PageNotShownException.cs b/src/Legerity.Core/Exceptions/PageNotShownException.cs index b9efebf7..38f25a50 100644 --- a/src/Legerity.Core/Exceptions/PageNotShownException.cs +++ b/src/Legerity.Core/Exceptions/PageNotShownException.cs @@ -1,25 +1,24 @@ -namespace Legerity.Exceptions +namespace Legerity.Exceptions; + +/// +/// Defines an exception for when a page is not shown. +/// +public class PageNotShownException : LegerityException { /// - /// Defines an exception for when a page is not shown. + /// Initializes a new instance of the class. /// - public class PageNotShownException : LegerityException + /// + /// The name of the page that was not shown. + /// + internal PageNotShownException(string pageName) + : base($"No page could be located for page: {pageName}") { - /// - /// Initializes a new instance of the class. - /// - /// - /// The name of the page that was not shown. - /// - internal PageNotShownException(string pageName) - : base($"Unable to verify on page '{pageName}'") - { - this.PageName = pageName; - } - - /// - /// Gets the name of the page that was not shown. - /// - public string PageName { get; } + this.PageName = pageName; } + + /// + /// Gets the name of the page that was not shown. + /// + public string PageName { get; } } \ No newline at end of file diff --git a/src/Legerity.Core/Extensions/AttributeExtensions.cs b/src/Legerity.Core/Extensions/AttributeExtensions.cs index e8a2725d..bba328dd 100644 --- a/src/Legerity.Core/Extensions/AttributeExtensions.cs +++ b/src/Legerity.Core/Extensions/AttributeExtensions.cs @@ -1,35 +1,36 @@ -namespace Legerity.Extensions -{ - using OpenQA.Selenium; - using OpenQA.Selenium.Remote; +namespace Legerity.Extensions; + +using OpenQA.Selenium; +using OpenQA.Selenium.Remote; +/// +/// Defines a collection of extensions for retrieving element attributes. +/// +public static class AttributeExtensions +{ /// - /// Defines a collection of extensions for retrieving element attributes. + /// Retrieves the Name attribute from the specified element. /// - public static class AttributeExtensions + /// The to retrieve a Name from. + /// The Name of the element. + /// Thrown when an element is no longer valid in the document DOM. + public static string GetName(this IWebElement element) { - /// - /// Retrieves the Name attribute from the specified element. - /// - /// The to retrieve a Name from. - /// The Name of the element. - public static string GetName(this IWebElement element) - { - return element.GetAttribute("Name"); - } + return element.GetAttribute("Name"); + } - /// - /// Retrieves the Name attribute from the specified element. - /// - /// - /// The type of . - /// - /// The to retrieve a Name from. - /// The Name of the element. - public static string GetName(this IElementWrapper element) - where TElement : IWebElement - { - return GetName(element.Element); - } + /// + /// Retrieves the Name attribute from the specified element. + /// + /// + /// The type of . + /// + /// The to retrieve a Name from. + /// The Name of the element. + /// Thrown when an element is no longer valid in the document DOM. + public static string GetName(this IElementWrapper element) + where TElement : IWebElement + { + return GetName(element.Element); } -} +} \ No newline at end of file diff --git a/src/Legerity.Core/Extensions/DriverExtensions.cs b/src/Legerity.Core/Extensions/DriverExtensions.cs index 87116087..404d32a4 100644 --- a/src/Legerity.Core/Extensions/DriverExtensions.cs +++ b/src/Legerity.Core/Extensions/DriverExtensions.cs @@ -18,6 +18,7 @@ public static class DriverExtensions /// The remote web driver. /// The locator to find the element. /// A . + /// Thrown when no element matches the expected locator. public static RemoteWebElement FindWebElement(this RemoteWebDriver driver, By locator) { return driver.FindElement(locator) as RemoteWebElement; @@ -40,6 +41,7 @@ public static ReadOnlyCollection FindWebElements(this RemoteWe /// The remote web driver. /// The text to find. /// A . + /// Thrown when no element matches the expected locator. public static IWebElement FindElementByText(this RemoteWebDriver driver, string text) { return driver.FindElement(ByExtras.Text(text)); @@ -62,6 +64,7 @@ public static ReadOnlyCollection FindElementsByText(this RemoteWebD /// The remote web driver. /// The partial text to find. /// A . + /// Thrown when no element matches the expected locator. public static IWebElement FindElementByPartialText(this RemoteWebDriver driver, string text) { return driver.FindElement(ByExtras.PartialText(text)); @@ -109,6 +112,7 @@ public static ReadOnlyCollection GetAllChildElements(this RemoteWeb /// An optional count of retries after a timeout before accepting the failure. /// The optional exception handler thrown if an error occurs as a result of timeout. /// Whether the wait was a success. + /// Thrown when the callback throws an exception. public static bool TryWaitUntil( this IWebDriver appDriver, Func condition, @@ -138,7 +142,7 @@ public static bool TryWaitUntil( /// An optional count of retries after a timeout before accepting the failure. /// The type of expected result from the wait condition. /// The of the wait until operation. - /// Thrown if the condition is not met in the allocated timeout period. + /// Thrown when the condition is not met in the allocated timeout period. public static TResult WaitUntil( this IWebDriver appDriver, Func condition, diff --git a/src/Legerity.Core/Extensions/ElementExtensions.cs b/src/Legerity.Core/Extensions/ElementExtensions.cs index df266236..a547237b 100644 --- a/src/Legerity.Core/Extensions/ElementExtensions.cs +++ b/src/Legerity.Core/Extensions/ElementExtensions.cs @@ -18,6 +18,7 @@ public static class ElementExtensions /// /// The element to determine the rect for. /// The elements bounding rectangle. + /// Thrown when an element is no longer valid in the document DOM. public static Rectangle GetBoundingRect(this IWebElement element) { Point location = element.Location; @@ -31,6 +32,7 @@ public static Rectangle GetBoundingRect(this IWebElement element) /// The remote web element. /// The locator to find the element. /// A . + /// Thrown when no element matches the expected locator. public static RemoteWebElement FindWebElement(this IWebElement element, By locator) { return element.FindElement(locator) as RemoteWebElement; @@ -53,6 +55,7 @@ public static ReadOnlyCollection FindWebElements(this IWebElem /// The remote web element. /// The text to find. /// A . + /// Thrown when no element matches the expected locator. public static IWebElement FindElementByText(this IWebElement element, string text) { return element.FindElement(ByExtras.Text(text)); @@ -75,6 +78,7 @@ public static ReadOnlyCollection FindElementsByText(this IWebElemen /// The remote web element. /// The partial text to find. /// A . + /// Thrown when no element matches the expected locator. public static IWebElement FindElementByPartialText(this IWebElement element, string text) { return element.FindElement(ByExtras.PartialText(text)); @@ -110,6 +114,7 @@ public static ReadOnlyCollection GetAllChildElements(this IWebEleme /// An optional count of retries after a timeout before accepting the failure. /// The optional exception handler thrown if an error occurs as a result of timeout. /// Whether the wait was a success. + /// Thrown when the callback throws an exception. public static bool TryWaitUntil( this RemoteWebElement element, Func condition, @@ -139,7 +144,8 @@ public static bool TryWaitUntil( /// An optional count of retries after a timeout before accepting the failure. /// The type of expected result from the wait condition. /// The of the wait until operation. - /// Thrown if the condition is not met in the allocated timeout period. + /// Thrown when the condition is not met in the allocated timeout period. + /// Thrown when the callback throws an exception. public static TResult WaitUntil( this RemoteWebElement element, Func condition, diff --git a/src/Legerity.Core/Extensions/ElementWrapperExtensions.cs b/src/Legerity.Core/Extensions/ElementWrapperExtensions.cs index e9ec476c..8c9b68dd 100644 --- a/src/Legerity.Core/Extensions/ElementWrapperExtensions.cs +++ b/src/Legerity.Core/Extensions/ElementWrapperExtensions.cs @@ -20,6 +20,7 @@ public static class ElementWrapperExtensions /// /// The element to determine the rect for. /// The elements bounding rectangle. + /// Thrown when an element is no longer valid in the document DOM. public static Rectangle GetBoundingRect(this IElementWrapper element) where TElement : IWebElement { @@ -35,6 +36,7 @@ public static Rectangle GetBoundingRect(this IElementWrapper /// The remote web element. /// The locator to find the element. /// A . + /// Thrown when no element matches the expected locator. public static RemoteWebElement FindWebElement(this IElementWrapper element, By locator) where TElement : IWebElement { @@ -66,6 +68,7 @@ public static ReadOnlyCollection FindWebElements( /// The remote web element. /// The text to find. /// A . + /// Thrown when no element matches the expected locator. public static IWebElement FindElementByText(this IElementWrapper element, string text) where TElement : IWebElement { @@ -97,6 +100,7 @@ public static ReadOnlyCollection FindElementsByText( /// The remote web element. /// The partial text to find. /// A . + /// Thrown when no element matches the expected locator. public static IWebElement FindElementByPartialText( this IElementWrapper element, string text) @@ -147,6 +151,7 @@ public static ReadOnlyCollection GetAllChildElements( /// The type of . /// The type of expected result from the wait condition. /// Whether the wait was a success. + /// Thrown when the callback throws an exception. public static bool TryWaitUntil( this IElementWrapper element, Func, TResult> condition, @@ -178,7 +183,8 @@ public static bool TryWaitUntil( /// The type of . /// The type of expected result from the wait condition. /// The of the wait until operation. - /// Thrown if the condition is not met in the allocated timeout period. + /// Thrown when the condition is not met in the allocated timeout period. + /// Thrown when the callback throws an exception. public static TResult WaitUntil( this IElementWrapper element, Func, TResult> condition, diff --git a/src/Legerity.Core/Extensions/PageExtensions.cs b/src/Legerity.Core/Extensions/PageExtensions.cs index ad5cfd79..306c0994 100644 --- a/src/Legerity.Core/Extensions/PageExtensions.cs +++ b/src/Legerity.Core/Extensions/PageExtensions.cs @@ -20,6 +20,7 @@ public static class PageExtensions /// The optional exception handler thrown if an error occurs as a result of timeout. /// The type of . /// Whether the wait was a success and the instance of the page. + /// Thrown when the callback throws an exception. public static (bool success, TPage page) TryWaitUntil( this TPage page, Func condition, @@ -51,7 +52,8 @@ public static (bool success, TPage page) TryWaitUntil( /// The type of . /// The type of expected result from the wait condition. /// The instance of the page. - /// Thrown if the condition is not met in the allocated timeout period. + /// Thrown when the condition is not met in the allocated timeout period. + /// Thrown when the callback throws an exception. public static TPage WaitUntil( this TPage page, Func condition, diff --git a/src/Legerity.Core/Extensions/StringExtensions.cs b/src/Legerity.Core/Extensions/StringExtensions.cs index f57eb262..3f969f86 100644 --- a/src/Legerity.Core/Extensions/StringExtensions.cs +++ b/src/Legerity.Core/Extensions/StringExtensions.cs @@ -1,53 +1,52 @@ -namespace Legerity.Extensions -{ - using System.Globalization; - using System.Linq; +namespace Legerity.Extensions; + +using System.Globalization; +using System.Linq; +/// +/// Defines a collection of extensions for . +/// +public static class StringExtensions +{ /// - /// Defines a collection of extensions for . + /// Determines whether the specified value contains the comparison value by the specified culture and comparison option. /// - public static class StringExtensions + /// + /// The value to check contains the value. + /// + /// + /// The value that should be contained within the . + /// + /// + /// The culture for comparison. + /// + /// + /// The comparison option. + /// + /// + /// True if the contains the value; otherwise, false. + /// + public static bool Contains( + this string value, + string contains, + CultureInfo culture, + CompareOptions compareOption) { - /// - /// Determines whether the specified value contains the comparison value by the specified culture and comparison option. - /// - /// - /// The value to check contains the value. - /// - /// - /// The value that should be contained within the . - /// - /// - /// The culture for comparison. - /// - /// - /// The comparison option. - /// - /// - /// True if the contains the value; otherwise, false. - /// - public static bool Contains( - this string value, - string contains, - CultureInfo culture, - CompareOptions compareOption) + if (value == null || contains == null) { - if (value == null || contains == null) - { - return false; - } - - return culture.CompareInfo.IndexOf(value, contains, compareOption) >= 0; + return false; } - /// - /// Removes unicode characters from the specified string. - /// - /// The string to remove unicode characters from. - /// The string with unicode characters removed. - public static string RemoveUnicodeCharacters(this string value) - { - return value == null ? null : new string(value.Where(c => c < 128).ToArray()); - } + return culture.CompareInfo.IndexOf(value, contains, compareOption) >= 0; + } + + /// + /// Removes unicode characters from the specified string. + /// + /// The string to remove unicode characters from. + /// The string with unicode characters removed. + public static string RemoveUnicodeCharacters(this string value) + { + return value == null ? null : new string(value.Where(c => c < 128).ToArray()); } } \ No newline at end of file diff --git a/src/Legerity.Core/Helpers/AppiumServerHelper.cs b/src/Legerity.Core/Helpers/AppiumServerHelper.cs index d1147d5f..1ceb3bd9 100644 --- a/src/Legerity.Core/Helpers/AppiumServerHelper.cs +++ b/src/Legerity.Core/Helpers/AppiumServerHelper.cs @@ -1,53 +1,52 @@ -namespace Legerity.Helpers +namespace Legerity.Helpers; + +using System; +using Legerity.Exceptions; +using OpenQA.Selenium.Appium.Service; + +/// +/// Defines a helper class for launching a local Appium server. +/// +public static class AppiumServerHelper { - using System; - using Legerity.Exceptions; - using OpenQA.Selenium.Appium.Service; + private static AppiumLocalService AppiumServer { get; set; } /// - /// Defines a helper class for launching a local Appium server. + /// Loads an instance of the Appium server process. /// - public static class AppiumServerHelper + /// Thrown when the Appium server fails to load. + public static void Run() { - private static AppiumLocalService AppiumServer { get; set; } - - /// - /// Loads an instance of the Appium server process. - /// - /// Thrown if the Appium server failed to load. - public static void Run() + if (AppiumServer is { IsRunning: true }) { - if (AppiumServer is { IsRunning: true }) - { - return; - } + return; + } - try - { - AppiumServer = AppiumLocalService.BuildDefaultService(); - AppiumServer.Start(); - } - catch (Exception ex) - { - throw new AppiumServerLoadFailedException(ex); - } + try + { + AppiumServer = AppiumLocalService.BuildDefaultService(); + AppiumServer.Start(); } + catch (Exception ex) + { + throw new AppiumServerLoadFailedException(ex); + } + } - /// - /// Stops the running instance of the WinAppDriver process. - /// - public static void Stop() + /// + /// Stops the running instance of the WinAppDriver process. + /// + public static void Stop() + { + try { - try - { - if (AppiumServer is { IsRunning: true }) - { - AppiumServer.Dispose(); - } - } - catch (Exception) + if (AppiumServer is { IsRunning: true }) { + AppiumServer.Dispose(); } } + catch (Exception) + { + } } } \ No newline at end of file diff --git a/src/Legerity.Core/Helpers/WaitUntilConditions.cs b/src/Legerity.Core/Helpers/WaitUntilConditions.cs index aaed2bc2..f6719c49 100644 --- a/src/Legerity.Core/Helpers/WaitUntilConditions.cs +++ b/src/Legerity.Core/Helpers/WaitUntilConditions.cs @@ -63,6 +63,7 @@ public static Func UrlContains(string url) /// /// The locator to find the element. /// True if the element exists; otherwise, false. + /// Thrown when no element matches the expected locator. public static Func ElementExists(By locator) { return driver => driver.FindElement(locator) != null; @@ -77,6 +78,7 @@ public static Func ElementExists(By locator) /// The type of . /// The locator to find the element. /// True if the element exists; otherwise, false. + /// Thrown when no element matches the expected locator. public static Func ElementExistsInElement(By locator) where TElement : IWebElement { @@ -92,6 +94,7 @@ public static Func ElementExistsInElement(By locator) /// The type of . /// The locator to find the element. /// True if the element exists; otherwise, false. + /// Thrown when no element matches the expected locator. public static Func, bool> ElementExistsInElementWrapper(By locator) where TElement : IWebElement { @@ -107,10 +110,11 @@ public static Func, bool> ElementExistsInElementWrappe /// The type of . /// The locator to find the element. /// True if the element exists; otherwise, false. + /// Thrown when no element matches the expected locator. public static Func ElementExistsInPage(By locator) where TPage : BasePage { - return page => page.App.FindElement(locator) != null; + return page => page.FindElement(locator) != null; } /// @@ -118,6 +122,7 @@ public static Func ElementExistsInPage(By locator) /// /// The locator to find the element. /// True if the element is visible; otherwise, false. + /// Thrown when no element matches the expected locator. public static Func ElementIsVisible(By locator) { return driver => @@ -139,6 +144,7 @@ public static Func ElementIsVisible(By locator) /// The type of . /// The locator to find the element. /// True if the element is visible; otherwise, false. + /// Thrown when no element matches the expected locator. public static Func ElementIsVisibleInElement(By locator) where TElement : IWebElement { @@ -161,6 +167,7 @@ public static Func ElementIsVisibleInElement(By locato /// The type of . /// The locator to find the element. /// True if the element is visible; otherwise, false. + /// Thrown when no element matches the expected locator. public static Func, bool> ElementIsVisibleInElementWrapper(By locator) where TElement : IWebElement { @@ -183,6 +190,7 @@ public static Func, bool> ElementIsVisibleInElementWra /// The type of . /// The locator to find the element. /// True if the element is visible; otherwise, false. + /// Thrown when no element matches the expected locator. public static Func ElementIsVisibleInPage(By locator) where TPage : BasePage { @@ -190,7 +198,7 @@ public static Func ElementIsVisibleInPage(By locator) { try { - return page.App.FindElement(locator).Displayed; + return page.FindElement(locator).Displayed; } catch (StaleElementReferenceException) { @@ -294,7 +302,7 @@ public static Func ElementIsNotVisibleInPage(By locator) { try { - return !page.App.FindElement(locator).Displayed; + return !page.FindElement(locator).Displayed; } catch (NoSuchElementException) { @@ -334,6 +342,8 @@ public static Func FrameAvailableToSwitchTo(string frame /// /// The locator of the frame to switch to. /// The for the frame that has been switched to. + /// Thrown when no element matches the expected locator. + /// Thrown when an element is no longer valid. public static Func FrameAvailableToSwitchTo(By frameLocator) { return driver => diff --git a/src/Legerity.Core/IElementWrapper.cs b/src/Legerity.Core/IElementWrapper.cs index 05bc4d65..0d0a03ef 100644 --- a/src/Legerity.Core/IElementWrapper.cs +++ b/src/Legerity.Core/IElementWrapper.cs @@ -1,89 +1,88 @@ -namespace Legerity +namespace Legerity; + +using System; +using OpenQA.Selenium; + +/// +/// Defines an interface for a Selenium/Appium element wrapper. +/// +/// +/// The type of . +/// +public interface IElementWrapper + where TElement : IWebElement { - using System; - using OpenQA.Selenium; + /// Gets the original reference object. + TElement Element { get; } /// - /// Defines an interface for a Selenium/Appium element wrapper. + /// Gets the driver used to find this element. /// - /// - /// The type of . - /// - public interface IElementWrapper - where TElement : IWebElement - { - /// Gets the original reference object. - TElement Element { get; } - - /// - /// Gets the driver used to find this element. - /// - IWebDriver ElementDriver { get; } + IWebDriver ElementDriver { get; } - /// - /// Gets a value indicating whether the element is visible. - /// - bool IsVisible { get; } + /// + /// Gets a value indicating whether the element is visible. + /// + bool IsVisible { get; } - /// - /// Gets a value indicating whether the element is enabled. - /// - bool IsEnabled { get; } + /// + /// Gets a value indicating whether the element is enabled. + /// + bool IsEnabled { get; } - /// - /// Clicks the element. - /// - void Click(); + /// + /// Clicks the element. + /// + void Click(); - /// - /// Gets the value of the specified attribute for this element. - /// - /// The name of the attribute. - /// The attribute's current value if it exists; otherwise, null. - string GetAttribute(string attributeName); + /// + /// Gets the value of the specified attribute for this element. + /// + /// The name of the attribute. + /// The attribute's current value if it exists; otherwise, null. + string GetAttribute(string attributeName); - /// - /// Determines whether the given element is shown. - /// - /// - /// The locator for the element to find. - /// - void VerifyElementShown(By locator); + /// + /// Determines whether the given element is shown. + /// + /// + /// The locator for the element to find. + /// + void VerifyElementShown(By locator); - /// - /// Determines whether the specified element is shown with the specified timeout. - /// - /// The locator to find a specific element. - /// - /// The amount of time the driver should wait when searching for the if it is not immediately present. - /// - void VerifyElementShown(By locator, TimeSpan? timeout); + /// + /// Determines whether the specified element is shown with the specified timeout. + /// + /// The locator to find a specific element. + /// + /// The amount of time the driver should wait when searching for the if it is not immediately present. + /// + void VerifyElementShown(By locator, TimeSpan? timeout); - /// - /// Determines whether the given element is not shown. - /// - /// - /// The locator for the element to locate. - /// - void VerifyElementNotShown(By locator); + /// + /// Determines whether the given element is not shown. + /// + /// + /// The locator for the element to locate. + /// + void VerifyElementNotShown(By locator); - /// - /// Determines whether the specified elements are shown. - /// - /// - /// The locator for the element to find. - /// - void VerifyElementsShown(By locator); + /// + /// Determines whether the specified elements are shown. + /// + /// + /// The locator for the element to find. + /// + void VerifyElementsShown(By locator); - /// - /// Determines whether the specified elements are shown with the specified timeout. - /// - /// - /// The locator to find a collection of elements. - /// - /// - /// The amount of time the driver should wait when searching for the if it is not immediately present. - /// - void VerifyElementsShown(By locator, TimeSpan? timeout); - } -} + /// + /// Determines whether the specified elements are shown with the specified timeout. + /// + /// + /// The locator to find a collection of elements. + /// + /// + /// The amount of time the driver should wait when searching for the if it is not immediately present. + /// + void VerifyElementsShown(By locator, TimeSpan? timeout); +} \ No newline at end of file diff --git a/src/Legerity.Core/IOS/IOSAppManagerOptions.cs b/src/Legerity.Core/IOS/IOSAppManagerOptions.cs index e5301e3c..d002e4e3 100644 --- a/src/Legerity.Core/IOS/IOSAppManagerOptions.cs +++ b/src/Legerity.Core/IOS/IOSAppManagerOptions.cs @@ -1,168 +1,167 @@ -namespace Legerity.IOS +namespace Legerity.IOS; + +using System.Collections.Generic; +using OpenQA.Selenium.Appium; +using OpenQA.Selenium.Appium.Enums; + +/// +/// Defines a specific for an iOS application. +/// +public class IOSAppManagerOptions : AppiumManagerOptions { - using System.Collections.Generic; - using OpenQA.Selenium.Appium; - using OpenQA.Selenium.Appium.Enums; + /// + /// Initializes a new instance of the class. + /// + public IOSAppManagerOptions() + { + } /// - /// Defines a specific for an iOS application. + /// Initializes a new instance of the class. /// - public class IOSAppManagerOptions : AppiumManagerOptions + /// + /// The ID of the application under test, e.g. com.instagram.ios. + /// + /// + /// The version of iOS to run the application on. + /// + /// + /// The name of the iOS device to run the application on. + /// + /// + /// The ID of the Android device to run the application on. + /// + public IOSAppManagerOptions(string appId, string osVersion, string deviceName, string deviceId) + : this(appId, osVersion, deviceName, deviceId, null) { - /// - /// Initializes a new instance of the class. - /// - public IOSAppManagerOptions() - { - } + } - /// - /// Initializes a new instance of the class. - /// - /// - /// The ID of the application under test, e.g. com.instagram.ios. - /// - /// - /// The version of iOS to run the application on. - /// - /// - /// The name of the iOS device to run the application on. - /// - /// - /// The ID of the Android device to run the application on. - /// - public IOSAppManagerOptions(string appId, string osVersion, string deviceName, string deviceId) - : this(appId, osVersion, deviceName, deviceId, null) - { - } + /// + /// Initializes a new instance of the class. + /// + /// + /// The ID of the application under test, e.g. com.instagram.ios. + /// + /// + /// The version of iOS to run the application on. + /// + /// + /// The name of the iOS device to run the application on. + /// + /// + /// The ID of the iOS device to run the application on. + /// + /// + /// The additional options to apply to the . + /// + public IOSAppManagerOptions( + string appId, + string osVersion, + string deviceName, + string deviceId, + params (string, object)[] additionalOptions) + { + this.AppId = appId; + this.OSVersion = osVersion; + this.DeviceName = deviceName; + this.DeviceId = deviceId; + this.AdditionalOptions = additionalOptions; + } - /// - /// Initializes a new instance of the class. - /// - /// - /// The ID of the application under test, e.g. com.instagram.ios. - /// - /// - /// The version of iOS to run the application on. - /// - /// - /// The name of the iOS device to run the application on. - /// - /// - /// The ID of the iOS device to run the application on. - /// - /// - /// The additional options to apply to the . - /// - public IOSAppManagerOptions( - string appId, - string osVersion, - string deviceName, - string deviceId, - params (string, object)[] additionalOptions) - { - this.AppId = appId; - this.OSVersion = osVersion; - this.DeviceName = deviceName; - this.DeviceId = deviceId; - this.AdditionalOptions = additionalOptions; - } + /// + /// Gets or sets the ID of the application under test. + /// + public string AppId { get; set; } + + /// + /// Gets or sets the version of iOS to run the application on. + /// + public string OSVersion { get; set; } + + /// + /// Gets or sets the name of the iOS device to run the application on. + /// + public string DeviceName { get; set; } + + /// + /// Gets or sets the ID of the iOS device to run the application on. + /// + public string DeviceId { get; set; } + + /// + /// Gets or sets the name of the automation tool to use to run the application. Defaults to XCUITest. + /// + /// If a value is provided in the additional options, this value will override it. + /// + /// + public string AutomationName { get; set; } = "XCUITest"; - /// - /// Gets or sets the ID of the application under test. - /// - public string AppId { get; set; } - - /// - /// Gets or sets the version of iOS to run the application on. - /// - public string OSVersion { get; set; } - - /// - /// Gets or sets the name of the iOS device to run the application on. - /// - public string DeviceName { get; set; } - - /// - /// Gets or sets the ID of the iOS device to run the application on. - /// - public string DeviceId { get; set; } - - /// - /// Gets or sets the name of the automation tool to use to run the application. Defaults to XCUITest. - /// - /// If a value is provided in the additional options, this value will override it. - /// - /// - public string AutomationName { get; set; } = "XCUITest"; - - /// - /// Gets or sets a value indicating whether to launch the Appium server instance. - /// - public bool LaunchAppiumServer { get; set; } - - /// - /// Configures the with the specified additional options. - /// - public override void Configure() + /// + /// Gets or sets a value indicating whether to launch the Appium server instance. + /// + public bool LaunchAppiumServer { get; set; } + + /// + /// Configures the with the specified additional options. + /// + public override void Configure() + { + base.Configure(); + + this.AppiumOptions.AddAdditionalCapability(MobileCapabilityType.PlatformName, "iOS"); + this.AppiumOptions.AddAdditionalCapability(MobileCapabilityType.PlatformVersion, this.OSVersion); + this.AppiumOptions.AddAdditionalCapability(MobileCapabilityType.DeviceName, this.DeviceName); + this.AppiumOptions.AddAdditionalCapability(MobileCapabilityType.Udid, this.DeviceId); + this.AppiumOptions.AddAdditionalCapability(MobileCapabilityType.App, this.AppId); + this.AppiumOptions.AddAdditionalCapability(MobileCapabilityType.AutomationName, this.AutomationName); + } + + /// + /// Configures the with the specified additional options. + /// + /// + /// The additional options to apply to the . + /// + public void Configure((string, object)[] additionalOptions) + { + this.AdditionalOptions = additionalOptions; + this.Configure(); + } + + /// Returns a string that represents the current object. + /// A string that represents the current object. + public override string ToString() + { + return $"Platform [IOS], {base.ToString()}, {this.GetOptionDetails()}"; + } + + private string GetOptionDetails() + { + var options = new List(); + + if (!string.IsNullOrWhiteSpace(this.AppId)) { - base.Configure(); - - this.AppiumOptions.AddAdditionalCapability(MobileCapabilityType.PlatformName, "iOS"); - this.AppiumOptions.AddAdditionalCapability(MobileCapabilityType.PlatformVersion, this.OSVersion); - this.AppiumOptions.AddAdditionalCapability(MobileCapabilityType.DeviceName, this.DeviceName); - this.AppiumOptions.AddAdditionalCapability(MobileCapabilityType.Udid, this.DeviceId); - this.AppiumOptions.AddAdditionalCapability(MobileCapabilityType.App, this.AppId); - this.AppiumOptions.AddAdditionalCapability(MobileCapabilityType.AutomationName, this.AutomationName); + options.Add($"App ID [{this.AppId}]"); } - /// - /// Configures the with the specified additional options. - /// - /// - /// The additional options to apply to the . - /// - public void Configure((string, object)[] additionalOptions) + if (!string.IsNullOrWhiteSpace(this.DeviceId)) { - this.AdditionalOptions = additionalOptions; - this.Configure(); + options.Add($"Device ID [{this.DeviceId}]"); } - /// Returns a string that represents the current object. - /// A string that represents the current object. - public override string ToString() + if (!string.IsNullOrWhiteSpace(this.DeviceName)) { - return $"Platform [IOS], {base.ToString()}, {this.GetOptionDetails()}"; + options.Add($"Device Name [{this.DeviceName}]"); } - private string GetOptionDetails() + if (this.AdditionalOptions != null) { - var options = new List(); - - if (!string.IsNullOrWhiteSpace(this.AppId)) + foreach ((string name, object value) in this.AdditionalOptions) { - options.Add($"App ID [{this.AppId}]"); + options.Add($"{name} [{value}]"); } - - if (!string.IsNullOrWhiteSpace(this.DeviceId)) - { - options.Add($"Device ID [{this.DeviceId}]"); - } - - if (!string.IsNullOrWhiteSpace(this.DeviceName)) - { - options.Add($"Device Name [{this.DeviceName}]"); - } - - if (this.AdditionalOptions != null) - { - foreach ((string name, object value) in this.AdditionalOptions) - { - options.Add($"{name} [{value}]"); - } - } - - return string.Join(", ", options); } + + return string.Join(", ", options); } -} +} \ No newline at end of file diff --git a/src/Legerity.Core/LegerityTestClass.cs b/src/Legerity.Core/LegerityTestClass.cs index d925494b..d5425379 100644 --- a/src/Legerity.Core/LegerityTestClass.cs +++ b/src/Legerity.Core/LegerityTestClass.cs @@ -1,174 +1,190 @@ -namespace Legerity +namespace Legerity; + +using System; +using System.Collections.Generic; +using Android; +using Exceptions; +using IOS; +using OpenQA.Selenium; +using OpenQA.Selenium.Appium.Android; +using OpenQA.Selenium.Appium.iOS; +using OpenQA.Selenium.Appium.Windows; +using OpenQA.Selenium.Remote; +using Windows; + +/// +/// Defines a base class for running tests with the Legerity framework. +/// +public abstract class LegerityTestClass { - using System; - using System.Collections.Generic; - using OpenQA.Selenium; - using OpenQA.Selenium.Appium.Android; - using OpenQA.Selenium.Appium.iOS; - using OpenQA.Selenium.Appium.Windows; - using OpenQA.Selenium.Remote; + private readonly List apps = new(); /// - /// Defines a base class for running tests with the Legerity framework. + /// Initializes a new instance of the class. + /// + /// The will need to be set before calling . + /// /// - public abstract class LegerityTestClass + protected LegerityTestClass() { - private readonly List apps = new(); - - /// - /// Initializes a new instance of the class. - /// - /// The will need to be set before calling . - /// - /// - protected LegerityTestClass() - { - } + } - /// - /// Initializes a new instance of the class with application launch option. - /// - /// The application launch options. - protected LegerityTestClass(AppManagerOptions options) - { - this.Options = options; - } + /// + /// Initializes a new instance of the class with application launch option. + /// + /// The application launch options. + protected LegerityTestClass(AppManagerOptions options) + { + this.Options = options; + } - /// - /// Gets the instance of the started application. - /// - /// This could be a , , , or web driver. - /// - /// - /// - /// This instance should not be used in parallelized test runs. Instead, use the instance returned by the method. - /// - protected RemoteWebDriver App { get; private set; } - - /// - /// Gets or sets the instances of started applications. - /// - /// - /// This is useful for accessing drivers in parallelized tests. - /// - protected IReadOnlyCollection Apps => this.apps; - - /// - /// Gets or sets the model that represents the configuration options for the . - /// - protected AppManagerOptions Options { get; set; } - - /// - /// Starts the application ready for testing. - /// - /// - /// An optional condition of the driver to wait on until it is met. - /// - /// - /// An optional timeout wait on the conditional wait until being true. If not set, the wait will run immediately, and if not valid, will throw an exception. - /// - /// - /// An optional count of retries after a timeout on the wait until condition before accepting the failure. - /// - /// The configured and running application driver. - public virtual RemoteWebDriver StartApp( - Func waitUntil = default, - TimeSpan? waitUntilTimeout = default, - int waitUntilRetries = 0) - { - return this.StartApp(this.Options, waitUntil, waitUntilTimeout, waitUntilRetries); - } + /// + /// Gets the instance of the started application. + /// + /// This could be a , , , or web driver. + /// + /// + /// + /// This instance should not be used in parallelized test runs. Instead, use the instance returned by the or method. + /// + protected RemoteWebDriver App { get; private set; } - /// - /// Starts the application ready for testing. - /// - /// - /// The optional options to configure the driver with. - /// - /// Settings this will override the if previously set. - /// - /// - /// - /// An optional condition of the driver to wait on until it is met. - /// - /// - /// An optional timeout wait on the conditional wait until being true. If not set, the wait will run immediately, and if not valid, will throw an exception. - /// - /// - /// An optional count of retries after a timeout on the wait until condition before accepting the failure. - /// - /// The configured and running application driver. - public virtual RemoteWebDriver StartApp( - AppManagerOptions options, - Func waitUntil = default, - TimeSpan? waitUntilTimeout = default, - int waitUntilRetries = 0) - { - if (options != default && this.Options != options) - { - this.Options = options; - } - - RemoteWebDriver app = AppManager.StartApp(this.Options, waitUntil, waitUntilTimeout, waitUntilRetries); - this.App = app; - this.apps.Add(app); - return app; - } + /// + /// Gets or sets the instances of started applications. + /// + /// + /// This is useful for accessing drivers in parallelized tests. + /// + protected IReadOnlyCollection Apps => this.apps; + /// + /// Gets or sets the model that represents the configuration options for the . + /// + protected AppManagerOptions Options { get; set; } - /// - /// Stops the and any running Appium or WinAppDriver server. - /// - public virtual void StopApp() - { - this.StopApp(true); - } + /// + /// Starts the application ready for testing. + /// + /// + /// An optional condition of the driver to wait on until it is met. + /// + /// + /// An optional timeout wait on the conditional wait until being true. If not set, the wait will run immediately, and if not valid, will throw an exception. + /// + /// + /// An optional count of retries after a timeout on the wait until condition before accepting the failure. + /// + /// The configured and running application driver. + /// Thrown when the wait until condition is not met in the allocated timeout period if provided. + /// Thrown when the application is null, the session ID is null once initialized, or the driver fails to configure correctly before returning. + /// Thrown when: + /// - The Appium server could not be found when running with or true. + /// - The WinAppDriver could not be found when running with true. + /// - The WinAppDriver failed to load when running with true. + /// + public virtual RemoteWebDriver StartApp( + Func waitUntil = default, + TimeSpan? waitUntilTimeout = default, + int waitUntilRetries = 0) + { + return this.StartApp(this.Options, waitUntil, waitUntilTimeout, waitUntilRetries); + } - /// - /// Stops the , with an option to stop the running Appium or WinAppDriver server. - /// - /// - /// An optional value indicating whether to stop the running Appium or WinAppDriver server. - /// - public virtual void StopApp(bool stopServer) + /// + /// Starts the application ready for testing. + /// + /// + /// The optional options to configure the driver with. + /// + /// Settings this will override the if previously set. + /// + /// + /// + /// An optional condition of the driver to wait on until it is met. + /// + /// + /// An optional timeout wait on the conditional wait until being true. If not set, the wait will run immediately, and if not valid, will throw an exception. + /// + /// + /// An optional count of retries after a timeout on the wait until condition before accepting the failure. + /// + /// The configured and running application driver. + /// Thrown when the application is null, the session ID is null once initialized, or the driver fails to configure correctly before returning. + /// Thrown when: + /// - The Appium server could not be found when running with or true. + /// - The WinAppDriver could not be found when running with true. + /// - The WinAppDriver failed to load when running with true. + /// + /// Thrown when the wait until condition is not met in the allocated timeout period if provided. + public virtual RemoteWebDriver StartApp( + AppManagerOptions options, + Func waitUntil = default, + TimeSpan? waitUntilTimeout = default, + int waitUntilRetries = 0) + { + if (options != default && this.Options != options) { - this.StopApp(this.App, stopServer); + this.Options = options; } - /// - /// Stops an application, with an option to stop the running Appium or WinAppDriver server. - /// - /// - /// The instance to stop running. - /// - /// - /// An optional value indicating whether to stop the running Appium or WinAppDriver server. Default, false. - /// - public virtual void StopApp(RemoteWebDriver app, bool stopServer = false) - { - this.StopAppManagerApp(app, stopServer, true); - } + RemoteWebDriver app = AppManager.StartApp(this.Options, waitUntil, waitUntilTimeout, waitUntilRetries); + this.App = app; + this.apps.Add(app); + return app; + } - /// - /// Stops all running application drivers, with an option to stop the running Appium or WinAppDriver server. - /// - /// - /// An optional value indicating whether to stop the running Appium or WinAppDriver server. Default, true. - /// - public virtual void StopApps(bool stopServer = true) - { - this.apps.ForEach(app => this.StopAppManagerApp(app, stopServer, false)); - this.apps.Clear(); - } + /// + /// Stops the and any running Appium or WinAppDriver server. + /// + public virtual void StopApp() + { + this.StopApp(true); + } - private void StopAppManagerApp(RemoteWebDriver app, bool stopServer, bool removeApp) - { - if (removeApp) - { - this.apps.Remove(app); - } + /// + /// Stops the , with an option to stop the running Appium or WinAppDriver server. + /// + /// + /// An optional value indicating whether to stop the running Appium or WinAppDriver server. + /// + public virtual void StopApp(bool stopServer) + { + this.StopApp(this.App, stopServer); + } + + /// + /// Stops an application, with an option to stop the running Appium or WinAppDriver server. + /// + /// + /// The instance to stop running. + /// + /// + /// An optional value indicating whether to stop the running Appium or WinAppDriver server. Default, false. + /// + public virtual void StopApp(RemoteWebDriver app, bool stopServer = false) + { + this.StopAppManagerApp(app, stopServer, true); + } + + /// + /// Stops all running application drivers, with an option to stop the running Appium or WinAppDriver server. + /// + /// + /// An optional value indicating whether to stop the running Appium or WinAppDriver server. Default, true. + /// + public virtual void StopApps(bool stopServer = true) + { + this.apps.ForEach(app => this.StopAppManagerApp(app, stopServer, false)); + this.apps.Clear(); + } - AppManager.StopApp(app, stopServer); + private void StopAppManagerApp(RemoteWebDriver app, bool stopServer, bool removeApp) + { + if (removeApp) + { + this.apps.Remove(app); } + + AppManager.StopApp(app, stopServer); } } \ No newline at end of file diff --git a/src/Legerity.Core/Pages/BasePage.cs b/src/Legerity.Core/Pages/BasePage.cs index a9861342..296f18df 100644 --- a/src/Legerity.Core/Pages/BasePage.cs +++ b/src/Legerity.Core/Pages/BasePage.cs @@ -1,298 +1,310 @@ -namespace Legerity.Pages +namespace Legerity.Pages; + +using System; +using System.Collections.ObjectModel; +using System.Linq; +using Legerity.Exceptions; +using Legerity.Extensions; +using OpenQA.Selenium; +using OpenQA.Selenium.Appium.Android; +using OpenQA.Selenium.Appium.iOS; +using OpenQA.Selenium.Appium.Windows; +using OpenQA.Selenium.Remote; +using OpenQA.Selenium.Support.UI; + +/// +/// Defines a base page for creating tests following the page object pattern. +/// +public abstract class BasePage { - using System; - using System.Collections.ObjectModel; - using System.Linq; - using Legerity.Exceptions; - using Legerity.Extensions; - using OpenQA.Selenium; - using OpenQA.Selenium.Appium.Android; - using OpenQA.Selenium.Appium.iOS; - using OpenQA.Selenium.Appium.Windows; - using OpenQA.Selenium.Remote; - using OpenQA.Selenium.Support.UI; + /// + /// Initializes a new instance of the class using the instance that verifies the page has loaded within 2 seconds. + /// + /// Thrown when AppManager.StartApp() has not been called. + /// Thrown when the page is not shown in 2 seconds. + /// Thrown when no element matches the expected locator. + protected BasePage() + : this(AppManager.App, TimeSpan.FromSeconds(2)) + { + } /// - /// Defines a base page for creating tests following the page object pattern. + /// Initializes a new instance of the class using a instance that verifies the page has loaded within 2 seconds. /// - public abstract class BasePage + /// + /// The instance of the started application driver that will be used to drive the page interaction. + /// + /// Thrown when AppManager.StartApp() has not been called. + /// Thrown when the page is not shown in 2 seconds. + /// Thrown when no element matches the expected locator. + protected BasePage(RemoteWebDriver app) + : this(app, TimeSpan.FromSeconds(2)) { - /// - /// Initializes a new instance of the class using the instance that verifies the page has loaded within 2 seconds. - /// - /// Thrown if AppManager.StartApp() has not been called. - /// Thrown if the page is not shown in 2 seconds. - protected BasePage() - : this(AppManager.App, TimeSpan.FromSeconds(2)) - { - } + } - /// - /// Initializes a new instance of the class using a instance that verifies the page has loaded within 2 seconds. - /// - /// - /// The instance of the started application driver that will be used to drive the page interaction. - /// - /// Thrown if AppManager.StartApp() has not been called. - /// Thrown if the page is not shown in 2 seconds. - protected BasePage(RemoteWebDriver app) - : this(app, TimeSpan.FromSeconds(2)) - { - } + /// + /// Initializes a new instance of the class using the instance that verifies the page has loaded within the given timeout. + /// + /// + /// The amount of time the driver should wait when searching for the if it is not immediately present. + /// + /// Thrown when AppManager.StartApp() has not been called. + /// Thrown when the page is not shown in the given timeout. + /// Thrown when no element matches the expected locator. + protected BasePage(TimeSpan? traitTimeout) + : this(AppManager.App, traitTimeout) + { + } - /// - /// Initializes a new instance of the class using the instance that verifies the page has loaded within the given timeout. - /// - /// - /// The amount of time the driver should wait when searching for the if it is not immediately present. - /// - /// Thrown if AppManager.StartApp() has not been called. - /// Thrown if the page is not shown in the given timeout. - protected BasePage(TimeSpan? traitTimeout) - : this(AppManager.App, traitTimeout) - { - } + /// + /// Initializes a new instance of the class using a instance that verifies the page has loaded within the given timeout. + /// + /// + /// The instance of the started application driver that will be used to drive the page interaction. + /// + /// + /// The amount of time the driver should wait when searching for the if it is not immediately present. + /// + /// Thrown when AppManager.StartApp() has not been called. + /// Thrown when the page is not shown in the given timeout. + /// Thrown when no element matches the expected locator. + protected BasePage(RemoteWebDriver app, TimeSpan? traitTimeout) + { + this.App = app; + this.WaitTimeout = traitTimeout ?? TimeSpan.FromSeconds(2); + this.VerifyPageShown(this.WaitTimeout); + } - /// - /// Initializes a new instance of the class using a instance that verifies the page has loaded within the given timeout. - /// - /// - /// The instance of the started application driver that will be used to drive the page interaction. - /// - /// - /// The amount of time the driver should wait when searching for the if it is not immediately present. - /// - /// Thrown if AppManager.StartApp() has not been called. - /// Thrown if the page is not shown in the given timeout. - protected BasePage(RemoteWebDriver app, TimeSpan? traitTimeout) - { - this.App = app; - this.WaitTimeout = traitTimeout ?? TimeSpan.FromSeconds(2); - this.VerifyPageShown(this.WaitTimeout); - } + /// + /// Gets the instance of the started application. + /// + /// The instance serves as base for the drivers and can be referenced for basic Selenium functions. + /// + /// + /// This could be a , , , or web driver. + /// + /// + public RemoteWebDriver App { get; } - /// - /// Gets the instance of the started application. - /// - /// The instance serves as base for the drivers and can be referenced for basic Selenium functions. - /// - /// - /// This could be a , , , or web driver. - /// - /// - public RemoteWebDriver App { get; } + /// + /// Gets or sets the amount of time the driver should wait when searching for elements if they are not immediately present. + /// + public TimeSpan WaitTimeout { get; set; } - /// - /// Gets or sets the amount of time the driver should wait when searching for elements if they are not immediately present. - /// - public TimeSpan WaitTimeout { get; set; } + /// + /// Gets the instance of the started Windows application. + /// + protected WindowsDriver WindowsApp => this.App as WindowsDriver; - /// - /// Gets the instance of the started Windows application. - /// - protected WindowsDriver WindowsApp => this.App as WindowsDriver; + /// + /// Gets the instance of the started Android application. + /// + protected AndroidDriver AndroidApp => this.App as AndroidDriver; - /// - /// Gets the instance of the started Android application. - /// - protected AndroidDriver AndroidApp => this.App as AndroidDriver; + /// + /// Gets the instance of the started iOS application. + /// + protected IOSDriver IOSApp => this.App as IOSDriver; - /// - /// Gets the instance of the started iOS application. - /// - protected IOSDriver IOSApp => this.App as IOSDriver; + /// + /// Gets the instance of the started web application. + /// + protected RemoteWebDriver WebApp => this.App; - /// - /// Gets the instance of the started web application. - /// - protected RemoteWebDriver WebApp => this.App; + /// + /// Gets a given trait of the page to verify that the page is in view. + /// + protected abstract By Trait { get; } - /// - /// Gets a given trait of the page to verify that the page is in view. - /// - protected abstract By Trait { get; } + /// + /// Finds the first element in the page that matches the locator. + /// + /// The locator to find the element. + /// A . + /// Thrown when no element matches the expected locator. + public RemoteWebElement FindElement(By locator) + { + return this.App.FindWebElement(locator); + } - /// - /// Finds the first element in the page that matches the locator. - /// - /// The locator to find the element. - /// A . - public RemoteWebElement FindElement(By locator) - { - return this.App.FindWebElement(locator); - } + /// + /// Finds all the elements in the page that matches the locator. + /// + /// The locator to find the elements. + /// A readonly collection of . + public ReadOnlyCollection FindElements(By locator) + { + return this.App.FindWebElements(locator); + } - /// - /// Finds all the elements in the page that matches the locator. - /// - /// The locator to find the elements. - /// A readonly collection of . - public ReadOnlyCollection FindElements(By locator) - { - return this.App.FindWebElements(locator); - } + /// + /// Finds the first element in the page that matches the specified XPath. + /// + /// The XPath to find the element. + /// A . + /// Thrown when no element matches the expected locator. + public RemoteWebElement FindElementByXPath(string xpath) + { + return this.App.FindElementByXPath(xpath) as RemoteWebElement; + } - /// - /// Finds the first element in the page that matches the specified XPath. - /// - /// The XPath to find the element. - /// A . - public RemoteWebElement FindElementByXPath(string xpath) - { - return this.App.FindElementByXPath(xpath) as RemoteWebElement; - } + /// + /// Finds all the elements in the page that matches the specified XPath. + /// + /// The XPath to find the elements. + /// A readonly collection of . + public ReadOnlyCollection FindElementsByXPath(string xpath) + { + return this.App.FindElementsByXPath(xpath).Cast().ToList().AsReadOnly(); + } - /// - /// Finds all the elements in the page that matches the specified XPath. - /// - /// The XPath to find the elements. - /// A readonly collection of . - public ReadOnlyCollection FindElementsByXPath(string xpath) - { - return this.App.FindElementsByXPath(xpath).Cast().ToList().AsReadOnly(); - } + /// + /// Finds the first element in the page that matches the specified ID. + /// + /// The ID of the element. + /// A . + /// Thrown when no element matches the expected locator. + public RemoteWebElement FindElementById(string id) + { + return this.App.FindElementById(id) as RemoteWebElement; + } - /// - /// Finds the first element in the page that matches the specified ID. - /// - /// The ID of the element. - /// A . - public RemoteWebElement FindElementById(string id) - { - return this.App.FindElementById(id) as RemoteWebElement; - } + /// + /// Finds the first of element in the page that matches the specified name. + /// + /// The name of the element. + /// A . + /// Thrown when no element matches the expected locator. + public RemoteWebElement FindElementByName(string name) + { + return this.App.FindElementByName(name) as RemoteWebElement; + } - /// - /// Finds the first of element in the page that matches the specified name. - /// - /// The name of the element. - /// A . - public RemoteWebElement FindElementByName(string name) - { - return this.App.FindElementByName(name) as RemoteWebElement; - } + /// + /// Determines whether the current page is shown immediately. + /// + /// Thrown when AppManager.StartApp() has not been called. + /// Thrown when the page is not shown. + /// Thrown when no element matches the expected locator. + public void VerifyPageShown() + { + this.VerifyPageShown(null); + } - /// - /// Determines whether the current page is shown immediately. - /// - /// Thrown if AppManager.StartApp() has not been called. - /// Thrown if the page is not shown. - public void VerifyPageShown() + /// + /// Determines whether the current page is shown with the specified timeout. + /// + /// + /// The amount of time the driver should wait when searching for the if it is not immediately present. + /// + /// Thrown when AppManager.StartApp() has not been called. + /// Thrown when the page is not shown. + /// Thrown when no element matches the expected locator. + public void VerifyPageShown(TimeSpan? timeout) + { + if (this.App == null) { - this.VerifyPageShown(null); + throw new DriverNotInitializedException( + $"An app driver has not been initialized. Call 'AppManager.StartApp()' with an instance of an {nameof(AppManagerOptions)} to setup for testing."); } - /// - /// Determines whether the current page is shown with the specified timeout. - /// - /// - /// The amount of time the driver should wait when searching for the if it is not immediately present. - /// - /// Thrown if AppManager.StartApp() has not been called. - /// Thrown if the page is not shown. - public void VerifyPageShown(TimeSpan? timeout) + if (timeout == null) { - if (this.App == null) - { - throw new DriverNotInitializedException( - $"An app driver has not been initialized. Call 'AppManager.StartApp()' with an instance of an {nameof(AppManagerOptions)} to setup for testing."); - } - - if (timeout == null) + if (this.App != null && this.App.FindElement(this.Trait) == null) { - if (this.App != null && this.App.FindElement(this.Trait) == null) - { - throw new PageNotShownException(this.GetType().Name); - } + throw new PageNotShownException(this.GetType().Name); } - else + } + else + { + if (this.App != null) { - if (this.App != null) - { - AttemptWaitForDriverElement(this.Trait, timeout.Value, this.App); - } + AttemptWaitForDriverElement(this.Trait, timeout.Value, this.App); } } + } - /// - /// Determines whether the given element is shown. - /// - /// - /// The locator for the element to find. - /// - /// Thrown if AppManager.StartApp() has not been called. - /// Thrown if the element is not shown. - public void VerifyElementShown(By locator) + /// + /// Determines whether the given element is shown. + /// + /// + /// The locator for the element to find. + /// + /// Thrown when AppManager.StartApp() has not been called. + /// Thrown when the element is not shown. + /// Thrown when no element matches the expected locator. + public void VerifyElementShown(By locator) + { + this.VerifyElementShown(locator, null); + } + + /// + /// Determines whether the given element is shown with the specified timeout. + /// + /// + /// The locator for the element to find. + /// + /// + /// The amount of time the driver should wait when searching for the element if it is not immediately present. + /// + /// Thrown when AppManager.StartApp() has not been called. + /// Thrown when the element is not shown. + /// Thrown when no element matches the expected locator. + public void VerifyElementShown(By locator, TimeSpan? timeout) + { + if (this.App == null) { - this.VerifyElementShown(locator, null); + throw new DriverNotInitializedException( + $"An app driver has not been initialized. Call 'AppManager.StartApp()' with an instance of an {nameof(AppManagerOptions)} to setup for testing."); } - /// - /// Determines whether the given element is shown with the specified timeout. - /// - /// - /// The locator for the element to find. - /// - /// - /// The amount of time the driver should wait when searching for the element if it is not immediately present. - /// - /// Thrown if AppManager.StartApp() has not been called. - /// Thrown if the element is not shown. - public void VerifyElementShown(By locator, TimeSpan? timeout) + if (timeout == null) { - if (this.App == null) + if (this.App != null && this.App.FindElement(locator) == null) { - throw new DriverNotInitializedException( - $"An app driver has not been initialized. Call 'AppManager.StartApp()' with an instance of an {nameof(AppManagerOptions)} to setup for testing."); - } - - if (timeout == null) - { - if (this.App != null && this.App.FindElement(locator) == null) - { - throw new ElementNotShownException(locator.ToString()); - } - } - else - { - if (this.App != null) - { - AttemptWaitForDriverElement(locator, timeout.Value, this.App); - } + throw new ElementNotShownException(locator.ToString()); } } - - /// - /// Determines whether the given element is not shown. - /// - /// - /// The locator for the element to locate. - /// - /// Thrown if AppManager.StartApp() has not been called. - public void VerifyElementNotShown(By locator) + else { - if (this.App == null) + if (this.App != null) { - throw new DriverNotInitializedException( - $"An app driver has not been initialized. Call 'AppManager.StartApp()' with an instance of an {nameof(AppManagerOptions)} to setup for testing."); + AttemptWaitForDriverElement(locator, timeout.Value, this.App); } + } + } - try - { - this.VerifyElementShown(locator); - } - catch (ElementNotShownException) - { - } - catch (WebDriverException wde) when (wde.Message.Contains("element could not be located")) - { - } + /// + /// Determines whether the given element is not shown. + /// + /// + /// The locator for the element to locate. + /// + /// Thrown when AppManager.StartApp() has not been called. + public void VerifyElementNotShown(By locator) + { + if (this.App == null) + { + throw new DriverNotInitializedException( + $"An app driver has not been initialized. Call 'AppManager.StartApp()' with an instance of an {nameof(AppManagerOptions)} to setup for testing."); } - private static void AttemptWaitForDriverElement(By locator, TimeSpan timeout, IWebDriver appDriver) + try { - var wait = new WebDriverWait(appDriver, timeout); - wait.Until(driver => driver.FindElement(locator) != null); + this.VerifyElementShown(locator); } + catch (ElementNotShownException) + { + } + catch (WebDriverException wde) when (wde.Message.Contains("element could not be located")) + { + } + } + + /// Thrown when no element matches the expected locator. + private static void AttemptWaitForDriverElement(By locator, TimeSpan timeout, IWebDriver appDriver) + { + var wait = new WebDriverWait(appDriver, timeout); + wait.Until(driver => driver.FindElement(locator) != null); } } \ No newline at end of file diff --git a/src/Legerity.Core/Web/WebAppDriverType.cs b/src/Legerity.Core/Web/WebAppDriverType.cs index 5b7e75eb..3a118e7f 100644 --- a/src/Legerity.Core/Web/WebAppDriverType.cs +++ b/src/Legerity.Core/Web/WebAppDriverType.cs @@ -1,48 +1,47 @@ -namespace Legerity.Web +namespace Legerity.Web; + +/// +/// Defines the values associated with the web app driver type. +/// +public enum WebAppDriverType { /// - /// Defines the values associated with the web app driver type. - /// - public enum WebAppDriverType - { - /// - /// None. Setting this will cause the application driver to not start. - /// - None, - - /// - /// Chrome. Setting this will cause the application driver to launch for Google Chrome. - /// - Chrome, - - /// - /// Firefox. Setting this will cause the application driver to launch for Mozilla Firefox. - /// - Firefox, - - /// - /// Opera. Setting this will cause the application driver to launch for Opera. - /// - Opera, - - /// - /// Safari. Setting this will cause the application driver to launch for Apple's Safari. - /// - Safari, - - /// - /// Edge. Setting this will cause the application driver to launch for Microsoft's Legacy Edge. - /// - Edge, - - /// - /// Internet Explorer. This will cause the application driver to launch for Microsoft's Internet Explorer. - /// - InternetExplorer, - - /// - /// Edge Chromium. Setting this will cause the application driver to launch for Microsoft's Chromium Edge. - /// - EdgeChromium, - } + /// None. Setting this will cause the application driver to not start. + /// + None, + + /// + /// Chrome. Setting this will cause the application driver to launch for Google Chrome. + /// + Chrome, + + /// + /// Firefox. Setting this will cause the application driver to launch for Mozilla Firefox. + /// + Firefox, + + /// + /// Opera. Setting this will cause the application driver to launch for Opera. + /// + Opera, + + /// + /// Safari. Setting this will cause the application driver to launch for Apple's Safari. + /// + Safari, + + /// + /// Edge. Setting this will cause the application driver to launch for Microsoft's Legacy Edge. + /// + Edge, + + /// + /// Internet Explorer. This will cause the application driver to launch for Microsoft's Internet Explorer. + /// + InternetExplorer, + + /// + /// Edge Chromium. Setting this will cause the application driver to launch for Microsoft's Chromium Edge. + /// + EdgeChromium, } \ No newline at end of file diff --git a/src/Legerity.Core/Web/WebAppManagerOptions.cs b/src/Legerity.Core/Web/WebAppManagerOptions.cs index fdef1b69..aac6faac 100644 --- a/src/Legerity.Core/Web/WebAppManagerOptions.cs +++ b/src/Legerity.Core/Web/WebAppManagerOptions.cs @@ -1,74 +1,73 @@ -namespace Legerity.Web +namespace Legerity.Web; + +using System.Collections.Generic; +using System.Drawing; + +/// +/// Defines a specific for a Web application. +/// +public class WebAppManagerOptions : AppManagerOptions { - using System.Collections.Generic; - using System.Drawing; + /// + /// Initializes a new instance of the class. + /// + public WebAppManagerOptions() + { + } /// - /// Defines a specific for a Web application. + /// Initializes a new instance of the class. /// - public class WebAppManagerOptions : AppManagerOptions + /// The type of web application driver to start. + /// The path to the web application driver directory. + public WebAppManagerOptions(WebAppDriverType driverType, string driverDirectoryPath) { - /// - /// Initializes a new instance of the class. - /// - public WebAppManagerOptions() - { - } + this.DriverType = driverType; + this.DriverUri = driverDirectoryPath; + } - /// - /// Initializes a new instance of the class. - /// - /// The type of web application driver to start. - /// The path to the web application driver directory. - public WebAppManagerOptions(WebAppDriverType driverType, string driverDirectoryPath) - { - this.DriverType = driverType; - this.DriverUri = driverDirectoryPath; - } + /// + /// Gets or sets the type of web application driver to start. + /// + public WebAppDriverType DriverType { get; set; } - /// - /// Gets or sets the type of web application driver to start. - /// - public WebAppDriverType DriverType { get; set; } + /// + /// Gets or sets the URL of the web application to load. + /// + public string Url { get; set; } - /// - /// Gets or sets the URL of the web application to load. - /// - public string Url { get; set; } + /// + /// Gets or sets the desired size of the window for the web application. + /// + /// The default value is 1280x800. + /// + /// + /// If is set to true, this value is ignored. + /// + /// + public Size DesiredSize { get; set; } = new Size(1280, 800); - /// - /// Gets or sets the desired size of the window for the web application. - /// - /// The default value is 1280x800. - /// - /// - /// If is set to true, this value is ignored. - /// - /// - public Size DesiredSize { get; set; } = new Size(1280, 800); + /// + /// Gets or sets a value indicating whether to maximize the window for the web application. + /// + public bool Maximize { get; set; } - /// - /// Gets or sets a value indicating whether to maximize the window for the web application. - /// - public bool Maximize { get; set; } + /// Returns a string that represents the current object. + /// A string that represents the current object. + public override string ToString() + { + return $"Platform [{this.DriverType}], {base.ToString()}, {this.GetOptionDetails()}"; + } - /// Returns a string that represents the current object. - /// A string that represents the current object. - public override string ToString() - { - return $"Platform [{this.DriverType}], {base.ToString()}, {this.GetOptionDetails()}"; - } + private string GetOptionDetails() + { + var options = new List(); - private string GetOptionDetails() + if (!string.IsNullOrWhiteSpace(this.Url)) { - var options = new List(); - - if (!string.IsNullOrWhiteSpace(this.Url)) - { - options.Add($"URL [{this.Url}]"); - } - - return string.Join(", ", options); + options.Add($"URL [{this.Url}]"); } + + return string.Join(", ", options); } } \ No newline at end of file diff --git a/src/Legerity.Core/Windows/Exceptions/WinAppDriverLoadFailedException.cs b/src/Legerity.Core/Windows/Exceptions/WinAppDriverLoadFailedException.cs index 7966e365..0f4a5760 100644 --- a/src/Legerity.Core/Windows/Exceptions/WinAppDriverLoadFailedException.cs +++ b/src/Legerity.Core/Windows/Exceptions/WinAppDriverLoadFailedException.cs @@ -1,26 +1,25 @@ -namespace Legerity.Windows.Exceptions -{ - using System; +namespace Legerity.Windows.Exceptions; + +using System; +/// +/// Defines an exception for when the WinAppDriver could not be loaded. +/// +public class WinAppDriverLoadFailedException : LegerityException +{ /// - /// Defines an exception for when the WinAppDriver could not be loaded. + /// Initializes a new instance of the class. /// - public class WinAppDriverLoadFailedException : LegerityException + /// The expected path for the WinAppDriver. + /// The inner exception thrown by the failure to load the WinAppDriver. + internal WinAppDriverLoadFailedException(string path, Exception exception) + : base($"The WinAppDriver could not be loaded at {path}.", exception) { - /// - /// Initializes a new instance of the class. - /// - /// The expected path for the WinAppDriver. - /// The inner exception thrown by the failure to load the WinAppDriver. - internal WinAppDriverLoadFailedException(string path, Exception exception) - : base($"The WinAppDriver could not be loaded at {path}.", exception) - { - this.Path = path; - } - - /// - /// Gets or sets the path where the WinAppDriver should have loaded from. - /// - public string Path { get; set; } + this.Path = path; } + + /// + /// Gets or sets the path where the WinAppDriver should have loaded from. + /// + public string Path { get; set; } } \ No newline at end of file diff --git a/src/Legerity.Core/Windows/Exceptions/WinAppDriverNotFoundException.cs b/src/Legerity.Core/Windows/Exceptions/WinAppDriverNotFoundException.cs index 9f29c1d2..0aaa4c79 100644 --- a/src/Legerity.Core/Windows/Exceptions/WinAppDriverNotFoundException.cs +++ b/src/Legerity.Core/Windows/Exceptions/WinAppDriverNotFoundException.cs @@ -1,23 +1,22 @@ -namespace Legerity.Windows.Exceptions +namespace Legerity.Windows.Exceptions; + +/// +/// Defines an exception for when the WinAppDriver cannot be found. +/// +public class WinAppDriverNotFoundException : LegerityException { /// - /// Defines an exception for when the WinAppDriver cannot be found. + /// Initializes a new instance of the class. /// - public class WinAppDriverNotFoundException : LegerityException + /// The expected path for the WinAppDriver. + internal WinAppDriverNotFoundException(string path) + : base($"The WinAppDriver could not be located at {path}. Please ensure it is installed first.") { - /// - /// Initializes a new instance of the class. - /// - /// The expected path for the WinAppDriver. - internal WinAppDriverNotFoundException(string path) - : base($"The WinAppDriver could not be located at {path}. Please ensure it is installed first.") - { - this.Path = path; - } - - /// - /// Gets or sets the path where the WinAppDriver should be located. - /// - public string Path { get; set; } + this.Path = path; } -} + + /// + /// Gets or sets the path where the WinAppDriver should be located. + /// + public string Path { get; set; } +} \ No newline at end of file diff --git a/src/Legerity.Core/Windows/Helpers/WinAppDriverHelper.cs b/src/Legerity.Core/Windows/Helpers/WinAppDriverHelper.cs index 1ada37a5..95c50559 100644 --- a/src/Legerity.Core/Windows/Helpers/WinAppDriverHelper.cs +++ b/src/Legerity.Core/Windows/Helpers/WinAppDriverHelper.cs @@ -1,79 +1,78 @@ -namespace Legerity.Windows.Helpers +namespace Legerity.Windows.Helpers; + +using System; +using System.Diagnostics; +using System.IO; +using System.Linq; +using Legerity.Windows.Exceptions; + +/// +/// Defines a helper class for the WinAppDriver. +/// +public static class WinAppDriverHelper { - using System; - using System.Diagnostics; - using System.IO; - using System.Linq; - using Legerity.Windows.Exceptions; + /// + /// Defines the default install location for the WinAppDriver. + /// + internal const string DefaultInstallLocation = + @"C:\Program Files (x86)\Windows Application Driver\WinAppDriver.exe"; + + private static Process WinAppDriverProcess { get; set; } /// - /// Defines a helper class for the WinAppDriver. + /// Determines whether the WinAppDriver is installed. /// - public static class WinAppDriverHelper + /// The expected path for the WinAppDriver. + /// True if the WinAppDriver exists at the specified ; otherwise, false. + public static bool IsInstalled(string path = DefaultInstallLocation) { - /// - /// Defines the default install location for the WinAppDriver. - /// - internal const string DefaultInstallLocation = - @"C:\Program Files (x86)\Windows Application Driver\WinAppDriver.exe"; - - private static Process WinAppDriverProcess { get; set; } + return File.Exists(path); + } - /// - /// Determines whether the WinAppDriver is installed. - /// - /// The expected path for the WinAppDriver. - /// True if the WinAppDriver exists at the specified ; otherwise, false. - public static bool IsInstalled(string path = DefaultInstallLocation) + /// + /// Loads an instance of the WinAppDriver process. + /// + /// The expected path for the WinAppDriver. + /// Thrown when the WinAppDriver could not be found. + /// Thrown when the WinAppDriver fails to load. + public static void Run(string path = DefaultInstallLocation) + { + WinAppDriverProcess ??= Process.GetProcessesByName("WinAppDriver").FirstOrDefault(); + if (WinAppDriverProcess is { HasExited: false }) { - return File.Exists(path); + return; } - /// - /// Loads an instance of the WinAppDriver process. - /// - /// The expected path for the WinAppDriver. - /// Thrown if the WinAppDriver could not be found. - /// Thrown if the WinAppDriver failed to load. - public static void Run(string path = DefaultInstallLocation) + bool isInstalled = IsInstalled(path); + if (!isInstalled) { - WinAppDriverProcess ??= Process.GetProcessesByName("WinAppDriver").FirstOrDefault(); - if (WinAppDriverProcess is { HasExited: false }) - { - return; - } - - bool isInstalled = IsInstalled(path); - if (!isInstalled) - { - throw new WinAppDriverNotFoundException(path); - } + throw new WinAppDriverNotFoundException(path); + } - try - { - WinAppDriverProcess = Process.Start(path); - } - catch (Exception ex) - { - throw new WinAppDriverLoadFailedException(path, ex); - } + try + { + WinAppDriverProcess = Process.Start(path); + } + catch (Exception ex) + { + throw new WinAppDriverLoadFailedException(path, ex); } + } - /// - /// Stops the running instance of the WinAppDriver process. - /// - public static void Stop() + /// + /// Stops the running instance of the WinAppDriver process. + /// + public static void Stop() + { + try { - try - { - if (WinAppDriverProcess is { HasExited: false }) - { - WinAppDriverProcess.Kill(); - } - } - catch (Exception) + if (WinAppDriverProcess is { HasExited: false }) { + WinAppDriverProcess.Kill(); } } + catch (Exception) + { + } } } \ No newline at end of file diff --git a/src/Legerity.Core/Windows/WindowsAppManagerOptions.cs b/src/Legerity.Core/Windows/WindowsAppManagerOptions.cs index 7c99c493..ecba6b4c 100644 --- a/src/Legerity.Core/Windows/WindowsAppManagerOptions.cs +++ b/src/Legerity.Core/Windows/WindowsAppManagerOptions.cs @@ -1,116 +1,115 @@ -namespace Legerity.Windows +namespace Legerity.Windows; + +using System.Collections.Generic; +using Legerity.Windows.Helpers; +using OpenQA.Selenium.Appium; + +/// +/// Defines a specific for a Windows application. +/// +public class WindowsAppManagerOptions : AppiumManagerOptions { - using System.Collections.Generic; - using Legerity.Windows.Helpers; - using OpenQA.Selenium.Appium; + /// + /// Initializes a new instance of the class. + /// + public WindowsAppManagerOptions() + { + } /// - /// Defines a specific for a Windows application. + /// Initializes a new instance of the class. /// - public class WindowsAppManagerOptions : AppiumManagerOptions + /// + /// The ID of the application under test. + /// + public WindowsAppManagerOptions(string appId) + : this(appId, null) { - /// - /// Initializes a new instance of the class. - /// - public WindowsAppManagerOptions() - { - } + } - /// - /// Initializes a new instance of the class. - /// - /// - /// The ID of the application under test. - /// - public WindowsAppManagerOptions(string appId) - : this(appId, null) - { - } + /// + /// Initializes a new instance of the class. + /// + /// + /// The ID of the application under test. + /// + /// + /// The additional options to apply to the . + /// + public WindowsAppManagerOptions(string appId, params (string, object)[] additionalOptions) + { + this.AppId = appId; + this.AdditionalOptions = additionalOptions; + } - /// - /// Initializes a new instance of the class. - /// - /// - /// The ID of the application under test. - /// - /// - /// The additional options to apply to the . - /// - public WindowsAppManagerOptions(string appId, params (string, object)[] additionalOptions) - { - this.AppId = appId; - this.AdditionalOptions = additionalOptions; - } + /// + /// Gets or sets the ID of the application under test. + /// + public string AppId { get; set; } - /// - /// Gets or sets the ID of the application under test. - /// - public string AppId { get; set; } + /// + /// Gets or sets a value indicating whether to launch the WinAppDriver if it is not already running. + /// + public bool LaunchWinAppDriver { get; set; } - /// - /// Gets or sets a value indicating whether to launch the WinAppDriver if it is not already running. - /// - public bool LaunchWinAppDriver { get; set; } + /// + /// Gets or sets a value indicating whether to maximize the window for the application. + /// + public bool Maximize { get; set; } - /// - /// Gets or sets a value indicating whether to maximize the window for the application. - /// - public bool Maximize { get; set; } + /// + /// Gets or sets the path to the WinAppDriver installation for launch. + /// + /// By default, the path will be the default install location; C:\Program Files (x86)\Windows Application Driver\WinAppDriver.exe. + /// + /// + public string WinAppDriverPath { get; set; } = WinAppDriverHelper.DefaultInstallLocation; - /// - /// Gets or sets the path to the WinAppDriver installation for launch. - /// - /// By default, the path will be the default install location; C:\Program Files (x86)\Windows Application Driver\WinAppDriver.exe. - /// - /// - public string WinAppDriverPath { get; set; } = WinAppDriverHelper.DefaultInstallLocation; + /// + /// Configures the with the specified additional options. + /// + public override void Configure() + { + base.Configure(); + this.AppiumOptions.AddAdditionalCapability("app", this.AppId); + } - /// - /// Configures the with the specified additional options. - /// - public override void Configure() - { - base.Configure(); - this.AppiumOptions.AddAdditionalCapability("app", this.AppId); - } + /// + /// Configures the with the specified additional options. + /// + /// + /// The additional options to apply to the . + /// + public void Configure((string, object)[] additionalOptions) + { + this.AdditionalOptions = additionalOptions; + this.Configure(); + } - /// - /// Configures the with the specified additional options. - /// - /// - /// The additional options to apply to the . - /// - public void Configure((string, object)[] additionalOptions) - { - this.AdditionalOptions = additionalOptions; - this.Configure(); - } + /// Returns a string that represents the current object. + /// A string that represents the current object. + public override string ToString() + { + return $"Platform [Windows], {base.ToString()}, {this.GetOptionDetails()}"; + } - /// Returns a string that represents the current object. - /// A string that represents the current object. - public override string ToString() + private string GetOptionDetails() + { + var options = new List(); + + if (!string.IsNullOrWhiteSpace(this.AppId)) { - return $"Platform [Windows], {base.ToString()}, {this.GetOptionDetails()}"; + options.Add($"App ID [{this.AppId}]"); } - private string GetOptionDetails() + if (this.AdditionalOptions != null) { - var options = new List(); - - if (!string.IsNullOrWhiteSpace(this.AppId)) + foreach ((string name, object value) in this.AdditionalOptions) { - options.Add($"App ID [{this.AppId}]"); + options.Add($"{name} [{value}]"); } - - if (this.AdditionalOptions != null) - { - foreach ((string name, object value) in this.AdditionalOptions) - { - options.Add($"{name} [{value}]"); - } - } - - return string.Join(", ", options); } + + return string.Join(", ", options); } } \ No newline at end of file diff --git a/src/Legerity.IOS/Elements/Core/Button.cs b/src/Legerity.IOS/Elements/Core/Button.cs index 39fbcf55..ff7de2f4 100644 --- a/src/Legerity.IOS/Elements/Core/Button.cs +++ b/src/Legerity.IOS/Elements/Core/Button.cs @@ -1,71 +1,72 @@ -namespace Legerity.IOS.Elements.Core -{ - using Legerity.IOS.Extensions; - using OpenQA.Selenium.Appium; - using OpenQA.Selenium.Appium.iOS; - using OpenQA.Selenium.Remote; +namespace Legerity.IOS.Elements.Core; + +using Legerity.IOS.Extensions; +using OpenQA.Selenium; +using OpenQA.Selenium.Appium; +using OpenQA.Selenium.Appium.iOS; +using OpenQA.Selenium.Remote; +/// +/// Defines a wrapper for the core iOS Button control. +/// +public class Button : IOSElementWrapper +{ /// - /// Defines a wrapper for the core iOS Button control. + /// Initializes a new instance of the class. /// - public class Button : IOSElementWrapper + /// + /// The reference. + /// + public Button(IOSElement element) + : base(element) { - /// - /// Initializes a new instance of the class. - /// - /// - /// The reference. - /// - public Button(IOSElement element) - : base(element) - { - } + } - /// - /// Gets the button's label content. - /// - public virtual string Label => this.Element.GetLabel(); + /// + /// Gets the button's label content. + /// + /// Thrown when an element is no longer valid in the document DOM. + public virtual string Label => this.GetLabel(); - /// - /// Allows conversion of a to the without direct casting. - /// - /// - /// The . - /// - /// - /// The . - /// - public static implicit operator Button(IOSElement element) - { - return new Button(element); - } + /// + /// Allows conversion of a to the without direct casting. + /// + /// + /// The . + /// + /// + /// The . + /// + public static implicit operator Button(IOSElement element) + { + return new Button(element); + } - /// - /// Allows conversion of a to the without direct casting. - /// - /// - /// The . - /// - /// - /// The . - /// - public static implicit operator Button(AppiumWebElement element) - { - return new Button(element as IOSElement); - } + /// + /// Allows conversion of a to the without direct casting. + /// + /// + /// The . + /// + /// + /// The . + /// + public static implicit operator Button(AppiumWebElement element) + { + return new Button(element as IOSElement); + } - /// - /// Allows conversion of a to the without direct casting. - /// - /// - /// The . - /// - /// - /// The . - /// - public static implicit operator Button(RemoteWebElement element) - { - return new Button(element as IOSElement); - } + /// + /// Allows conversion of a to the without direct casting. + /// + /// + /// The . + /// + /// + /// The . + /// + public static implicit operator Button(RemoteWebElement element) + { + return new Button(element as IOSElement); } } \ No newline at end of file diff --git a/src/Legerity.IOS/Elements/Core/Label.cs b/src/Legerity.IOS/Elements/Core/Label.cs index 8e5c4111..c1eebf18 100644 --- a/src/Legerity.IOS/Elements/Core/Label.cs +++ b/src/Legerity.IOS/Elements/Core/Label.cs @@ -1,71 +1,72 @@ -namespace Legerity.IOS.Elements.Core -{ - using Legerity.IOS.Extensions; - using OpenQA.Selenium.Appium; - using OpenQA.Selenium.Appium.iOS; - using OpenQA.Selenium.Remote; +namespace Legerity.IOS.Elements.Core; + +using Legerity.IOS.Extensions; +using OpenQA.Selenium; +using OpenQA.Selenium.Appium; +using OpenQA.Selenium.Appium.iOS; +using OpenQA.Selenium.Remote; +/// +/// Defines a wrapper for the core iOS Label control. +/// +public class Label : IOSElementWrapper +{ /// - /// Defines a wrapper for the core iOS Label control. + /// Initializes a new instance of the class. /// - public class Label : IOSElementWrapper + /// + /// The reference. + /// + public Label(IOSElement element) + : base(element) { - /// - /// Initializes a new instance of the class. - /// - /// - /// The reference. - /// - public Label(IOSElement element) - : base(element) - { - } + } - /// - /// Gets the text value of the label. - /// - public virtual string Text => this.Element.GetLabel(); + /// + /// Gets the text value of the label. + /// + /// Thrown when an element is no longer valid in the document DOM. + public virtual string Text => this.GetLabel(); - /// - /// Allows conversion of a to the without direct casting. - /// - /// - /// The . - /// - /// - /// The . - /// - public static implicit operator Label(IOSElement element) - { - return new Label(element); - } + /// + /// Allows conversion of a to the without direct casting. + /// + /// + /// The . + /// + /// + /// The . + /// + public static implicit operator Label(IOSElement element) + { + return new Label(element); + } - /// - /// Allows conversion of a to the without direct casting. - /// - /// - /// The . - /// - /// - /// The . - /// - public static implicit operator Label(AppiumWebElement element) - { - return new Label(element as IOSElement); - } + /// + /// Allows conversion of a to the without direct casting. + /// + /// + /// The . + /// + /// + /// The . + /// + public static implicit operator Label(AppiumWebElement element) + { + return new Label(element as IOSElement); + } - /// - /// Allows conversion of a to the without direct casting. - /// - /// - /// The . - /// - /// - /// The . - /// - public static implicit operator Label(RemoteWebElement element) - { - return new Label(element as IOSElement); - } + /// + /// Allows conversion of a to the without direct casting. + /// + /// + /// The . + /// + /// + /// The . + /// + public static implicit operator Label(RemoteWebElement element) + { + return new Label(element as IOSElement); } } \ No newline at end of file diff --git a/src/Legerity.IOS/Elements/Core/ProgressView.cs b/src/Legerity.IOS/Elements/Core/ProgressView.cs index f1fb46da..b343c163 100644 --- a/src/Legerity.IOS/Elements/Core/ProgressView.cs +++ b/src/Legerity.IOS/Elements/Core/ProgressView.cs @@ -1,71 +1,72 @@ -namespace Legerity.IOS.Elements.Core -{ - using Legerity.IOS.Extensions; - using OpenQA.Selenium.Appium; - using OpenQA.Selenium.Appium.iOS; - using OpenQA.Selenium.Remote; +namespace Legerity.IOS.Elements.Core; + +using Legerity.IOS.Extensions; +using OpenQA.Selenium; +using OpenQA.Selenium.Appium; +using OpenQA.Selenium.Appium.iOS; +using OpenQA.Selenium.Remote; +/// +/// Defines a wrapper for the core iOS ProgressView control. +/// +public class ProgressView : IOSElementWrapper +{ /// - /// Defines a wrapper for the core iOS ProgressView control. + /// Initializes a new instance of the class. /// - public class ProgressView : IOSElementWrapper + /// + /// The reference. + /// + public ProgressView(IOSElement element) + : base(element) { - /// - /// Initializes a new instance of the class. - /// - /// - /// The reference. - /// - public ProgressView(IOSElement element) - : base(element) - { - } + } - /// - /// Gets the value of the progress bar. - /// - public virtual double Percentage => double.Parse(this.Element.GetValue().TrimEnd('%')); + /// + /// Gets the value of the progress bar. + /// + /// Thrown when an element is no longer valid in the document DOM. + public virtual double Percentage => double.Parse(this.GetValue().TrimEnd('%')); - /// - /// Allows conversion of a to the without direct casting. - /// - /// - /// The . - /// - /// - /// The . - /// - public static implicit operator ProgressView(IOSElement element) - { - return new ProgressView(element); - } + /// + /// Allows conversion of a to the without direct casting. + /// + /// + /// The . + /// + /// + /// The . + /// + public static implicit operator ProgressView(IOSElement element) + { + return new ProgressView(element); + } - /// - /// Allows conversion of a to the without direct casting. - /// - /// - /// The . - /// - /// - /// The . - /// - public static implicit operator ProgressView(AppiumWebElement element) - { - return new ProgressView(element as IOSElement); - } + /// + /// Allows conversion of a to the without direct casting. + /// + /// + /// The . + /// + /// + /// The . + /// + public static implicit operator ProgressView(AppiumWebElement element) + { + return new ProgressView(element as IOSElement); + } - /// - /// Allows conversion of a to the without direct casting. - /// - /// - /// The . - /// - /// - /// The . - /// - public static implicit operator ProgressView(RemoteWebElement element) - { - return new ProgressView(element as IOSElement); - } + /// + /// Allows conversion of a to the without direct casting. + /// + /// + /// The . + /// + /// + /// The . + /// + public static implicit operator ProgressView(RemoteWebElement element) + { + return new ProgressView(element as IOSElement); } } \ No newline at end of file diff --git a/src/Legerity.IOS/Elements/Core/Slider.cs b/src/Legerity.IOS/Elements/Core/Slider.cs index 6edea17b..9860eeaf 100644 --- a/src/Legerity.IOS/Elements/Core/Slider.cs +++ b/src/Legerity.IOS/Elements/Core/Slider.cs @@ -1,96 +1,99 @@ -namespace Legerity.IOS.Elements.Core -{ - using System; - using Legerity.IOS.Extensions; - using OpenQA.Selenium; - using OpenQA.Selenium.Appium; - using OpenQA.Selenium.Appium.iOS; - using OpenQA.Selenium.Remote; +namespace Legerity.IOS.Elements.Core; + +using System; +using Legerity.IOS.Extensions; +using OpenQA.Selenium; +using OpenQA.Selenium.Appium; +using OpenQA.Selenium.Appium.iOS; +using OpenQA.Selenium.Remote; +/// +/// Defines a wrapper for the core iOS Slider control. +/// +public class Slider : IOSElementWrapper +{ /// - /// Defines a wrapper for the core iOS Slider control. + /// Initializes a new instance of the class. /// - public class Slider : IOSElementWrapper + /// + /// The reference. + /// + public Slider(IOSElement element) + : base(element) { - /// - /// Initializes a new instance of the class. - /// - /// - /// The reference. - /// - public Slider(IOSElement element) - : base(element) - { - } + } - /// - /// Gets the value of the slider as a percentage between 0 and 100. - /// - public virtual double Value => double.Parse(this.Element.GetValue().TrimEnd('%')); + /// + /// Gets the value of the slider as a percentage between 0 and 100. + /// + /// Thrown when an element is no longer valid in the document DOM. + public virtual double Value => double.Parse(this.GetValue().TrimEnd('%')); - /// - /// Gets a value indicating whether the control is in a readonly state. - /// - public virtual bool IsReadonly => !this.IsEnabled; + /// + /// Gets a value indicating whether the control is in a readonly state. + /// + public virtual bool IsReadonly => !this.IsEnabled; - /// - /// Allows conversion of a to the without direct casting. - /// - /// - /// The . - /// - /// - /// The . - /// - public static implicit operator Slider(IOSElement element) - { - return new Slider(element); - } + /// + /// Allows conversion of a to the without direct casting. + /// + /// + /// The . + /// + /// + /// The . + /// + public static implicit operator Slider(IOSElement element) + { + return new Slider(element); + } - /// - /// Allows conversion of a to the without direct casting. - /// - /// - /// The . - /// - /// - /// The . - /// - public static implicit operator Slider(AppiumWebElement element) - { - return new Slider(element as IOSElement); - } + /// + /// Allows conversion of a to the without direct casting. + /// + /// + /// The . + /// + /// + /// The . + /// + public static implicit operator Slider(AppiumWebElement element) + { + return new Slider(element as IOSElement); + } - /// - /// Allows conversion of a to the without direct casting. - /// - /// - /// The . - /// - /// - /// The . - /// - public static implicit operator Slider(RemoteWebElement element) - { - return new Slider(element as IOSElement); - } + /// + /// Allows conversion of a to the without direct casting. + /// + /// + /// The . + /// + /// + /// The . + /// + public static implicit operator Slider(RemoteWebElement element) + { + return new Slider(element as IOSElement); + } - /// - /// Sets the value of the slider. - /// - /// - /// The value. - /// - public virtual void SetValue(double value) - { - this.Click(); + /// + /// Sets the value of the slider. + /// + /// + /// The value. + /// + /// Thrown when an element is not enabled. + /// Thrown when an element is not visible. + /// Thrown when an element is no longer valid in the document DOM. + public virtual void SetValue(double value) + { + this.Click(); - double currentValue = this.Value; - while (Math.Abs(currentValue - value) > double.Epsilon) - { - this.Element.SendKeys(currentValue < value ? Keys.ArrowRight : Keys.ArrowLeft); - currentValue = this.Value; - } + double currentValue = this.Value; + while (Math.Abs(currentValue - value) > double.Epsilon) + { + this.Element.SendKeys(currentValue < value ? Keys.ArrowRight : Keys.ArrowLeft); + currentValue = this.Value; } } } \ No newline at end of file diff --git a/src/Legerity.IOS/Elements/Core/Switch.cs b/src/Legerity.IOS/Elements/Core/Switch.cs index e5268635..b6f851e8 100644 --- a/src/Legerity.IOS/Elements/Core/Switch.cs +++ b/src/Legerity.IOS/Elements/Core/Switch.cs @@ -1,99 +1,106 @@ -namespace Legerity.IOS.Elements.Core +namespace Legerity.IOS.Elements.Core; + +using Legerity.IOS.Extensions; +using OpenQA.Selenium; +using OpenQA.Selenium.Appium; +using OpenQA.Selenium.Appium.iOS; +using OpenQA.Selenium.Remote; + +/// +/// Defines a wrapper for the core iOS Switch control. +/// +public class Switch : IOSElementWrapper { - using Legerity.IOS.Extensions; - using OpenQA.Selenium.Appium; - using OpenQA.Selenium.Appium.iOS; - using OpenQA.Selenium.Remote; + private const string ToggleOnValue = "1"; /// - /// Defines a wrapper for the core iOS Switch control. + /// Initializes a new instance of the class. /// - public class Switch : IOSElementWrapper + /// + /// The reference. + /// + public Switch(IOSElement element) + : base(element) { - private const string ToggleOnValue = "1"; + } - /// - /// Initializes a new instance of the class. - /// - /// - /// The reference. - /// - public Switch(IOSElement element) - : base(element) - { - } + /// + /// Gets a value indicating whether the toggle switch is in the on position. + /// + /// Thrown when an element is no longer valid in the document DOM. + public virtual bool IsOn => this.GetValue() == ToggleOnValue; - /// - /// Gets a value indicating whether the toggle switch is in the on position. - /// - public virtual bool IsOn => this.Element.GetValue() == ToggleOnValue; + /// + /// Allows conversion of a to the without direct casting. + /// + /// + /// The . + /// + /// + /// The . + /// + public static implicit operator Switch(IOSElement element) + { + return new Switch(element); + } - /// - /// Allows conversion of a to the without direct casting. - /// - /// - /// The . - /// - /// - /// The . - /// - public static implicit operator Switch(IOSElement element) - { - return new Switch(element); - } + /// + /// Allows conversion of a to the without direct casting. + /// + /// + /// The . + /// + /// + /// The . + /// + public static implicit operator Switch(AppiumWebElement element) + { + return new Switch(element as IOSElement); + } - /// - /// Allows conversion of a to the without direct casting. - /// - /// - /// The . - /// - /// - /// The . - /// - public static implicit operator Switch(AppiumWebElement element) - { - return new Switch(element as IOSElement); - } + /// + /// Allows conversion of a to the without direct casting. + /// + /// + /// The . + /// + /// + /// The . + /// + public static implicit operator Switch(RemoteWebElement element) + { + return new Switch(element as IOSElement); + } - /// - /// Allows conversion of a to the without direct casting. - /// - /// - /// The . - /// - /// - /// The . - /// - public static implicit operator Switch(RemoteWebElement element) + /// + /// Toggles the switch on. + /// + /// Thrown when an element is not enabled. + /// Thrown when an element is not visible. + /// Thrown when an element is no longer valid in the document DOM. + public virtual void ToggleOn() + { + if (this.IsOn) { - return new Switch(element as IOSElement); + return; } - /// - /// Toggles the switch on. - /// - public virtual void ToggleOn() - { - if (this.IsOn) - { - return; - } - - this.Click(); - } + this.Click(); + } - /// - /// Toggles the switch off. - /// - public virtual void ToggleOff() + /// + /// Toggles the switch off. + /// + /// Thrown when an element is not enabled. + /// Thrown when an element is not visible. + /// Thrown when an element is no longer valid in the document DOM. + public virtual void ToggleOff() + { + if (!this.IsOn) { - if (!this.IsOn) - { - return; - } - - this.Click(); + return; } + + this.Click(); } } \ No newline at end of file diff --git a/src/Legerity.IOS/Elements/Core/TextField.cs b/src/Legerity.IOS/Elements/Core/TextField.cs index 7f5a83ce..f2974485 100644 --- a/src/Legerity.IOS/Elements/Core/TextField.cs +++ b/src/Legerity.IOS/Elements/Core/TextField.cs @@ -1,104 +1,115 @@ -namespace Legerity.IOS.Elements.Core -{ - using Legerity.IOS.Elements; - using Legerity.IOS.Extensions; - using OpenQA.Selenium.Appium; - using OpenQA.Selenium.Appium.iOS; - using OpenQA.Selenium.Remote; +namespace Legerity.IOS.Elements.Core; + +using Legerity.IOS.Elements; +using Legerity.IOS.Extensions; +using OpenQA.Selenium; +using OpenQA.Selenium.Appium; +using OpenQA.Selenium.Appium.iOS; +using OpenQA.Selenium.Remote; +/// +/// Defines a wrapper for the core iOS TextField control. +/// +public class TextField : IOSElementWrapper +{ /// - /// Defines a wrapper for the core iOS TextField control. + /// Initializes a new instance of the class. /// - public class TextField : IOSElementWrapper + /// The representing the element. + public TextField(IOSElement element) + : base(element) { - /// - /// Initializes a new instance of the class. - /// - /// The representing the element. - public TextField(IOSElement element) - : base(element) - { - } + } - /// - /// Gets the text value of the text field. - /// - public virtual string Text => this.Element.GetValue(); + /// + /// Gets the text value of the text field. + /// + /// Thrown when an element is no longer valid in the document DOM. + public virtual string Text => this.GetValue(); - /// - /// Gets the element associated with the clear text button, if shown. - /// - public virtual Button ClearTextButton => this.Element.FindElement(IOSByExtras.Label("Clear text")); + /// + /// Gets the element associated with the clear text button, if shown. + /// + /// Thrown when no element matches the expected locator. + public virtual Button ClearTextButton => this.FindElement(IOSByExtras.Label("Clear text")); - /// - /// Allows conversion of a to the without direct casting. - /// - /// - /// The . - /// - /// - /// The . - /// - public static implicit operator TextField(IOSElement element) - { - return new TextField(element); - } + /// + /// Allows conversion of a to the without direct casting. + /// + /// + /// The . + /// + /// + /// The . + /// + public static implicit operator TextField(IOSElement element) + { + return new TextField(element); + } - /// - /// Allows conversion of a to the without direct casting. - /// - /// - /// The . - /// - /// - /// The . - /// - public static implicit operator TextField(AppiumWebElement element) - { - return new TextField(element as IOSElement); - } + /// + /// Allows conversion of a to the without direct casting. + /// + /// + /// The . + /// + /// + /// The . + /// + public static implicit operator TextField(AppiumWebElement element) + { + return new TextField(element as IOSElement); + } - /// - /// Allows conversion of a to the without direct casting. - /// - /// - /// The . - /// - /// - /// The . - /// - public static implicit operator TextField(RemoteWebElement element) - { - return new TextField(element as IOSElement); - } + /// + /// Allows conversion of a to the without direct casting. + /// + /// + /// The . + /// + /// + /// The . + /// + public static implicit operator TextField(RemoteWebElement element) + { + return new TextField(element as IOSElement); + } - /// - /// Sets the text of the text field to the specified text. - /// - /// The text to display. - public virtual void SetText(string text) - { - this.ClearText(); - this.AppendText(text); - } + /// + /// Sets the text of the text field to the specified text. + /// + /// The text to display. + /// Thrown when an element is not visible. + /// Thrown when an element is not enabled. + /// Thrown when an element is no longer valid in the document DOM. + public virtual void SetText(string text) + { + this.ClearText(); + this.AppendText(text); + } - /// - /// Appends the specified text to the text field. - /// - /// The text to append. - public virtual void AppendText(string text) - { - this.Click(); - this.Element.SendKeys(text); - } + /// + /// Appends the specified text to the text field. + /// + /// The text to append. + /// Thrown when an element is not enabled. + /// Thrown when an element is not visible. + /// Thrown when an element is no longer valid in the document DOM. + public virtual void AppendText(string text) + { + this.Click(); + this.Element.SendKeys(text); + } - /// - /// Clears the text from the text field. - /// - public virtual void ClearText() - { - this.Click(); - this.Element.Clear(); - } + /// + /// Clears the text from the text field. + /// + /// Thrown when an element is not enabled. + /// Thrown when an element is not visible. + /// Thrown when an element is no longer valid in the document DOM. + public virtual void ClearText() + { + this.Click(); + this.Element.Clear(); } } \ No newline at end of file diff --git a/src/Legerity.IOS/Elements/IOSElementWrapper.cs b/src/Legerity.IOS/Elements/IOSElementWrapper.cs index 34b25c86..992cf130 100644 --- a/src/Legerity.IOS/Elements/IOSElementWrapper.cs +++ b/src/Legerity.IOS/Elements/IOSElementWrapper.cs @@ -80,13 +80,22 @@ public static implicit operator IOSElementWrapper(RemoteWebElement element) /// /// The amount of time the driver should wait when searching for the if it is not immediately present. /// + /// Thrown when an element is not shown for the expected locator. + /// Thrown when no element matches the expected locator. protected void VerifyDriverElementShown(By locator, TimeSpan? timeout) { if (timeout == null) { - if (this.Driver.FindElement(locator) == null) + try { - throw new ElementNotShownException(locator.ToString()); + if (this.Driver.FindElement(locator) == null) + { + throw new ElementNotShownException(locator.ToString()); + } + } + catch (NoSuchElementException ex) + { + throw new ElementNotShownException(locator.ToString(), ex); } } else @@ -105,13 +114,14 @@ protected void VerifyDriverElementShown(By locator, TimeSpan? timeout) /// /// The amount of time the driver should wait when searching for the if it is not immediately present. /// + /// Thrown when no elements are shown for the expected locator. protected void VerifyDriverElementsShown(By locator, TimeSpan? timeout) { if (timeout == null) { if (this.Driver.FindElements(locator).Count == 0) { - throw new ElementNotShownException(locator.ToString()); + throw new ElementsNotShownException(locator.ToString()); } } else diff --git a/src/Legerity.IOS/Extensions/AttributeExtensions.cs b/src/Legerity.IOS/Extensions/AttributeExtensions.cs index 622965cf..2eb88629 100644 --- a/src/Legerity.IOS/Extensions/AttributeExtensions.cs +++ b/src/Legerity.IOS/Extensions/AttributeExtensions.cs @@ -1,59 +1,62 @@ -namespace Legerity.IOS.Extensions -{ - using OpenQA.Selenium; - using OpenQA.Selenium.Remote; +namespace Legerity.IOS.Extensions; + +using OpenQA.Selenium; +using OpenQA.Selenium.Remote; +/// +/// Defines a collection of extensions for retrieving element attributes. +/// +public static class AttributeExtensions +{ /// - /// Defines a collection of extensions for retrieving element attributes. + /// Retrieves the label attribute from the specified element. /// - public static class AttributeExtensions + /// The to retrieve a label from. + /// The label of the element. + /// Thrown when an element is no longer valid in the document DOM. + public static string GetLabel(this IWebElement element) { - /// - /// Retrieves the label attribute from the specified element. - /// - /// The to retrieve a label from. - /// The label of the element. - public static string GetLabel(this IWebElement element) - { - return element.GetAttribute("label"); - } + return element.GetAttribute("label"); + } - /// - /// Retrieves the label attribute from the specified element. - /// - /// - /// The type of . - /// - /// The to retrieve a label from. - /// The label of the element. - public static string GetLabel(this IElementWrapper element) - where TElement : IWebElement - { - return GetLabel(element.Element); - } + /// + /// Retrieves the label attribute from the specified element. + /// + /// + /// The type of . + /// + /// The to retrieve a label from. + /// The label of the element. + /// Thrown when an element is no longer valid in the document DOM. + public static string GetLabel(this IElementWrapper element) + where TElement : IWebElement + { + return GetLabel(element.Element); + } - /// - /// Retrieves the value attribute from the specified element. - /// - /// The to retrieve a value from. - /// The value of the element. - public static string GetValue(this IWebElement element) - { - return element.GetAttribute("value"); - } + /// + /// Retrieves the value attribute from the specified element. + /// + /// The to retrieve a value from. + /// The value of the element. + /// Thrown when an element is no longer valid in the document DOM. + public static string GetValue(this IWebElement element) + { + return element.GetAttribute("value"); + } - /// - /// Retrieves the value attribute from the specified element. - /// - /// - /// The type of . - /// - /// The to retrieve a value from. - /// The value of the element. - public static string GetValue(this IElementWrapper element) - where TElement : IWebElement - { - return GetValue(element.Element); - } + /// + /// Retrieves the value attribute from the specified element. + /// + /// + /// The type of . + /// + /// The to retrieve a value from. + /// The value of the element. + /// Thrown when an element is no longer valid in the document DOM. + public static string GetValue(this IElementWrapper element) + where TElement : IWebElement + { + return GetValue(element.Element); } -} +} \ No newline at end of file diff --git a/src/Legerity.IOS/Extensions/IOSElementWrapperExtensions.cs b/src/Legerity.IOS/Extensions/IOSElementWrapperExtensions.cs index e3fb8188..fc37ff6c 100644 --- a/src/Legerity.IOS/Extensions/IOSElementWrapperExtensions.cs +++ b/src/Legerity.IOS/Extensions/IOSElementWrapperExtensions.cs @@ -21,6 +21,7 @@ public static class IOSElementWrapperExtensions /// The type of . /// The type of expected result from the wait condition. /// Whether the wait was a success. + /// Thrown when the callback throws an exception. public static bool TryWaitUntil( this TElementWrapper element, Func condition, @@ -52,7 +53,8 @@ public static bool TryWaitUntil( /// The type of . /// The type of expected result from the wait condition. /// The of the wait until operation. - /// Thrown if the condition is not met in the allocated timeout period. + /// Thrown when the condition is not met in the allocated timeout period. + /// Thrown when the callback throws an exception. public static TResult WaitUntil( this TElementWrapper element, Func condition, diff --git a/src/Legerity.IOS/Extensions/LegerityTestClassExtensions.cs b/src/Legerity.IOS/Extensions/LegerityTestClassExtensions.cs index 0a0c474d..fcc5fb00 100644 --- a/src/Legerity.IOS/Extensions/LegerityTestClassExtensions.cs +++ b/src/Legerity.IOS/Extensions/LegerityTestClassExtensions.cs @@ -1,70 +1,80 @@ -namespace Legerity.IOS.Extensions -{ - using System; - using OpenQA.Selenium; - using OpenQA.Selenium.Appium.iOS; +namespace Legerity.IOS.Extensions; + +using System; +using Exceptions; +using OpenQA.Selenium; +using OpenQA.Selenium.Appium.iOS; +/// +/// Defines a collection of extensions for instances. +/// +public static class LegerityTestClassExtensions +{ /// - /// Defines a collection of extensions for instances. + /// Starts the iOS application ready for testing. /// - public static class LegerityTestClassExtensions + /// + /// The test class to launch an Android application for. + /// + /// + /// An optional condition of the driver to wait on until it is met. + /// + /// + /// An optional timeout wait on the conditional wait until being true. If not set, the wait will run immediately, and if not valid, will throw an exception. + /// + /// + /// An optional count of retries after a timeout on the wait until condition before accepting the failure. + /// + /// The configured and running application driver. + /// Thrown when the wait until condition is not met in the allocated timeout period if provided. + /// Thrown when the application is null, the session ID is null once initialized, or the driver fails to configure correctly before returning. + /// Thrown when: + /// - The Appium server could not be found when running with true. + /// + public static IOSDriver StartIOSApp( + this LegerityTestClass testClass, + Func waitUntil = default, + TimeSpan? waitUntilTimeout = default, + int waitUntilRetries = 0) { - /// - /// Starts the iOS application ready for testing. - /// - /// - /// The test class to launch an Android application for. - /// - /// - /// An optional condition of the driver to wait on until it is met. - /// - /// - /// An optional timeout wait on the conditional wait until being true. If not set, the wait will run immediately, and if not valid, will throw an exception. - /// - /// - /// An optional count of retries after a timeout on the wait until condition before accepting the failure. - /// - /// The configured and running application driver. - public static IOSDriver StartIOSApp( - this LegerityTestClass testClass, - Func waitUntil = default, - TimeSpan? waitUntilTimeout = default, - int waitUntilRetries = 0) - { - return testClass.StartApp(waitUntil, waitUntilTimeout, waitUntilRetries) as IOSDriver; - } + return testClass.StartApp(waitUntil, waitUntilTimeout, waitUntilRetries) as IOSDriver; + } - /// - /// Starts the iOS application ready for testing. - /// - /// - /// The test class to launch an Android application for. - /// - /// - /// The optional options to configure the driver with. - /// - /// Settings this will override the if previously set. - /// - /// - /// - /// An optional condition of the driver to wait on until it is met. - /// - /// - /// An optional timeout wait on the conditional wait until being true. If not set, the wait will run immediately, and if not valid, will throw an exception. - /// - /// - /// An optional count of retries after a timeout on the wait until condition before accepting the failure. - /// - /// The configured and running application driver. - public static IOSDriver StartIOSApp( - this LegerityTestClass testClass, - IOSAppManagerOptions options, - Func waitUntil = default, - TimeSpan? waitUntilTimeout = default, - int waitUntilRetries = 0) - { - return testClass.StartApp(options, waitUntil, waitUntilTimeout, waitUntilRetries) as - IOSDriver; - } + /// + /// Starts the iOS application ready for testing. + /// + /// + /// The test class to launch an Android application for. + /// + /// + /// The optional options to configure the driver with. + /// + /// Settings this will override the if previously set. + /// + /// + /// + /// An optional condition of the driver to wait on until it is met. + /// + /// + /// An optional timeout wait on the conditional wait until being true. If not set, the wait will run immediately, and if not valid, will throw an exception. + /// + /// + /// An optional count of retries after a timeout on the wait until condition before accepting the failure. + /// + /// The configured and running application driver. + /// Thrown when the wait until condition is not met in the allocated timeout period if provided. + /// Thrown when the application is null, the session ID is null once initialized, or the driver fails to configure correctly before returning. + /// Thrown when: + /// - The Appium server could not be found when running with true. + /// + public static IOSDriver StartIOSApp( + this LegerityTestClass testClass, + IOSAppManagerOptions options, + Func waitUntil = default, + TimeSpan? waitUntilTimeout = default, + int waitUntilRetries = 0) + { + return testClass.StartApp(options, waitUntil, waitUntilTimeout, waitUntilRetries) as + IOSDriver; } } \ No newline at end of file diff --git a/src/Legerity.IOS/IOSByExtras.cs b/src/Legerity.IOS/IOSByExtras.cs index 8156035b..44805473 100644 --- a/src/Legerity.IOS/IOSByExtras.cs +++ b/src/Legerity.IOS/IOSByExtras.cs @@ -1,50 +1,49 @@ -namespace Legerity.IOS -{ - using OpenQA.Selenium; +namespace Legerity.IOS; + +using OpenQA.Selenium; +/// +/// Defines a collection of extra locator constraints for . +/// +public static class IOSByExtras +{ /// - /// Defines a collection of extra locator constraints for . + /// Gets a mechanism to find elements by the label. /// - public static class IOSByExtras + /// The label to find. + /// A object the driver can use to find elements. + public static By Label(string label) { - /// - /// Gets a mechanism to find elements by the label. - /// - /// The label to find. - /// A object the driver can use to find elements. - public static By Label(string label) - { - return By.XPath($".//*[@label='{label}']"); - } + return By.XPath($".//*[@label='{label}']"); + } - /// - /// Gets a mechanism to find elements by a partial label. - /// - /// The label to find. - /// A object the driver can use to find elements. - public static By PartialLabel(string label) - { - return By.XPath($".//*[contains(@label,'{label}')]"); - } + /// + /// Gets a mechanism to find elements by a partial label. + /// + /// The label to find. + /// A object the driver can use to find elements. + public static By PartialLabel(string label) + { + return By.XPath($".//*[contains(@label,'{label}')]"); + } - /// - /// Gets a mechanism to find elements by the value. - /// - /// The value to find. - /// A object the driver can use to find elements. - public static By Value(string value) - { - return By.XPath($".//*[@value='{value}']"); - } + /// + /// Gets a mechanism to find elements by the value. + /// + /// The value to find. + /// A object the driver can use to find elements. + public static By Value(string value) + { + return By.XPath($".//*[@value='{value}']"); + } - /// - /// Gets a mechanism to find elements by a partial value. - /// - /// The value to find. - /// A object the driver can use to find elements. - public static By PartialValue(string value) - { - return By.XPath($".//*[contains(@value,'{value}')]"); - } + /// + /// Gets a mechanism to find elements by a partial value. + /// + /// The value to find. + /// A object the driver can use to find elements. + public static By PartialValue(string value) + { + return By.XPath($".//*[contains(@value,'{value}')]"); } -} +} \ No newline at end of file diff --git a/src/Legerity.MADE/DropDownList.cs b/src/Legerity.MADE/DropDownList.cs index 60126c10..3b6a344d 100644 --- a/src/Legerity.MADE/DropDownList.cs +++ b/src/Legerity.MADE/DropDownList.cs @@ -1,130 +1,144 @@ -namespace Legerity.Windows.Elements.MADE +namespace Legerity.Windows.Elements.MADE; + +using Legerity.Exceptions; +using Legerity.Windows.Elements.Core; +using OpenQA.Selenium; +using OpenQA.Selenium.Appium; +using OpenQA.Selenium.Appium.Windows; +using OpenQA.Selenium.Remote; + +/// +/// Defines a wrapper for the MADE.NET UWP DropDownList control. +/// +public class DropDownList : WindowsElementWrapper { - using Legerity.Exceptions; - using Legerity.Windows.Elements.Core; - using OpenQA.Selenium; - using OpenQA.Selenium.Appium; - using OpenQA.Selenium.Appium.Windows; - using OpenQA.Selenium.Remote; + /// + /// Initializes a new instance of the class. + /// + /// + /// The reference. + /// + public DropDownList(WindowsElement element) + : base(element) + { + } /// - /// Defines a wrapper for the MADE.NET UWP DropDownList control. + /// Gets the element associated with the drop down content. /// - public class DropDownList : WindowsElementWrapper + /// Thrown when no element matches the expected locator. + public virtual ListView DropDown => this.FindElement(WindowsByExtras.AutomationId("DropDownContent")); + + /// + /// Allows conversion of a to the without direct casting. + /// + /// + /// The . + /// + /// + /// The . + /// + public static implicit operator DropDownList(WindowsElement element) { - /// - /// Initializes a new instance of the class. - /// - /// - /// The reference. - /// - public DropDownList(WindowsElement element) - : base(element) - { - } + return new DropDownList(element); + } - /// - /// Gets the element associated with the drop down content. - /// - public virtual ListView DropDown => this.Element.FindElement(WindowsByExtras.AutomationId("DropDownContent")); + /// + /// Allows conversion of a to the without direct casting. + /// + /// + /// The . + /// + /// + /// The . + /// + public static implicit operator DropDownList(AppiumWebElement element) + { + return new DropDownList(element as WindowsElement); + } - /// - /// Allows conversion of a to the without direct casting. - /// - /// - /// The . - /// - /// - /// The . - /// - public static implicit operator DropDownList(WindowsElement element) - { - return new DropDownList(element); - } + /// + /// Allows conversion of a to the without direct casting. + /// + /// + /// The . + /// + /// + /// The . + /// + public static implicit operator DropDownList(RemoteWebElement element) + { + return new DropDownList(element as WindowsElement); + } - /// - /// Allows conversion of a to the without direct casting. - /// - /// - /// The . - /// - /// - /// The . - /// - public static implicit operator DropDownList(AppiumWebElement element) - { - return new DropDownList(element as WindowsElement); - } + /// + /// Selects an item in the combo-box with the specified item name. + /// + /// + /// The name of the item to select. + /// + /// Thrown when no element matches the expected locator. + /// Thrown when an element is not enabled. + /// Thrown when an element is not visible. + /// Thrown when an element is no longer valid in the document DOM. + /// Thrown when no elements are shown for the expected locator. + public virtual void SelectItem(string name) + { + this.OpenDropDown(); + this.DropDown.ClickItem(name); + } - /// - /// Allows conversion of a to the without direct casting. - /// - /// - /// The . - /// - /// - /// The . - /// - public static implicit operator DropDownList(RemoteWebElement element) - { - return new DropDownList(element as WindowsElement); - } + /// + /// Selects an item in the combo-box with the specified partial item name. + /// + /// The partial name match for the item to select. + /// Thrown when no element matches the expected locator. + /// Thrown when an element is not enabled. + /// Thrown when an element is not visible. + /// Thrown when an element is no longer valid in the document DOM. + /// Thrown when no elements are shown for the expected locator. + public virtual void SelectItemByPartialName(string partialName) + { + this.OpenDropDown(); + this.DropDown.ClickItemByPartialName(partialName); + } - /// - /// Selects an item in the combo-box with the specified item name. - /// - /// - /// The name of the item to select. - /// - public virtual void SelectItem(string name) + /// + /// Opens the drop down if it is not already open. + /// + /// Thrown when an element is not enabled. + /// Thrown when an element is not visible. + /// Thrown when an element is no longer valid in the document DOM. + public virtual void OpenDropDown() + { + if (!this.IsDropDownOpen()) { - this.OpenDropDown(); - this.DropDown.ClickItem(name); + this.Click(); } + } + + /// + /// Determines whether the drop down is open. + /// + /// True if the drop down is open; otherwise, false. + /// Thrown when an element is no longer valid in the document DOM. + public virtual bool IsDropDownOpen() + { + bool isVisible; - /// - /// Selects an item in the combo-box with the specified partial item name. - /// - /// The partial name match for the item to select. - public virtual void SelectItemByPartialName(string partialName) + try { - this.OpenDropDown(); - this.DropDown.ClickItemByPartialName(partialName); + isVisible = this.DropDown.IsVisible; } - - /// - /// Opens the drop down if it is not already open. - /// - public virtual void OpenDropDown() + catch (WebDriverException wde) when (wde.Message.Contains("element could not be located")) { - if (!this.IsDropDownOpen()) - { - this.Click(); - } + isVisible = false; } - - /// - /// Determines whether the drop down is open. - /// - /// True if the drop down is open; otherwise, false. - public virtual bool IsDropDownOpen() + catch (ElementNotShownException) { - bool isVisible; - - try - { - isVisible = this.DropDown.IsVisible; - } - catch (WebDriverException wde) when (wde.Message.Contains("element could not be located")) - { - isVisible = false; - } - catch (ElementNotShownException) - { - isVisible = false; - } - - return isVisible; + isVisible = false; } + + return isVisible; } } \ No newline at end of file diff --git a/src/Legerity.MADE/InputValidator.cs b/src/Legerity.MADE/InputValidator.cs index 399cf739..e307529b 100644 --- a/src/Legerity.MADE/InputValidator.cs +++ b/src/Legerity.MADE/InputValidator.cs @@ -1,107 +1,112 @@ -namespace Legerity.Windows.Elements.MADE +namespace Legerity.Windows.Elements.MADE; + +using Legerity.Windows.Elements.Core; +using OpenQA.Selenium; +using OpenQA.Selenium.Appium; +using OpenQA.Selenium.Appium.Windows; +using OpenQA.Selenium.Remote; + +/// +/// Defines a wrapper for the MADE.NET UWP InputValidator control. +/// +public class InputValidator : WindowsElementWrapper { - using Legerity.Windows.Elements.Core; - using OpenQA.Selenium; - using OpenQA.Selenium.Appium; - using OpenQA.Selenium.Appium.Windows; - using OpenQA.Selenium.Remote; + /// + /// Initializes a new instance of the class. + /// + /// + /// The reference. + /// + public InputValidator(WindowsElement element) + : base(element) + { + } + + /// + /// Gets the associated with the validation feedback message. + /// + /// Thrown when no element matches the expected locator. + public virtual TextBlock ValidationFeedback => + this.FindElement(WindowsByExtras.AutomationId("ValidatorFeedbackMessage")); + + /// + /// Gets the validation feedback message associated with the element. + /// + /// Thrown when an element is no longer valid in the document DOM. + public virtual string Message => this.ValidationFeedback?.Text; /// - /// Defines a wrapper for the MADE.NET UWP InputValidator control. + /// Allows conversion of a to the without direct casting. /// - public class InputValidator : WindowsElementWrapper + /// + /// The . + /// + /// + /// The . + /// + public static implicit operator InputValidator(WindowsElement element) { - /// - /// Initializes a new instance of the class. - /// - /// - /// The reference. - /// - public InputValidator(WindowsElement element) - : base(element) - { - } + return new InputValidator(element); + } - /// - /// Gets the associated with the validation feedback message. - /// - public virtual TextBlock ValidationFeedback => this.Element.FindElement(WindowsByExtras.AutomationId("ValidatorFeedbackMessage")); + /// + /// Allows conversion of a to the without direct casting. + /// + /// + /// The . + /// + /// + /// The . + /// + public static implicit operator InputValidator(AppiumWebElement element) + { + return new InputValidator(element as WindowsElement); + } - /// - /// Gets the validation feedback message associated with the element. - /// - public virtual string Message => this.ValidationFeedback?.Text; + /// + /// Allows conversion of a to the without direct casting. + /// + /// + /// The . + /// + /// + /// The . + /// + public static implicit operator InputValidator(RemoteWebElement element) + { + return new InputValidator(element as WindowsElement); + } - /// - /// Allows conversion of a to the without direct casting. - /// - /// - /// The . - /// - /// - /// The . - /// - public static implicit operator InputValidator(WindowsElement element) - { - return new InputValidator(element); - } + /// + /// Retrieves the input element with the given locator. + /// + /// The locator to find the input element. + /// The if found; otherwise, throws . + /// Thrown when no element matches the expected locator. + public AppiumWebElement Input(By locator) + { + return this.FindElement(locator); + } - /// - /// Allows conversion of a to the without direct casting. - /// - /// - /// The . - /// - /// - /// The . - /// - public static implicit operator InputValidator(AppiumWebElement element) - { - return new InputValidator(element as WindowsElement); - } + /// + /// Retrieves the feedback message text if the is shown. + /// + /// The feedback message text of the element. + /// Thrown when an element is no longer valid in the document DOM. + /// Thrown when no element matches the expected locator. + public virtual string FeedbackMessage() + { + string message; - /// - /// Allows conversion of a to the without direct casting. - /// - /// - /// The . - /// - /// - /// The . - /// - public static implicit operator InputValidator(RemoteWebElement element) + try { - return new InputValidator(element as WindowsElement); + message = this.ValidationFeedback.Text; } - - /// - /// Retrieves the input element with the given locator. - /// - /// The locator to find the input element. - /// The if found; otherwise, throws . - public AppiumWebElement Input(By locator) + catch (WebDriverException ex) when (ex.Message.Contains("element could not be located")) { - return this.Element.FindElement(locator); + message = null; } - /// - /// Retrieves the feedback message text if the is shown. - /// - /// The feedback message text of the element. - public virtual string FeedbackMessage() - { - string message; - - try - { - message = this.ValidationFeedback.Text; - } - catch (WebDriverException ex) when (ex.Message.Contains("element could not be located")) - { - message = null; - } - - return message; - } + return message; } } \ No newline at end of file diff --git a/src/Legerity.Telerik.Uwp/RadAutoCompleteBox.cs b/src/Legerity.Telerik.Uwp/RadAutoCompleteBox.cs index ba0ccc7c..259722aa 100644 --- a/src/Legerity.Telerik.Uwp/RadAutoCompleteBox.cs +++ b/src/Legerity.Telerik.Uwp/RadAutoCompleteBox.cs @@ -1,128 +1,152 @@ -namespace Legerity.Windows.Elements.Telerik +namespace Legerity.Windows.Elements.Telerik; + +using System; +using Legerity.Exceptions; +using Legerity.Windows.Elements.Core; +using OpenQA.Selenium; +using OpenQA.Selenium.Appium; +using OpenQA.Selenium.Appium.Windows; +using OpenQA.Selenium.Remote; + +/// +/// Defines a wrapper for the Telerik UWP RadAutoCompleteBox control. +/// +public class RadAutoCompleteBox : WindowsElementWrapper { - using System; - using Legerity.Windows.Elements.Core; - using OpenQA.Selenium; - using OpenQA.Selenium.Appium; - using OpenQA.Selenium.Appium.Windows; - using OpenQA.Selenium.Remote; + private readonly By suggestionsControlLocator = WindowsByExtras.AutomationId("PART_SuggestionsControl"); + + /// + /// Initializes a new instance of the class. + /// + /// + /// The reference. + /// + public RadAutoCompleteBox(WindowsElement element) + : base(element) + { + } + + /// + /// Gets the element associated with the text box. + /// + /// Thrown when no element matches the expected locator. + public virtual TextBox TextBox => this.FindElement(By.ClassName("TextBox")); + + /// + /// Gets the value of the auto-suggest box. + /// + /// Thrown when an element is no longer valid in the document DOM. + public virtual string Text => this.TextBox.Text; + + /// + /// Allows conversion of a to the without direct casting. + /// + /// + /// The . + /// + /// + /// The . + /// + public static implicit operator RadAutoCompleteBox(WindowsElement element) + { + return new RadAutoCompleteBox(element); + } + + /// + /// Allows conversion of a to the without direct casting. + /// + /// + /// The . + /// + /// + /// The . + /// + public static implicit operator RadAutoCompleteBox(AppiumWebElement element) + { + return new RadAutoCompleteBox(element as WindowsElement); + } + + /// + /// Allows conversion of a to the without direct casting. + /// + /// + /// The . + /// + /// + /// The . + /// + public static implicit operator RadAutoCompleteBox(RemoteWebElement element) + { + return new RadAutoCompleteBox(element as WindowsElement); + } + + /// + /// Selects a suggestion from the auto-suggest box. + /// + /// The suggestion to select. + /// Thrown when an element is not shown for the expected locator. + /// Thrown when no element matches the expected locator. + /// Thrown when an element is not enabled. + /// Thrown when an element is not visible. + /// Thrown when an element is no longer valid in the document DOM. + /// Thrown when no elements are shown for the expected locator. + public virtual void SelectSuggestion(string suggestion) + { + this.SelectSuggestion(suggestion, suggestion); + } + + /// + /// Selects a suggestion from the auto-suggest box. + /// + /// The initial value to set. + /// The suggestion to select. + /// Thrown when an element is not shown for the expected locator. + /// Thrown when no element matches the expected locator. + /// Thrown when an element is not enabled. + /// Thrown when an element is not visible. + /// Thrown when an element is no longer valid in the document DOM. + /// Thrown when no elements are shown for the expected locator. + public virtual void SelectSuggestion(string value, string suggestion) + { + this.SetText(value); + + this.VerifyElementShown(this.suggestionsControlLocator, TimeSpan.FromSeconds(2)); + + ListBox suggestionList = this.FindElement(this.suggestionsControlLocator); + suggestionList.ClickItem(suggestion); + } + + /// + /// Selects a suggestion from the auto-suggest box. + /// + /// The initial value to set. + /// The partial suggestion match to select. + /// Thrown when an element is not shown for the expected locator. + /// Thrown when no element matches the expected locator. + /// Thrown when an element is not enabled. + /// Thrown when an element is not visible. + /// Thrown when an element is no longer valid in the document DOM. + /// Thrown when no elements are shown for the expected locator. + public virtual void SelectSuggestionByPartialSuggestion(string value, string partialSuggestion) + { + this.SetText(value); + + this.VerifyElementShown(this.suggestionsControlLocator, TimeSpan.FromSeconds(2)); + + ListBox suggestionList = this.FindElement(this.suggestionsControlLocator); + suggestionList.ClickItemByPartialName(partialSuggestion); + } /// - /// Defines a wrapper for the Telerik UWP RadAutoCompleteBox control. + /// Sets the value of the auto-suggest box. /// - public class RadAutoCompleteBox : WindowsElementWrapper + /// The value to set. + /// Thrown when no element matches the expected locator. + /// Thrown when an element is no longer valid in the document DOM. + /// Thrown when an element is not enabled. + /// Thrown when an element is not visible. + public virtual void SetText(string value) { - private readonly By suggestionsControlLocator = WindowsByExtras.AutomationId("PART_SuggestionsControl"); - - /// - /// Initializes a new instance of the class. - /// - /// - /// The reference. - /// - public RadAutoCompleteBox(WindowsElement element) - : base(element) - { - } - - /// - /// Gets the element associated with the text box. - /// - public virtual TextBox TextBox => this.Element.FindElement(By.ClassName("TextBox")); - - /// - /// Gets the value of the auto-suggest box. - /// - public virtual string Text => this.TextBox.Text; - - /// - /// Allows conversion of a to the without direct casting. - /// - /// - /// The . - /// - /// - /// The . - /// - public static implicit operator RadAutoCompleteBox(WindowsElement element) - { - return new RadAutoCompleteBox(element); - } - - /// - /// Allows conversion of a to the without direct casting. - /// - /// - /// The . - /// - /// - /// The . - /// - public static implicit operator RadAutoCompleteBox(AppiumWebElement element) - { - return new RadAutoCompleteBox(element as WindowsElement); - } - - /// - /// Allows conversion of a to the without direct casting. - /// - /// - /// The . - /// - /// - /// The . - /// - public static implicit operator RadAutoCompleteBox(RemoteWebElement element) - { - return new RadAutoCompleteBox(element as WindowsElement); - } - - /// - /// Selects a suggestion from the auto-suggest box. - /// - /// The suggestion to select. - public virtual void SelectSuggestion(string suggestion) - { - this.SelectSuggestion(suggestion, suggestion); - } - - /// - /// Selects a suggestion from the auto-suggest box. - /// - /// The initial value to set. - /// The suggestion to select. - public virtual void SelectSuggestion(string value, string suggestion) - { - this.SetText(value); - - this.VerifyElementShown(this.suggestionsControlLocator, TimeSpan.FromSeconds(2)); - - ListBox suggestionList = this.Element.FindElement(this.suggestionsControlLocator); - suggestionList.ClickItem(suggestion); - } - - /// - /// Selects a suggestion from the auto-suggest box. - /// - /// The initial value to set. - /// The partial suggestion match to select. - public virtual void SelectSuggestionByPartialSuggestion(string value, string partialSuggestion) - { - this.SetText(value); - - this.VerifyElementShown(this.suggestionsControlLocator, TimeSpan.FromSeconds(2)); - - ListBox suggestionList = this.Element.FindElement(this.suggestionsControlLocator); - suggestionList.ClickItemByPartialName(partialSuggestion); - } - - /// - /// Sets the value of the auto-suggest box. - /// - /// The value to set. - public virtual void SetText(string value) - { - this.TextBox.SetText(value); - } + this.TextBox.SetText(value); } } \ No newline at end of file diff --git a/src/Legerity.Telerik.Uwp/RadBulletGraph.cs b/src/Legerity.Telerik.Uwp/RadBulletGraph.cs index 896483c4..a74ad09d 100644 --- a/src/Legerity.Telerik.Uwp/RadBulletGraph.cs +++ b/src/Legerity.Telerik.Uwp/RadBulletGraph.cs @@ -1,81 +1,84 @@ -namespace Legerity.Windows.Elements.Telerik -{ - using Legerity.Windows.Extensions; - using OpenQA.Selenium.Appium; - using OpenQA.Selenium.Appium.Windows; - using OpenQA.Selenium.Remote; +namespace Legerity.Windows.Elements.Telerik; + +using Legerity.Windows.Extensions; +using OpenQA.Selenium; +using OpenQA.Selenium.Appium; +using OpenQA.Selenium.Appium.Windows; +using OpenQA.Selenium.Remote; +/// +/// Defines a wrapper for the Telerik UWP RadBulletGraph control. +/// +public class RadBulletGraph : WindowsElementWrapper +{ /// - /// Defines a wrapper for the Telerik UWP RadBulletGraph control. + /// Initializes a new instance of the class. /// - public class RadBulletGraph : WindowsElementWrapper + /// + /// The reference. + /// + public RadBulletGraph(WindowsElement element) + : base(element) { - /// - /// Initializes a new instance of the class. - /// - /// - /// The reference. - /// - public RadBulletGraph(WindowsElement element) - : base(element) - { - } + } - /// - /// Gets the minimum value of the bullet graph. - /// - public virtual double Minimum => this.GetRangeMinimum(); + /// + /// Gets the minimum value of the bullet graph. + /// + /// Thrown when an element is no longer valid in the document DOM. + public virtual double Minimum => this.GetRangeMinimum(); - /// - /// Gets the maximum value of the bullet graph. - /// - public virtual double Maximum => this.GetRangeMaximum(); + /// + /// Gets the maximum value of the bullet graph. + /// + /// Thrown when an element is no longer valid in the document DOM. + public virtual double Maximum => this.GetRangeMaximum(); - /// - /// Gets the value of the bullet graph. - /// - public virtual double Value => this.GetRangeValue(); + /// + /// Gets the value of the bullet graph. + /// + /// Thrown when an element is no longer valid in the document DOM. + public virtual double Value => this.GetRangeValue(); - /// - /// Allows conversion of a to the without direct casting. - /// - /// - /// The . - /// - /// - /// The . - /// - public static implicit operator RadBulletGraph(WindowsElement element) - { - return new RadBulletGraph(element); - } + /// + /// Allows conversion of a to the without direct casting. + /// + /// + /// The . + /// + /// + /// The . + /// + public static implicit operator RadBulletGraph(WindowsElement element) + { + return new RadBulletGraph(element); + } - /// - /// Allows conversion of a to the without direct casting. - /// - /// - /// The . - /// - /// - /// The . - /// - public static implicit operator RadBulletGraph(AppiumWebElement element) - { - return new RadBulletGraph(element as WindowsElement); - } + /// + /// Allows conversion of a to the without direct casting. + /// + /// + /// The . + /// + /// + /// The . + /// + public static implicit operator RadBulletGraph(AppiumWebElement element) + { + return new RadBulletGraph(element as WindowsElement); + } - /// - /// Allows conversion of a to the without direct casting. - /// - /// - /// The . - /// - /// - /// The . - /// - public static implicit operator RadBulletGraph(RemoteWebElement element) - { - return new RadBulletGraph(element as WindowsElement); - } + /// + /// Allows conversion of a to the without direct casting. + /// + /// + /// The . + /// + /// + /// The . + /// + public static implicit operator RadBulletGraph(RemoteWebElement element) + { + return new RadBulletGraph(element as WindowsElement); } } \ No newline at end of file diff --git a/src/Legerity.Telerik.Uwp/RadBusyIndicator.cs b/src/Legerity.Telerik.Uwp/RadBusyIndicator.cs index e3f58ad3..c825b2a9 100644 --- a/src/Legerity.Telerik.Uwp/RadBusyIndicator.cs +++ b/src/Legerity.Telerik.Uwp/RadBusyIndicator.cs @@ -1,72 +1,73 @@ -namespace Legerity.Windows.Elements.Telerik +namespace Legerity.Windows.Elements.Telerik; + +using OpenQA.Selenium; +using OpenQA.Selenium.Appium; +using OpenQA.Selenium.Appium.Windows; +using OpenQA.Selenium.Remote; + +/// +/// Defines a wrapper for the Telerik UWP RadBusyIndicator control. +/// +public class RadBusyIndicator : WindowsElementWrapper { - using OpenQA.Selenium.Appium; - using OpenQA.Selenium.Appium.Windows; - using OpenQA.Selenium.Remote; + private const string OnValue = "On"; /// - /// Defines a wrapper for the Telerik UWP RadBusyIndicator control. + /// Initializes a new instance of the class. /// - public class RadBusyIndicator : WindowsElementWrapper + /// + /// The reference. + /// + public RadBusyIndicator(WindowsElement element) + : base(element) { - private const string OnValue = "On"; - - /// - /// Initializes a new instance of the class. - /// - /// - /// The reference. - /// - public RadBusyIndicator(WindowsElement element) - : base(element) - { - } + } - /// - /// Gets a value indicating whether the busy indicator is on. - /// - public virtual bool IsOn => this.GetAttribute("ItemStatus") == OnValue; + /// + /// Gets a value indicating whether the busy indicator is on. + /// + /// Thrown when an element is no longer valid in the document DOM. + public virtual bool IsOn => this.GetAttribute("ItemStatus") == OnValue; - /// - /// Allows conversion of a to the without direct casting. - /// - /// - /// The . - /// - /// - /// The . - /// - public static implicit operator RadBusyIndicator(WindowsElement element) - { - return new RadBusyIndicator(element); - } + /// + /// Allows conversion of a to the without direct casting. + /// + /// + /// The . + /// + /// + /// The . + /// + public static implicit operator RadBusyIndicator(WindowsElement element) + { + return new RadBusyIndicator(element); + } - /// - /// Allows conversion of a to the without direct casting. - /// - /// - /// The . - /// - /// - /// The . - /// - public static implicit operator RadBusyIndicator(AppiumWebElement element) - { - return new RadBusyIndicator(element as WindowsElement); - } + /// + /// Allows conversion of a to the without direct casting. + /// + /// + /// The . + /// + /// + /// The . + /// + public static implicit operator RadBusyIndicator(AppiumWebElement element) + { + return new RadBusyIndicator(element as WindowsElement); + } - /// - /// Allows conversion of a to the without direct casting. - /// - /// - /// The . - /// - /// - /// The . - /// - public static implicit operator RadBusyIndicator(RemoteWebElement element) - { - return new RadBusyIndicator(element as WindowsElement); - } + /// + /// Allows conversion of a to the without direct casting. + /// + /// + /// The . + /// + /// + /// The . + /// + public static implicit operator RadBusyIndicator(RemoteWebElement element) + { + return new RadBusyIndicator(element as WindowsElement); } } \ No newline at end of file diff --git a/src/Legerity.Telerik.Uwp/RadNumericBox.cs b/src/Legerity.Telerik.Uwp/RadNumericBox.cs index 89135cb2..b25451b3 100644 --- a/src/Legerity.Telerik.Uwp/RadNumericBox.cs +++ b/src/Legerity.Telerik.Uwp/RadNumericBox.cs @@ -1,159 +1,178 @@ -namespace Legerity.Windows.Elements.Telerik +namespace Legerity.Windows.Elements.Telerik; + +using System; +using Legerity.Windows.Elements.Core; +using Legerity.Windows.Extensions; +using OpenQA.Selenium; +using OpenQA.Selenium.Appium; +using OpenQA.Selenium.Appium.Windows; +using OpenQA.Selenium.Remote; + +/// +/// Defines a wrapper for the Telerik UWP RadNumericBox control. +/// +public class RadNumericBox : WindowsElementWrapper { - using System; - using Legerity.Windows.Elements.Core; - using Legerity.Windows.Extensions; - using OpenQA.Selenium; - using OpenQA.Selenium.Appium; - using OpenQA.Selenium.Appium.Windows; - using OpenQA.Selenium.Remote; + /// + /// Initializes a new instance of the class. + /// + /// + /// The reference. + /// + public RadNumericBox(WindowsElement element) + : base(element) + { + } + + /// + /// Gets the minimum value of the RadNumericBox. + /// + /// Thrown when an element is no longer valid in the document DOM. + public virtual double Minimum => this.GetRangeMinimum(); + + /// + /// Gets the maximum value of the RadNumericBox. + /// + /// Thrown when an element is no longer valid in the document DOM. + public virtual double Maximum => this.GetRangeMaximum(); + + /// + /// Gets the small change (step) value of the RadNumericBox. + /// + /// Thrown when an element is no longer valid in the document DOM. + public virtual double SmallChange => this.GetRangeSmallChange(); + + /// + /// Gets the value of the RadNumericBox. + /// + /// Thrown when an element is no longer valid in the document DOM. + public virtual double Value => this.GetRangeValue(); + + /// + /// Gets a value indicating whether the control is in a readonly state. + /// + /// Thrown when an element is no longer valid in the document DOM. + public virtual bool IsReadonly => this.IsRangeReadonly(); /// - /// Defines a wrapper for the Telerik UWP RadNumericBox control. + /// Gets the element associated with the increase button. /// - public class RadNumericBox : WindowsElementWrapper + /// Thrown when no element matches the expected locator. + public virtual Button Increase => this.FindElement(WindowsByExtras.AutomationId("PART_IncreaseButton")); + + /// + /// Gets the element associated with the decrease button. + /// + /// Thrown when no element matches the expected locator. + public virtual Button DecreaseButton => this.FindElement(WindowsByExtras.AutomationId("PART_DecreaseButton")); + + /// + /// Gets the element associated with the input text box. + /// + /// Thrown when no element matches the expected locator. + public virtual TextBox InputBox => this.FindElement(WindowsByExtras.AutomationId("PART_TextBox")); + + /// + /// Allows conversion of a to the without direct casting. + /// + /// + /// The . + /// + /// + /// The . + /// + public static implicit operator RadNumericBox(WindowsElement element) { - /// - /// Initializes a new instance of the class. - /// - /// - /// The reference. - /// - public RadNumericBox(WindowsElement element) - : base(element) - { - } + return new RadNumericBox(element); + } - /// - /// Gets the minimum value of the RadNumericBox. - /// - public virtual double Minimum => this.GetRangeMinimum(); - - /// - /// Gets the maximum value of the RadNumericBox. - /// - public virtual double Maximum => this.GetRangeMaximum(); - - /// - /// Gets the small change (step) value of the RadNumericBox. - /// - public virtual double SmallChange => this.GetRangeSmallChange(); - - /// - /// Gets the value of the RadNumericBox. - /// - public virtual double Value => this.GetRangeValue(); - - /// - /// Gets a value indicating whether the control is in a readonly state. - /// - public virtual bool IsReadonly => this.IsRangeReadonly(); - - /// - /// Gets the element associated with the increase button. - /// - public virtual Button Increase => this.Element.FindElement(WindowsByExtras.AutomationId("PART_IncreaseButton")); - - /// - /// Gets the element associated with the decrease button. - /// - public virtual Button DecreaseButton => this.Element.FindElement(WindowsByExtras.AutomationId("PART_DecreaseButton")); - - /// - /// Gets the element associated with the input text box. - /// - public virtual TextBox InputBox => this.Element.FindElement(WindowsByExtras.AutomationId("PART_TextBox")); - - /// - /// Allows conversion of a to the without direct casting. - /// - /// - /// The . - /// - /// - /// The . - /// - public static implicit operator RadNumericBox(WindowsElement element) - { - return new RadNumericBox(element); - } + /// + /// Allows conversion of a to the without direct casting. + /// + /// + /// The . + /// + /// + /// The . + /// + public static implicit operator RadNumericBox(AppiumWebElement element) + { + return new RadNumericBox(element as WindowsElement); + } - /// - /// Allows conversion of a to the without direct casting. - /// - /// - /// The . - /// - /// - /// The . - /// - public static implicit operator RadNumericBox(AppiumWebElement element) - { - return new RadNumericBox(element as WindowsElement); - } + /// + /// Allows conversion of a to the without direct casting. + /// + /// + /// The . + /// + /// + /// The . + /// + public static implicit operator RadNumericBox(RemoteWebElement element) + { + return new RadNumericBox(element as WindowsElement); + } - /// - /// Allows conversion of a to the without direct casting. - /// - /// - /// The . - /// - /// - /// The . - /// - public static implicit operator RadNumericBox(RemoteWebElement element) - { - return new RadNumericBox(element as WindowsElement); - } + /// + /// Sets the value of the RadNumericBox. + /// + /// + /// The value. + /// + /// + /// Thrown when the value is out of the minimum and maximum range of the RadNumericBox. + /// + /// Thrown when an element is not enabled. + /// Thrown when an element is no longer valid in the document DOM. + /// Thrown when an element is not visible. + /// Thrown when no element matches the expected locator. + public virtual void SetValue(double value) + { + double min = this.Minimum; + double max = this.Maximum; - /// - /// Sets the value of the RadNumericBox. - /// - /// - /// The value. - /// - /// - /// Thrown if the value is out of the minimum and maximum range of the RadNumericBox. - /// - public virtual void SetValue(double value) + if (value < this.Minimum) { - double min = this.Minimum; - double max = this.Maximum; - - if (value < this.Minimum) - { - throw new ArgumentOutOfRangeException( - nameof(value), - value, - $"Value must be greater than or equal to the minimum value {min}"); - } - - if (value > this.Maximum) - { - throw new ArgumentOutOfRangeException( - nameof(value), - value, - $"Value must be less than or equal to the maximum value {max}"); - } - - this.InputBox.SetText(value.ToString()); - this.InputBox.Element.SendKeys(Keys.Enter); + throw new ArgumentOutOfRangeException( + nameof(value), + value, + $"Value must be greater than or equal to the minimum value {min}"); } - /// - /// Increases the number box value by the value. - /// - public virtual void Increment() + if (value > this.Maximum) { - this.Increase.Click(); + throw new ArgumentOutOfRangeException( + nameof(value), + value, + $"Value must be less than or equal to the maximum value {max}"); } - /// - /// Decreases the number box value by the value. - /// - public virtual void Decrement() - { - this.DecreaseButton.Click(); - } + this.InputBox.SetText(value.ToString()); + this.InputBox.Element.SendKeys(Keys.Enter); + } + + /// + /// Increases the number box value by the value. + /// + /// Thrown when no element matches the expected locator. + /// Thrown when an element is not enabled. + /// Thrown when an element is not visible. + /// Thrown when an element is no longer valid in the document DOM. + public virtual void Increment() + { + this.Increase.Click(); + } + + /// + /// Decreases the number box value by the value. + /// + /// Thrown when no element matches the expected locator. + /// Thrown when an element is not enabled. + /// Thrown when an element is not visible. + /// Thrown when an element is no longer valid in the document DOM. + public virtual void Decrement() + { + this.DecreaseButton.Click(); } } \ No newline at end of file diff --git a/src/Legerity.WCT/BladeView.cs b/src/Legerity.WCT/BladeView.cs index bdba186a..f2ed3a38 100644 --- a/src/Legerity.WCT/BladeView.cs +++ b/src/Legerity.WCT/BladeView.cs @@ -1,116 +1,125 @@ -namespace Legerity.Windows.Elements.WCT -{ - using System.Collections.Generic; - using System.Linq; - using Legerity.Windows.Extensions; - using OpenQA.Selenium; - using OpenQA.Selenium.Appium; - using OpenQA.Selenium.Appium.Windows; - using OpenQA.Selenium.Remote; +namespace Legerity.Windows.Elements.WCT; + +using System.Collections.Generic; +using System.Linq; +using Legerity.Windows.Extensions; +using OpenQA.Selenium; +using OpenQA.Selenium.Appium; +using OpenQA.Selenium.Appium.Windows; +using OpenQA.Selenium.Remote; +/// +/// Defines a wrapper for the Windows Community Toolkit BladeView control. +/// +public class BladeView : WindowsElementWrapper +{ /// - /// Defines a wrapper for the Windows Community Toolkit BladeView control. + /// Initializes a new instance of the class. /// - public class BladeView : WindowsElementWrapper + /// + /// The reference. + /// + public BladeView(WindowsElement element) + : base(element) { - /// - /// Initializes a new instance of the class. - /// - /// - /// The reference. - /// - public BladeView(WindowsElement element) - : base(element) - { - } + } - /// - /// Gets the UI components associated with the child blades. - /// - public virtual IEnumerable Blades => - this.Element.FindElements(By.ClassName("BladeItem")) - .Select(element => new BladeViewItem(this, element as WindowsElement)); + /// + /// Gets the UI components associated with the child blades. + /// + public virtual IEnumerable Blades => + this.Element.FindElements(By.ClassName("BladeItem")) + .Select(element => new BladeViewItem(this, element as WindowsElement)); - /// - /// Allows conversion of a to the without direct casting. - /// - /// - /// The . - /// - /// - /// The . - /// - public static implicit operator BladeView(WindowsElement element) - { - return new BladeView(element); - } + /// + /// Allows conversion of a to the without direct casting. + /// + /// + /// The . + /// + /// + /// The . + /// + public static implicit operator BladeView(WindowsElement element) + { + return new BladeView(element); + } - /// - /// Allows conversion of a to the without direct casting. - /// - /// - /// The . - /// - /// - /// The . - /// - public static implicit operator BladeView(AppiumWebElement element) - { - return new BladeView(element as WindowsElement); - } + /// + /// Allows conversion of a to the without direct casting. + /// + /// + /// The . + /// + /// + /// The . + /// + public static implicit operator BladeView(AppiumWebElement element) + { + return new BladeView(element as WindowsElement); + } - /// - /// Allows conversion of a to the without direct casting. - /// - /// - /// The . - /// - /// - /// The . - /// - public static implicit operator BladeView(RemoteWebElement element) - { - return new BladeView(element as WindowsElement); - } + /// + /// Allows conversion of a to the without direct casting. + /// + /// + /// The . + /// + /// + /// The . + /// + public static implicit operator BladeView(RemoteWebElement element) + { + return new BladeView(element as WindowsElement); + } - /// - /// Retrieves a by the given name. - /// - /// The name of the blade to retrieve. - /// A instance if found; otherwise, null. - public virtual BladeViewItem GetBlade(string name) - { - return this.Blades.FirstOrDefault(element => element.Element.VerifyNameOrAutomationIdEquals(name)); - } + /// + /// Retrieves a by the given name. + /// + /// The name of the blade to retrieve. + /// A instance if found; otherwise, null. + /// Thrown when an element is no longer valid in the document DOM. + public virtual BladeViewItem GetBlade(string name) + { + return this.Blades.FirstOrDefault(element => element.Element.VerifyNameOrAutomationIdEquals(name)); + } - /// - /// Retrieves a by the given partial name. - /// - /// The partial name of the blade to retrieve. - /// A instance if found; otherwise, null. - public virtual BladeViewItem GetBladeByPartialName(string partialName) - { - return this.Blades.FirstOrDefault(element => element.Element.VerifyNameOrAutomationIdContains(partialName)); - } + /// + /// Retrieves a by the given partial name. + /// + /// The partial name of the blade to retrieve. + /// A instance if found; otherwise, null. + /// Thrown when an element is no longer valid in the document DOM. + public virtual BladeViewItem GetBladeByPartialName(string partialName) + { + return this.Blades.FirstOrDefault(element => element.Element.VerifyNameOrAutomationIdContains(partialName)); + } - /// - /// Closes an open blade by name. - /// - /// The name of the blade to close. - public virtual void CloseBlade(string name) - { - BladeViewItem blade = this.GetBlade(name); - blade.Close(); - } + /// + /// Closes an open blade by name. + /// + /// The name of the blade to close. + /// Thrown when an element is no longer valid in the document DOM. + /// Thrown when no element matches the expected locator. + /// Thrown when an element is not enabled. + /// Thrown when an element is not visible. + public virtual void CloseBlade(string name) + { + BladeViewItem blade = this.GetBlade(name); + blade.Close(); + } - /// - /// Closes an open blade by partial name. - /// - /// The partial name of the blade to close. - public virtual void CloseBladeByPartialName(string partialName) - { - BladeViewItem blade = this.GetBladeByPartialName(partialName); - blade.Close(); - } + /// + /// Closes an open blade by partial name. + /// + /// The partial name of the blade to close. + /// Thrown when an element is no longer valid in the document DOM. + /// Thrown when no element matches the expected locator. + /// Thrown when an element is not enabled. + /// Thrown when an element is not visible. + public virtual void CloseBladeByPartialName(string partialName) + { + BladeViewItem blade = this.GetBladeByPartialName(partialName); + blade.Close(); } } \ No newline at end of file diff --git a/src/Legerity.WCT/BladeViewItem.cs b/src/Legerity.WCT/BladeViewItem.cs index 1b165675..05dd3948 100644 --- a/src/Legerity.WCT/BladeViewItem.cs +++ b/src/Legerity.WCT/BladeViewItem.cs @@ -1,113 +1,119 @@ -namespace Legerity.Windows.Elements.WCT +namespace Legerity.Windows.Elements.WCT; + +using System; +using Legerity.Windows.Elements.Core; +using OpenQA.Selenium; +using OpenQA.Selenium.Appium; +using OpenQA.Selenium.Appium.Windows; +using OpenQA.Selenium.Remote; + +/// +/// Defines a wrapper for the Windows Community Toolkit BladeViewItem control. +/// +public class BladeViewItem : WindowsElementWrapper { - using System; - using Legerity.Windows.Elements.Core; - using OpenQA.Selenium.Appium; - using OpenQA.Selenium.Appium.Windows; - using OpenQA.Selenium.Remote; + private readonly WeakReference parentBladeViewReference; /// - /// Defines a wrapper for the Windows Community Toolkit BladeViewItem control. + /// Initializes a new instance of the class. /// - public class BladeViewItem : WindowsElementWrapper + /// + /// The reference. + /// + public BladeViewItem(WindowsElement element) + : this(null, element) { - private readonly WeakReference parentBladeViewReference; - - /// - /// Initializes a new instance of the class. - /// - /// - /// The reference. - /// - public BladeViewItem(WindowsElement element) - : this(null, element) - { - } + } - /// - /// Initializes a new instance of the class. - /// - /// - /// The parent . - /// - /// - /// The reference. - /// - public BladeViewItem( - BladeView parentBladeView, - WindowsElement element) - : base(element) + /// + /// Initializes a new instance of the class. + /// + /// + /// The parent . + /// + /// + /// The reference. + /// + public BladeViewItem( + BladeView parentBladeView, + WindowsElement element) + : base(element) + { + if (parentBladeView != null) { - if (parentBladeView != null) - { - this.parentBladeViewReference = new WeakReference(parentBladeView); - } + this.parentBladeViewReference = new WeakReference(parentBladeView); } + } - /// Gets the original parent reference object. - public BladeView ParentMenuBar => - this.parentBladeViewReference is { IsAlive: true } - ? this.parentBladeViewReference.Target as BladeView - : null; + /// Gets the original parent reference object. + public BladeView ParentMenuBar => + this.parentBladeViewReference is { IsAlive: true } + ? this.parentBladeViewReference.Target as BladeView + : null; - /// - /// Gets the element associated with the blade enlarge option. - /// - public virtual Button EnlargeButton => this.Element.FindElement(WindowsByExtras.AutomationId("EnlargeButton")); + /// + /// Gets the element associated with the blade enlarge option. + /// + /// Thrown when no element matches the expected locator. + public virtual Button EnlargeButton => this.FindElement(WindowsByExtras.AutomationId("EnlargeButton")); - /// - /// Gets the element associated with the blade close option. - /// - public virtual Button CloseButton => this.Element.FindElement(WindowsByExtras.AutomationId("CloseButton")); + /// + /// Gets the element associated with the blade close option. + /// + /// Thrown when no element matches the expected locator. + public virtual Button CloseButton => this.FindElement(WindowsByExtras.AutomationId("CloseButton")); - /// - /// Allows conversion of a to the without direct casting. - /// - /// - /// The . - /// - /// - /// The . - /// - public static implicit operator BladeViewItem(WindowsElement element) - { - return new BladeViewItem(element); - } + /// + /// Allows conversion of a to the without direct casting. + /// + /// + /// The . + /// + /// + /// The . + /// + public static implicit operator BladeViewItem(WindowsElement element) + { + return new BladeViewItem(element); + } - /// - /// Allows conversion of a to the without direct casting. - /// - /// - /// The . - /// - /// - /// The . - /// - public static implicit operator BladeViewItem(AppiumWebElement element) - { - return new BladeViewItem(element as WindowsElement); - } + /// + /// Allows conversion of a to the without direct casting. + /// + /// + /// The . + /// + /// + /// The . + /// + public static implicit operator BladeViewItem(AppiumWebElement element) + { + return new BladeViewItem(element as WindowsElement); + } - /// - /// Allows conversion of a to the without direct casting. - /// - /// - /// The . - /// - /// - /// The . - /// - public static implicit operator BladeViewItem(RemoteWebElement element) - { - return new BladeViewItem(element as WindowsElement); - } + /// + /// Allows conversion of a to the without direct casting. + /// + /// + /// The . + /// + /// + /// The . + /// + public static implicit operator BladeViewItem(RemoteWebElement element) + { + return new BladeViewItem(element as WindowsElement); + } - /// - /// Closes the blade item. - /// - public virtual void Close() - { - this.CloseButton.Click(); - } + /// + /// Closes the blade item. + /// + /// Thrown when no element matches the expected locator. + /// Thrown when an element is not enabled. + /// Thrown when an element is not visible. + /// Thrown when an element is no longer valid in the document DOM. + public virtual void Close() + { + this.CloseButton.Click(); } } \ No newline at end of file diff --git a/src/Legerity.WCT/Carousel.cs b/src/Legerity.WCT/Carousel.cs index 8873850a..a113eb6f 100644 --- a/src/Legerity.WCT/Carousel.cs +++ b/src/Legerity.WCT/Carousel.cs @@ -1,151 +1,168 @@ -namespace Legerity.Windows.Elements.WCT +namespace Legerity.Windows.Elements.WCT; + +using System; +using System.Collections.ObjectModel; +using System.Linq; +using Legerity.Exceptions; +using Legerity.Windows.Elements.Core; +using Legerity.Windows.Extensions; +using OpenQA.Selenium; +using OpenQA.Selenium.Appium; +using OpenQA.Selenium.Appium.Windows; +using OpenQA.Selenium.Remote; + +/// +/// Defines a wrapper for the Windows Community Toolkit Carousel control. +/// +public class Carousel : WindowsElementWrapper { - using System; - using System.Collections.ObjectModel; - using System.Linq; - using Legerity.Windows.Elements.Core; - using Legerity.Windows.Extensions; - using OpenQA.Selenium; - using OpenQA.Selenium.Appium; - using OpenQA.Selenium.Appium.Windows; - using OpenQA.Selenium.Remote; + private readonly By carouselItemLocator = By.ClassName("CarouselItem"); /// - /// Defines a wrapper for the Windows Community Toolkit Carousel control. + /// Initializes a new instance of the class. /// - public class Carousel : WindowsElementWrapper + /// + /// The reference. + /// + public Carousel(WindowsElement element) + : base(element) { - private readonly By carouselItemLocator = By.ClassName("CarouselItem"); - - /// - /// Initializes a new instance of the class. - /// - /// - /// The reference. - /// - public Carousel(WindowsElement element) - : base(element) - { - } + } - /// - /// Gets the collection of items associated with the carousel. - /// - public virtual ReadOnlyCollection Items => - this.Element.FindElements(this.carouselItemLocator); - - /// - /// Gets the element associated with the currently selected item. - /// - public virtual AppiumWebElement SelectedItem => this.Items.FirstOrDefault(i => i.IsSelected()); - - /// - /// Gets the index of the element associated with the currently selected item. - /// - public virtual int SelectedIndex => this.Items.IndexOf(this.SelectedItem); - - /// - /// Allows conversion of a to the without direct casting. - /// - /// - /// The . - /// - /// - /// The . - /// - public static implicit operator Carousel(WindowsElement element) - { - return new Carousel(element); - } + /// + /// Gets the collection of items associated with the carousel. + /// + public virtual ReadOnlyCollection Items => + this.Element.FindElements(this.carouselItemLocator); - /// - /// Allows conversion of a to the without direct casting. - /// - /// - /// The . - /// - /// - /// The . - /// - public static implicit operator Carousel(AppiumWebElement element) - { - return new Carousel(element as WindowsElement); - } + /// + /// Gets the element associated with the currently selected item. + /// + /// Thrown when an element is no longer valid in the document DOM. + public virtual AppiumWebElement SelectedItem => this.Items.FirstOrDefault(i => i.IsSelected()); - /// - /// Allows conversion of a to the without direct casting. - /// - /// - /// The . - /// - /// - /// The . - /// - public static implicit operator Carousel(RemoteWebElement element) - { - return new Carousel(element as WindowsElement); - } + /// + /// Gets the index of the element associated with the currently selected item. + /// + /// Thrown when an element is no longer valid in the document DOM. + public virtual int SelectedIndex => this.Items.IndexOf(this.SelectedItem); - /// - /// Clicks on an item in the carousel with the specified item name. - /// - /// - /// The name of the item to click. - /// - public virtual void SelectItem(string name) - { - this.VerifyElementsShown(this.carouselItemLocator, TimeSpan.FromSeconds(2)); + /// + /// Allows conversion of a to the without direct casting. + /// + /// + /// The . + /// + /// + /// The . + /// + public static implicit operator Carousel(WindowsElement element) + { + return new Carousel(element); + } - int index = this.Items.IndexOf(this.Items.FirstOrDefault(element => - element.VerifyNameOrAutomationIdEquals(name))); + /// + /// Allows conversion of a to the without direct casting. + /// + /// + /// The . + /// + /// + /// The . + /// + public static implicit operator Carousel(AppiumWebElement element) + { + return new Carousel(element as WindowsElement); + } - this.SelectItemAtIndex(index); - } + /// + /// Allows conversion of a to the without direct casting. + /// + /// + /// The . + /// + /// + /// The . + /// + public static implicit operator Carousel(RemoteWebElement element) + { + return new Carousel(element as WindowsElement); + } - /// - /// Clicks on an item in the carousel with the specified partial item name. - /// - /// - /// The partial name of the item to click. - /// - public virtual void SelectItemByPartialName(string partialName) - { - this.VerifyElementsShown(this.carouselItemLocator, TimeSpan.FromSeconds(2)); + /// + /// Clicks on an item in the carousel with the specified item name. + /// + /// + /// The name of the item to click. + /// + /// Thrown when no elements are shown for the expected locator. + /// Thrown when an element is no longer valid in the document DOM. + /// Thrown when an element is not enabled. + /// Thrown when an element is not visible. + public virtual void SelectItem(string name) + { + this.VerifyElementsShown(this.carouselItemLocator, TimeSpan.FromSeconds(2)); - int index = this.Items.IndexOf(this.Items.FirstOrDefault(element => - element.VerifyNameOrAutomationIdContains(partialName))); + int index = this.Items.IndexOf(this.Items.FirstOrDefault(element => + element.VerifyNameOrAutomationIdEquals(name))); - this.SelectItemAtIndex(index); - } + this.SelectItemAtIndex(index); + } - /// - /// Clicks on an item in the carousel at the specified index. - /// - /// - /// The index of the item to click. - /// - /// Cannot select an element that is outside the range of items available. - public virtual void SelectItem(int index) - { - this.VerifyElementsShown(this.carouselItemLocator, TimeSpan.FromSeconds(2)); + /// + /// Clicks on an item in the carousel with the specified partial item name. + /// + /// + /// The partial name of the item to click. + /// + /// Thrown when no elements are shown for the expected locator. + /// Thrown when an element is no longer valid in the document DOM. + /// Thrown when an element is not enabled. + /// Thrown when an element is not visible. + public virtual void SelectItemByPartialName(string partialName) + { + this.VerifyElementsShown(this.carouselItemLocator, TimeSpan.FromSeconds(2)); + + int index = this.Items.IndexOf(this.Items.FirstOrDefault(element => + element.VerifyNameOrAutomationIdContains(partialName))); - if (index > this.Items.Count - 1) - { - throw new IndexOutOfRangeException( - "Cannot select an element that is outside the range of items available."); - } + this.SelectItemAtIndex(index); + } + + /// + /// Clicks on an item in the carousel at the specified index. + /// + /// + /// The index of the item to click. + /// + /// Thrown when an element is selected that is outside the range of items available. + /// Thrown when no elements are shown for the expected locator. + /// Thrown when an element is no longer valid in the document DOM. + /// Thrown when an element is not enabled. + /// Thrown when an element is not visible. + public virtual void SelectItem(int index) + { + this.VerifyElementsShown(this.carouselItemLocator, TimeSpan.FromSeconds(2)); - this.SelectItemAtIndex(index); + if (index > this.Items.Count - 1) + { + throw new IndexOutOfRangeException( + "Cannot select an element that is outside the range of items available."); } - private void SelectItemAtIndex(int index) + this.SelectItemAtIndex(index); + } + + /// Thrown when an element is no longer valid in the document DOM. + /// Thrown when an element is not enabled. + /// Thrown when an element is not visible. + private void SelectItemAtIndex(int index) + { + int selectedIndex = this.SelectedIndex; + while (Math.Abs(index - selectedIndex) > double.Epsilon) { - int selectedIndex = this.SelectedIndex; - while (Math.Abs(index - selectedIndex) > double.Epsilon) - { - this.Element.SendKeys(selectedIndex < index ? Keys.ArrowRight : Keys.ArrowLeft); - selectedIndex = this.SelectedIndex; - } + this.Element.SendKeys(selectedIndex < index ? Keys.ArrowRight : Keys.ArrowLeft); + selectedIndex = this.SelectedIndex; } } } \ No newline at end of file diff --git a/src/Legerity.WCT/Expander.cs b/src/Legerity.WCT/Expander.cs index b65e08bd..3d7d02f5 100644 --- a/src/Legerity.WCT/Expander.cs +++ b/src/Legerity.WCT/Expander.cs @@ -1,103 +1,113 @@ -namespace Legerity.Windows.Elements.WCT -{ - using Legerity.Windows.Elements.Core; - using Legerity.Windows.Extensions; - using OpenQA.Selenium.Appium; - using OpenQA.Selenium.Appium.Windows; - using OpenQA.Selenium.Remote; +namespace Legerity.Windows.Elements.WCT; + +using Legerity.Windows.Elements.Core; +using Legerity.Windows.Extensions; +using OpenQA.Selenium; +using OpenQA.Selenium.Appium; +using OpenQA.Selenium.Appium.Windows; +using OpenQA.Selenium.Remote; +/// +/// Defines a wrapper for the Windows Community Toolkit Expander control. +/// +public class Expander : WindowsElementWrapper +{ /// - /// Defines a wrapper for the Windows Community Toolkit Expander control. + /// Initializes a new instance of the class. /// - public class Expander : WindowsElementWrapper + /// + /// The reference. + /// + public Expander(WindowsElement element) + : base(element) { - /// - /// Initializes a new instance of the class. - /// - /// - /// The reference. - /// - public Expander(WindowsElement element) - : base(element) - { - } + } - /// - /// Gets a value indicating whether the expander has the content expanded (visible). - /// - public virtual bool IsExpanded => this.GetToggleState() == ToggleState.Checked; + /// + /// Gets a value indicating whether the expander has the content expanded (visible). + /// + /// Thrown when an element is no longer valid in the document DOM. + public virtual bool IsExpanded => this.GetToggleState() == ToggleState.Checked; - /// - /// Gets the associated with the expander. - /// - public virtual ToggleButton ToggleButton => this.Element.FindElement(WindowsByExtras.AutomationId("PART_ExpanderToggleButton")); + /// + /// Gets the associated with the expander. + /// + /// Thrown when no element matches the expected locator. + public virtual ToggleButton ToggleButton => this.FindElement(WindowsByExtras.AutomationId("PART_ExpanderToggleButton")); - /// - /// Allows conversion of a to the without direct casting. - /// - /// - /// The . - /// - /// - /// The . - /// - public static implicit operator Expander(WindowsElement element) - { - return new Expander(element); - } + /// + /// Allows conversion of a to the without direct casting. + /// + /// + /// The . + /// + /// + /// The . + /// + public static implicit operator Expander(WindowsElement element) + { + return new Expander(element); + } - /// - /// Allows conversion of a to the without direct casting. - /// - /// - /// The . - /// - /// - /// The . - /// - public static implicit operator Expander(AppiumWebElement element) - { - return new Expander(element as WindowsElement); - } + /// + /// Allows conversion of a to the without direct casting. + /// + /// + /// The . + /// + /// + /// The . + /// + public static implicit operator Expander(AppiumWebElement element) + { + return new Expander(element as WindowsElement); + } - /// - /// Allows conversion of a to the without direct casting. - /// - /// - /// The . - /// - /// - /// The . - /// - public static implicit operator Expander(RemoteWebElement element) - { - return new Expander(element as WindowsElement); - } + /// + /// Allows conversion of a to the without direct casting. + /// + /// + /// The . + /// + /// + /// The . + /// + public static implicit operator Expander(RemoteWebElement element) + { + return new Expander(element as WindowsElement); + } - /// - /// Expands the content of the expander. - /// - public virtual void Expand() + /// + /// Expands the content of the expander. + /// + /// Thrown when no element matches the expected locator. + /// Thrown when an element is not enabled. + /// Thrown when an element is not visible. + /// Thrown when an element is no longer valid in the document DOM. + public virtual void Expand() + { + if (this.IsExpanded) { - if (this.IsExpanded) - { - return; - } - - this.ToggleButton.Click(); + return; } - /// - /// Collapses the content of the expander. - /// - public virtual void Collapse() - { - if (!this.IsExpanded) - { - return; - } + this.ToggleButton.Click(); + } - this.ToggleButton.Click(); + /// + /// Collapses the content of the expander. + /// + /// Thrown when no element matches the expected locator. + /// Thrown when an element is not enabled. + /// Thrown when an element is not visible. + /// Thrown when an element is no longer valid in the document DOM. + public virtual void Collapse() + { + if (!this.IsExpanded) + { + return; } + + this.ToggleButton.Click(); } -} +} \ No newline at end of file diff --git a/src/Legerity.WCT/InAppNotification.cs b/src/Legerity.WCT/InAppNotification.cs index 9fc29cc0..e57eb252 100644 --- a/src/Legerity.WCT/InAppNotification.cs +++ b/src/Legerity.WCT/InAppNotification.cs @@ -1,88 +1,94 @@ -namespace Legerity.Windows.Elements.WCT -{ - using System.Linq; - using Legerity.Windows.Elements.Core; - using OpenQA.Selenium.Appium; - using OpenQA.Selenium.Appium.Windows; - using OpenQA.Selenium.Remote; +namespace Legerity.Windows.Elements.WCT; + +using System.Linq; +using Legerity.Windows.Elements.Core; +using OpenQA.Selenium; +using OpenQA.Selenium.Appium; +using OpenQA.Selenium.Appium.Windows; +using OpenQA.Selenium.Remote; +/// +/// Defines a wrapper for the Windows Community Toolkit InAppNotification control. +/// +public class InAppNotification : WindowsElementWrapper +{ /// - /// Defines a wrapper for the Windows Community Toolkit InAppNotification control. + /// Initializes a new instance of the class. /// - public class InAppNotification : WindowsElementWrapper + /// + /// The reference. + /// + public InAppNotification(WindowsElement element) + : base(element) { - /// - /// Initializes a new instance of the class. - /// - /// - /// The reference. - /// - public InAppNotification(WindowsElement element) - : base(element) - { - } + } - /// - /// Gets the dismiss button. - /// - public virtual Button DismissButton => this.Element.FindElement(WindowsByExtras.AutomationId("PART_DismissButton")); + /// + /// Gets the dismiss button. + /// + /// Thrown when no element matches the expected locator. + public virtual Button DismissButton => this.FindElement(WindowsByExtras.AutomationId("PART_DismissButton")); - /// - /// Gets the message displayed. - /// - /// Note, this only works if the Content is based on a or if the ContentTemplate includes a TextBlock element with the message. - /// - /// - public virtual string Message => this.Element.FindElementsByClassName("TextBlock").FirstOrDefault()?.Text; + /// + /// Gets the message displayed. + /// + /// Note, this only works if the Content is based on a or if the ContentTemplate includes a TextBlock element with the message. + /// + /// + /// Thrown when an element is no longer valid in the document DOM. + public virtual string Message => this.Element.FindElementsByClassName("TextBlock").FirstOrDefault()?.Text; - /// - /// Allows conversion of a to the without direct casting. - /// - /// - /// The . - /// - /// - /// The . - /// - public static implicit operator InAppNotification(WindowsElement element) - { - return new InAppNotification(element); - } + /// + /// Allows conversion of a to the without direct casting. + /// + /// + /// The . + /// + /// + /// The . + /// + public static implicit operator InAppNotification(WindowsElement element) + { + return new InAppNotification(element); + } - /// - /// Allows conversion of a to the without direct casting. - /// - /// - /// The . - /// - /// - /// The . - /// - public static implicit operator InAppNotification(AppiumWebElement element) - { - return new InAppNotification(element as WindowsElement); - } + /// + /// Allows conversion of a to the without direct casting. + /// + /// + /// The . + /// + /// + /// The . + /// + public static implicit operator InAppNotification(AppiumWebElement element) + { + return new InAppNotification(element as WindowsElement); + } - /// - /// Allows conversion of a to the without direct casting. - /// - /// - /// The . - /// - /// - /// The . - /// - public static implicit operator InAppNotification(RemoteWebElement element) - { - return new InAppNotification(element as WindowsElement); - } + /// + /// Allows conversion of a to the without direct casting. + /// + /// + /// The . + /// + /// + /// The . + /// + public static implicit operator InAppNotification(RemoteWebElement element) + { + return new InAppNotification(element as WindowsElement); + } - /// - /// Dismissed the in-app notification. - /// - public virtual void Dismiss() - { - this.DismissButton.Click(); - } + /// + /// Dismissed the in-app notification. + /// + /// Thrown when no element matches the expected locator. + /// Thrown when an element is not enabled. + /// Thrown when an element is not visible. + /// Thrown when an element is no longer valid in the document DOM. + public virtual void Dismiss() + { + this.DismissButton.Click(); } -} +} \ No newline at end of file diff --git a/src/Legerity.WCT/RadialGauge.cs b/src/Legerity.WCT/RadialGauge.cs index 915bf50f..2dcf9db5 100644 --- a/src/Legerity.WCT/RadialGauge.cs +++ b/src/Legerity.WCT/RadialGauge.cs @@ -1,133 +1,140 @@ -namespace Legerity.Windows.Elements.WCT -{ - using System; - using Legerity.Windows.Extensions; - using OpenQA.Selenium; - using OpenQA.Selenium.Appium; - using OpenQA.Selenium.Appium.Windows; - using OpenQA.Selenium.Remote; +namespace Legerity.Windows.Elements.WCT; + +using System; +using Legerity.Windows.Extensions; +using OpenQA.Selenium; +using OpenQA.Selenium.Appium; +using OpenQA.Selenium.Appium.Windows; +using OpenQA.Selenium.Remote; +/// +/// Defines a wrapper for the Windows Community Toolkit RadialGauge control. +/// +public class RadialGauge : WindowsElementWrapper +{ /// - /// Defines a wrapper for the Windows Community Toolkit RadialGauge control. + /// Initializes a new instance of the class. /// - public class RadialGauge : WindowsElementWrapper + /// + /// The reference. + /// + public RadialGauge(WindowsElement element) + : base(element) { - /// - /// Initializes a new instance of the class. - /// - /// - /// The reference. - /// - public RadialGauge(WindowsElement element) - : base(element) - { - } + } - /// - /// Gets the minimum value of the gauge. - /// - public virtual double Minimum => this.GetRangeMinimum(); + /// + /// Gets the minimum value of the gauge. + /// + /// Thrown when an element is no longer valid in the document DOM. + public virtual double Minimum => this.GetRangeMinimum(); - /// - /// Gets the maximum value of the gauge. - /// - public virtual double Maximum => this.GetRangeMaximum(); + /// + /// Gets the maximum value of the gauge. + /// + /// Thrown when an element is no longer valid in the document DOM. + public virtual double Maximum => this.GetRangeMaximum(); - /// - /// Gets the small change (step) value of the gauge. - /// - public virtual double SmallChange => this.GetRangeSmallChange(); + /// + /// Gets the small change (step) value of the gauge. + /// + /// Thrown when an element is no longer valid in the document DOM. + public virtual double SmallChange => this.GetRangeSmallChange(); - /// - /// Gets the value of the gauge. - /// - public virtual double Value => this.GetRangeValue(); + /// + /// Gets the value of the gauge. + /// + /// Thrown when an element is no longer valid in the document DOM. + public virtual double Value => this.GetRangeValue(); - /// - /// Gets a value indicating whether the control is in a readonly state. - /// - public virtual bool IsReadonly => this.IsRangeReadonly(); + /// + /// Gets a value indicating whether the control is in a readonly state. + /// + /// Thrown when an element is no longer valid in the document DOM. + public virtual bool IsReadonly => this.IsRangeReadonly(); - /// - /// Allows conversion of a to the without direct casting. - /// - /// - /// The . - /// - /// - /// The . - /// - public static implicit operator RadialGauge(WindowsElement element) - { - return new RadialGauge(element); - } + /// + /// Allows conversion of a to the without direct casting. + /// + /// + /// The . + /// + /// + /// The . + /// + public static implicit operator RadialGauge(WindowsElement element) + { + return new RadialGauge(element); + } - /// - /// Allows conversion of a to the without direct casting. - /// - /// - /// The . - /// - /// - /// The . - /// - public static implicit operator RadialGauge(AppiumWebElement element) - { - return new RadialGauge(element as WindowsElement); - } + /// + /// Allows conversion of a to the without direct casting. + /// + /// + /// The . + /// + /// + /// The . + /// + public static implicit operator RadialGauge(AppiumWebElement element) + { + return new RadialGauge(element as WindowsElement); + } + + /// + /// Allows conversion of a to the without direct casting. + /// + /// + /// The . + /// + /// + /// The . + /// + public static implicit operator RadialGauge(RemoteWebElement element) + { + return new RadialGauge(element as WindowsElement); + } + + /// + /// Sets the value of the gauge. + /// + /// + /// The value. + /// + /// + /// Thrown when the value is out of the minimum and maximum range of the gauge. + /// + /// Thrown when an element is not enabled. + /// Thrown when an element is not visible. + /// Thrown when an element is no longer valid in the document DOM. + public virtual void SetValue(double value) + { + double min = this.Minimum; + double max = this.Maximum; - /// - /// Allows conversion of a to the without direct casting. - /// - /// - /// The . - /// - /// - /// The . - /// - public static implicit operator RadialGauge(RemoteWebElement element) + if (value < this.Minimum) { - return new RadialGauge(element as WindowsElement); + throw new ArgumentOutOfRangeException( + nameof(value), + value, + $"Value must be greater than or equal to the minimum value {min}"); } - /// - /// Sets the value of the gauge. - /// - /// - /// The value. - /// - /// - /// Thrown if the value is out of the minimum and maximum range of the gauge. - /// - public virtual void SetValue(double value) + if (value > this.Maximum) { - double min = this.Minimum; - double max = this.Maximum; - - if (value < this.Minimum) - { - throw new ArgumentOutOfRangeException( - nameof(value), - value, - $"Value must be greater than or equal to the minimum value {min}"); - } - - if (value > this.Maximum) - { - throw new ArgumentOutOfRangeException( - nameof(value), - value, - $"Value must be less than or equal to the maximum value {max}"); - } + throw new ArgumentOutOfRangeException( + nameof(value), + value, + $"Value must be less than or equal to the maximum value {max}"); + } - this.Click(); + this.Click(); - double currentValue = this.Value; - while (Math.Abs(currentValue - value) > double.Epsilon) - { - this.Element.SendKeys(currentValue < value ? Keys.ArrowRight : Keys.ArrowLeft); - currentValue = this.Value; - } + double currentValue = this.Value; + while (Math.Abs(currentValue - value) > double.Epsilon) + { + this.Element.SendKeys(currentValue < value ? Keys.ArrowRight : Keys.ArrowLeft); + currentValue = this.Value; } } } \ No newline at end of file diff --git a/src/Legerity.Web.Authentication/Pages/AzureAdLoginPage.cs b/src/Legerity.Web.Authentication/Pages/AzureAdLoginPage.cs index e9823efe..811640cc 100644 --- a/src/Legerity.Web.Authentication/Pages/AzureAdLoginPage.cs +++ b/src/Legerity.Web.Authentication/Pages/AzureAdLoginPage.cs @@ -1,130 +1,144 @@ -namespace Legerity.Web.Authentication.Pages +namespace Legerity.Web.Authentication.Pages; + +using System; +using Exceptions; +using Legerity.Extensions; +using Legerity.Pages; +using Legerity.Web.Elements.Core; +using OpenQA.Selenium; +using OpenQA.Selenium.Remote; + +/// +/// Defines a page object for the Azure Active Directory login page. +/// +public class AzureAdLoginPage : BasePage { - using System; - using Legerity.Extensions; - using Legerity.Pages; - using Legerity.Web.Elements.Core; - using OpenQA.Selenium; - using OpenQA.Selenium.Remote; + /// + /// The expected title of the Azure AD login page. + /// + public const string Title = "Sign in to your account"; /// - /// Defines a page object for the Azure Active Directory login page. + /// Initializes a new instance of the class using the instance that verifies the page has loaded within 2 seconds. /// - public class AzureAdLoginPage : BasePage + /// Thrown when AppManager.StartApp() has not been called. + /// Thrown when the page is not shown in 2 seconds. + /// Thrown when no element matches the expected locator. + public AzureAdLoginPage() { - /// - /// The expected title of the Azure AD login page. - /// - public const string Title = "Sign in to your account"; - - /// - /// Initializes a new instance of the class using the instance that verifies the page has loaded within 2 seconds. - /// - public AzureAdLoginPage() - { - } + } - /// - /// Initializes a new instance of the class using a instance that verifies the page has loaded within 2 seconds. - /// - /// - /// The instance of the started application driver that will be used to drive the page interaction. - /// - /// Thrown if AppManager.StartApp() has not been called. - /// Thrown if the page is not shown in 2 seconds. - public AzureAdLoginPage(RemoteWebDriver app) - : base(app) - { - } + /// + /// Initializes a new instance of the class using a instance that verifies the page has loaded within 2 seconds. + /// + /// + /// The instance of the started application driver that will be used to drive the page interaction. + /// + /// Thrown when AppManager.StartApp() has not been called. + /// Thrown when the page is not shown in 2 seconds. + /// Thrown when no element matches the expected locator. + public AzureAdLoginPage(RemoteWebDriver app) + : base(app) + { + } - /// - /// Initializes a new instance of the class using the instance that verifies the page has loaded within the given timeout. - /// - /// - /// The amount of time the driver should wait when searching for the if it is not immediately present. - /// - /// Thrown if AppManager.StartApp() has not been called. - /// Thrown if the page is not shown in the given timeout. - public AzureAdLoginPage(TimeSpan? traitTimeout) - : base(traitTimeout) + /// + /// Initializes a new instance of the class using the instance that verifies the page has loaded within the given timeout. + /// + /// + /// The amount of time the driver should wait when searching for the if it is not immediately present. + /// + /// Thrown when AppManager.StartApp() has not been called. + /// Thrown when the page is not shown in the given timeout. + /// Thrown when no element matches the expected locator. + public AzureAdLoginPage(TimeSpan? traitTimeout) + : base(traitTimeout) + { + } + + /// + /// Initializes a new instance of the class using a instance that verifies the page has loaded within the given timeout. + /// + /// + /// The instance of the started application driver that will be used to drive the page interaction. + /// + /// + /// The amount of time the driver should wait when searching for the if it is not immediately present. + /// + /// Thrown when AppManager.StartApp() has not been called. + /// Thrown when the page is not shown in the given timeout. + /// Thrown when no element matches the expected locator. + public AzureAdLoginPage(RemoteWebDriver app, TimeSpan? traitTimeout) + : base(app, traitTimeout) + { + } + + /// + /// Gets the input element for providing an email address. + /// + /// Thrown when no element matches the expected locator. + public virtual TextInput EmailInput => this.FindElement(WebByExtras.InputType("email")); + + /// + /// Gets the input element for providing a password. + /// + /// Thrown when no element matches the expected locator. + public virtual TextInput PasswordInput => this.FindElement(WebByExtras.InputType("password")); + + /// + /// Gets the button element for continuing the sign-in flow through the Azure AD login UI. + /// + /// Thrown when no element matches the expected locator. + public virtual Button SignInButton => this.FindElement(By.Id("idSIButton9")); + + /// + /// Gets the optional "Use Password" button that appears when password-less authentication is enabled. + /// + /// Thrown when no element matches the expected locator. + public virtual Button UsePasswordButton => this.FindElement(By.Id("idA_PWD_SwitchToPassword")); + + /// + /// Gets a given trait of the page to verify that the page is in view. + /// + protected override By Trait => By.ClassName("login-paginated-page"); + + /// + /// Login an Azure Active Directory user by email and password. + /// + /// The email address to authenticate with. + /// The password associated with the email address to authenticate with. + /// The instance. + /// Thrown when no element matches the expected locator. + /// Thrown when an element is no longer valid in the document DOM. + /// Thrown when an element is not enabled. + /// Thrown when an element is not visible. + public AzureAdLoginPage Login(string email, string password) + { + (bool hasEmailInput, AzureAdLoginPage _) = + this.TryWaitUntil(page => page.EmailInput.IsVisible, this.WaitTimeout); + if (!hasEmailInput) { + // Cannot login as email address input not shown (possibly logged in already?) + return this; } - /// - /// Initializes a new instance of the class using a instance that verifies the page has loaded within the given timeout. - /// - /// - /// The instance of the started application driver that will be used to drive the page interaction. - /// - /// - /// The amount of time the driver should wait when searching for the if it is not immediately present. - /// - /// Thrown if AppManager.StartApp() has not been called. - /// Thrown if the page is not shown in the given timeout. - public AzureAdLoginPage(RemoteWebDriver app, TimeSpan? traitTimeout) - : base(app, traitTimeout) + this.EmailInput.SetText(email); + + // Azure AD login uses a 2-step process for email and password. + this.SignInButton.Click(); + + // Check to ensure that the user is not authenticating with password-less authentication. + (bool isNotPasswordLogin, AzureAdLoginPage _) = + this.TryWaitUntil(page => page.UsePasswordButton.IsVisible, this.WaitTimeout); + if (isNotPasswordLogin) { + this.UsePasswordButton.Click(); + this.TryWaitUntil(page => page.PasswordInput.IsVisible, this.WaitTimeout); } - /// - /// Gets the input element for providing an email address. - /// - public virtual TextInput EmailInput => this.App.FindWebElement(WebByExtras.InputType("email")); - - /// - /// Gets the input element for providing a password. - /// - public virtual TextInput PasswordInput => this.App.FindWebElement(WebByExtras.InputType("password")); - - /// - /// Gets the button element for continuing the sign-in flow through the Azure AD login UI. - /// - public virtual Button SignInButton => this.App.FindWebElement(By.Id("idSIButton9")); - - /// - /// Gets the optional "Use Password" button that appears when password-less authentication is enabled. - /// - public virtual Button UsePasswordButton => this.App.FindWebElement(By.Id("idA_PWD_SwitchToPassword")); - - /// - /// Gets a given trait of the page to verify that the page is in view. - /// - protected override By Trait => By.ClassName("login-paginated-page"); - - /// - /// Login an Azure Active Directory user by email and password. - /// - /// The email address to authenticate with. - /// The password associated with the email address to authenticate with. - /// The instance. - public AzureAdLoginPage Login(string email, string password) - { - (bool hasEmailInput, AzureAdLoginPage _) = - this.TryWaitUntil(page => page.EmailInput.IsVisible, this.WaitTimeout); - if (!hasEmailInput) - { - // Cannot login as email address input not shown (possibly logged in already?) - return this; - } - - this.EmailInput.SetText(email); - - // Azure AD login uses a 2-step process for email and password. - this.SignInButton.Click(); - - // Check to ensure that the user is not authenticating with password-less authentication. - (bool isNotPasswordLogin, AzureAdLoginPage _) = - this.TryWaitUntil(page => page.UsePasswordButton.IsVisible, this.WaitTimeout); - if (isNotPasswordLogin) - { - this.UsePasswordButton.Click(); - this.TryWaitUntil(page => page.PasswordInput.IsVisible, this.WaitTimeout); - } - - this.PasswordInput.SetText(password); - this.SignInButton.Click(); + this.PasswordInput.SetText(password); + this.SignInButton.Click(); - return this; - } + return this; } } \ No newline at end of file diff --git a/src/Legerity.Web.Authentication/Pages/FacebookLoginPage.cs b/src/Legerity.Web.Authentication/Pages/FacebookLoginPage.cs index 0b3ac6e1..5f0f6588 100644 --- a/src/Legerity.Web.Authentication/Pages/FacebookLoginPage.cs +++ b/src/Legerity.Web.Authentication/Pages/FacebookLoginPage.cs @@ -1,111 +1,124 @@ -namespace Legerity.Web.Authentication.Pages +namespace Legerity.Web.Authentication.Pages; + +using System; +using Exceptions; +using Legerity.Extensions; +using Legerity.Pages; +using Legerity.Web.Elements.Core; +using OpenQA.Selenium; +using OpenQA.Selenium.Remote; + +/// +/// Defines a page object for the Facebook login page. +/// +public class FacebookLoginPage : BasePage { - using System; - using Legerity.Extensions; - using Legerity.Pages; - using Legerity.Web.Elements.Core; - using OpenQA.Selenium; - using OpenQA.Selenium.Remote; + /// + /// The expected title of the Facebook login page. + /// + public const string Title = "Log in to Facebook"; /// - /// Defines a page object for the Facebook login page. + /// Initializes a new instance of the class using the instance that verifies the page has loaded within 2 seconds. /// - public class FacebookLoginPage : BasePage + /// Thrown when AppManager.StartApp() has not been called. + /// Thrown when the page is not shown in 2 seconds. + /// Thrown when no element matches the expected locator. + public FacebookLoginPage() { - /// - /// The expected title of the Facebook login page. - /// - public const string Title = "Log in to Facebook"; - - /// - /// Initializes a new instance of the class using the instance that verifies the page has loaded within 2 seconds. - /// - public FacebookLoginPage() - { - } + } - /// - /// Initializes a new instance of the class using a instance that verifies the page has loaded within 2 seconds. - /// - /// - /// The instance of the started application driver that will be used to drive the page interaction. - /// - /// Thrown if AppManager.StartApp() has not been called. - /// Thrown if the page is not shown in 2 seconds. - public FacebookLoginPage(RemoteWebDriver app) - : base(app) - { - } + /// + /// Initializes a new instance of the class using a instance that verifies the page has loaded within 2 seconds. + /// + /// + /// The instance of the started application driver that will be used to drive the page interaction. + /// + /// Thrown when AppManager.StartApp() has not been called. + /// Thrown when the page is not shown in 2 seconds. + /// Thrown when no element matches the expected locator. + public FacebookLoginPage(RemoteWebDriver app) + : base(app) + { + } - /// - /// Initializes a new instance of the class using the instance that verifies the page has loaded within the given timeout. - /// - /// - /// The amount of time the driver should wait when searching for the if it is not immediately present. - /// - /// Thrown if AppManager.StartApp() has not been called. - /// Thrown if the page is not shown in the given timeout. - public FacebookLoginPage(TimeSpan? traitTimeout) - : base(traitTimeout) - { - } + /// + /// Initializes a new instance of the class using the instance that verifies the page has loaded within the given timeout. + /// + /// + /// The amount of time the driver should wait when searching for the if it is not immediately present. + /// + /// Thrown when AppManager.StartApp() has not been called. + /// Thrown when the page is not shown in the given timeout. + /// Thrown when no element matches the expected locator. + public FacebookLoginPage(TimeSpan? traitTimeout) + : base(traitTimeout) + { + } - /// - /// Initializes a new instance of the class using a instance that verifies the page has loaded within the given timeout. - /// - /// - /// The instance of the started application driver that will be used to drive the page interaction. - /// - /// - /// The amount of time the driver should wait when searching for the if it is not immediately present. - /// - /// Thrown if AppManager.StartApp() has not been called. - /// Thrown if the page is not shown in the given timeout. - public FacebookLoginPage(RemoteWebDriver app, TimeSpan? traitTimeout) - : base(app, traitTimeout) - { - } + /// + /// Initializes a new instance of the class using a instance that verifies the page has loaded within the given timeout. + /// + /// + /// The instance of the started application driver that will be used to drive the page interaction. + /// + /// + /// The amount of time the driver should wait when searching for the if it is not immediately present. + /// + /// Thrown when AppManager.StartApp() has not been called. + /// Thrown when the page is not shown in the given timeout. + /// Thrown when no element matches the expected locator. + public FacebookLoginPage(RemoteWebDriver app, TimeSpan? traitTimeout) + : base(app, traitTimeout) + { + } - /// - /// Gets the input element for providing an email address. - /// - public virtual TextInput EmailInput => this.App.FindWebElement(By.Id("email")); + /// + /// Gets the input element for providing an email address. + /// + /// Thrown when no element matches the expected locator. + public virtual TextInput EmailInput => this.FindElement(By.Id("email")); - /// - /// Gets the input element for providing a password. - /// - public virtual TextInput PasswordInput => this.App.FindWebElement(WebByExtras.InputType("password")); + /// + /// Gets the input element for providing a password. + /// + /// Thrown when no element matches the expected locator. + public virtual TextInput PasswordInput => this.FindElement(WebByExtras.InputType("password")); - /// - /// Gets the button element for continuing the sign-in flow through the Facebook login UI. - /// - public virtual Button SignInButton => this.App.FindWebElement(By.Id("loginbutton")); + /// + /// Gets the button element for continuing the sign-in flow through the Facebook login UI. + /// + /// Thrown when no element matches the expected locator. + public virtual Button SignInButton => this.FindElement(By.Id("loginbutton")); - /// - /// Gets a given trait of the page to verify that the page is in view. - /// - protected override By Trait => By.ClassName("login_form_container"); + /// + /// Gets a given trait of the page to verify that the page is in view. + /// + protected override By Trait => By.ClassName("login_form_container"); - /// - /// Login a Facebook user by email and password. - /// - /// The email address to authenticate with. - /// The password associated with the email address to authenticate with. - /// The instance. - public FacebookLoginPage Login(string email, string password) + /// + /// Login a Facebook user by email and password. + /// + /// The email address to authenticate with. + /// The password associated with the email address to authenticate with. + /// The instance. + /// Thrown when no element matches the expected locator. + /// Thrown when an element is no longer valid in the document DOM. + /// Thrown when an element is not enabled. + /// Thrown when an element is not visible. + public FacebookLoginPage Login(string email, string password) + { + (bool hasEmailInput, FacebookLoginPage _) = + this.TryWaitUntil(page => page.EmailInput.IsVisible, this.WaitTimeout); + if (!hasEmailInput) { - (bool hasEmailInput, FacebookLoginPage _) = - this.TryWaitUntil(page => page.EmailInput.IsVisible, this.WaitTimeout); - if (!hasEmailInput) - { - // Cannot login as email address input not shown (possibly logged in already?) - return this; - } - - this.EmailInput.SetText(email); - this.PasswordInput.SetText(password); - this.SignInButton.Click(); + // Cannot login as email address input not shown (possibly logged in already?) return this; } + + this.EmailInput.SetText(email); + this.PasswordInput.SetText(password); + this.SignInButton.Click(); + return this; } -} +} \ No newline at end of file diff --git a/src/Legerity.Web.Authentication/Pages/GoogleLoginPage.cs b/src/Legerity.Web.Authentication/Pages/GoogleLoginPage.cs index 5934c0b0..c307c374 100644 --- a/src/Legerity.Web.Authentication/Pages/GoogleLoginPage.cs +++ b/src/Legerity.Web.Authentication/Pages/GoogleLoginPage.cs @@ -1,128 +1,142 @@ -namespace Legerity.Web.Authentication.Pages +namespace Legerity.Web.Authentication.Pages; + +using System; +using Exceptions; +using Legerity.Extensions; +using Legerity.Pages; +using Legerity.Web.Elements.Core; +using OpenQA.Selenium; +using OpenQA.Selenium.Remote; + +/// +/// Defines a page object for the Google login page. +/// +public class GoogleLoginPage : BasePage { - using System; - using Legerity.Extensions; - using Legerity.Pages; - using Legerity.Web.Elements.Core; - using OpenQA.Selenium; - using OpenQA.Selenium.Remote; + /// + /// The expected title of the Google login page. + /// + public const string Title = "Sign in"; /// - /// Defines a page object for the Google login page. + /// Initializes a new instance of the class using the instance that verifies the page has loaded within 2 seconds. /// - public class GoogleLoginPage : BasePage + /// Thrown when AppManager.StartApp() has not been called. + /// Thrown when the page is not shown in 2 seconds. + /// Thrown when no element matches the expected locator. + public GoogleLoginPage() { - /// - /// The expected title of the Google login page. - /// - public const string Title = "Sign in"; - - /// - /// Initializes a new instance of the class using the instance that verifies the page has loaded within 2 seconds. - /// - public GoogleLoginPage() - { - } + } - /// - /// Initializes a new instance of the class using a instance that verifies the page has loaded within 2 seconds. - /// - /// - /// The instance of the started application driver that will be used to drive the page interaction. - /// - /// Thrown if AppManager.StartApp() has not been called. - /// Thrown if the page is not shown in 2 seconds. - public GoogleLoginPage(RemoteWebDriver app) - : base(app) - { - } + /// + /// Initializes a new instance of the class using a instance that verifies the page has loaded within 2 seconds. + /// + /// + /// The instance of the started application driver that will be used to drive the page interaction. + /// + /// Thrown when AppManager.StartApp() has not been called. + /// Thrown when the page is not shown in 2 seconds. + /// Thrown when no element matches the expected locator. + public GoogleLoginPage(RemoteWebDriver app) + : base(app) + { + } - /// - /// Initializes a new instance of the class using the instance that verifies the page has loaded within the given timeout. - /// - /// - /// The amount of time the driver should wait when searching for the if it is not immediately present. - /// - /// Thrown if AppManager.StartApp() has not been called. - /// Thrown if the page is not shown in the given timeout. - public GoogleLoginPage(TimeSpan? traitTimeout) - : base(traitTimeout) - { - } + /// + /// Initializes a new instance of the class using the instance that verifies the page has loaded within the given timeout. + /// + /// + /// The amount of time the driver should wait when searching for the if it is not immediately present. + /// + /// Thrown when AppManager.StartApp() has not been called. + /// Thrown when the page is not shown in the given timeout. + /// Thrown when no element matches the expected locator. + public GoogleLoginPage(TimeSpan? traitTimeout) + : base(traitTimeout) + { + } - /// - /// Initializes a new instance of the class using a instance that verifies the page has loaded within the given timeout. - /// - /// - /// The instance of the started application driver that will be used to drive the page interaction. - /// - /// - /// The amount of time the driver should wait when searching for the if it is not immediately present. - /// - /// Thrown if AppManager.StartApp() has not been called. - /// Thrown if the page is not shown in the given timeout. - public GoogleLoginPage(RemoteWebDriver app, TimeSpan? traitTimeout) - : base(app, traitTimeout) - { - } + /// + /// Initializes a new instance of the class using a instance that verifies the page has loaded within the given timeout. + /// + /// + /// The instance of the started application driver that will be used to drive the page interaction. + /// + /// + /// The amount of time the driver should wait when searching for the if it is not immediately present. + /// + /// Thrown when AppManager.StartApp() has not been called. + /// Thrown when the page is not shown in the given timeout. + /// Thrown when no element matches the expected locator. + public GoogleLoginPage(RemoteWebDriver app, TimeSpan? traitTimeout) + : base(app, traitTimeout) + { + } - /// - /// Gets the input element for providing an email address. - /// - public virtual TextInput EmailInput => this.App.FindWebElement(WebByExtras.InputType("email")); - - /// - /// Gets the input element for providing a password. - /// - public virtual TextInput PasswordInput => this.App.FindWebElement(WebByExtras.InputType("password")); - - /// - /// Gets the button element for continuing the sign-in flow through the Google login UI. - /// - public virtual Button NextButton => this.App.FindWebElement(By.Id("identifierNext")); - - /// - /// Gets the button element for completing the sign-in flow through the Google login UI. - /// - public virtual Button SignInButton => this.App.FindWebElement(By.Id("passwordNext")); - - /// - /// Gets a given trait of the page to verify that the page is in view. - /// - protected override By Trait => By.ClassName("view_container"); - - /// - /// Login a Google user by email and password. - /// - /// The email address to authenticate with. - /// The password associated with the email address to authenticate with. - /// The instance. - public GoogleLoginPage Login(string email, string password) - { - (bool hasEmailInput, GoogleLoginPage _) = - this.TryWaitUntil(page => page.EmailInput.IsVisible, this.WaitTimeout); - if (!hasEmailInput) - { - // Cannot login as email address input not shown (possibly logged in already?) - return this; - } + /// + /// Gets the input element for providing an email address. + /// + /// Thrown when no element matches the expected locator. + public virtual TextInput EmailInput => this.FindElement(WebByExtras.InputType("email")); - this.EmailInput.SetText(email); + /// + /// Gets the input element for providing a password. + /// + /// Thrown when no element matches the expected locator. + public virtual TextInput PasswordInput => this.FindElement(WebByExtras.InputType("password")); - // Google login uses a 2-step process for email and password. - this.NextButton.Click(); + /// + /// Gets the button element for continuing the sign-in flow through the Google login UI. + /// + /// Thrown when no element matches the expected locator. + public virtual Button NextButton => this.FindElement(By.Id("identifierNext")); - (bool isPasswordInputVisible, GoogleLoginPage _) = - this.TryWaitUntil(page => page.PasswordInput.IsVisible, this.WaitTimeout); - if (!isPasswordInputVisible) - { - return this; - } + /// + /// Gets the button element for completing the sign-in flow through the Google login UI. + /// + /// Thrown when no element matches the expected locator. + public virtual Button SignInButton => this.FindElement(By.Id("passwordNext")); - this.PasswordInput.SetText(password); - this.SignInButton.Click(); + /// + /// Gets a given trait of the page to verify that the page is in view. + /// + protected override By Trait => By.ClassName("view_container"); + /// + /// Login a Google user by email and password. + /// + /// The email address to authenticate with. + /// The password associated with the email address to authenticate with. + /// The instance. + /// Thrown when no element matches the expected locator. + /// Thrown when an element is no longer valid in the document DOM. + /// Thrown when an element is not enabled. + /// Thrown when an element is not visible. + public GoogleLoginPage Login(string email, string password) + { + (bool hasEmailInput, GoogleLoginPage _) = + this.TryWaitUntil(page => page.EmailInput.IsVisible, this.WaitTimeout); + if (!hasEmailInput) + { + // Cannot login as email address input not shown (possibly logged in already?) return this; } + + this.EmailInput.SetText(email); + + // Google login uses a 2-step process for email and password. + this.NextButton.Click(); + + (bool isPasswordInputVisible, GoogleLoginPage _) = + this.TryWaitUntil(page => page.PasswordInput.IsVisible, this.WaitTimeout); + if (!isPasswordInputVisible) + { + return this; + } + + this.PasswordInput.SetText(password); + this.SignInButton.Click(); + + return this; } } \ No newline at end of file diff --git a/src/Legerity.Web/Elements/Core/Button.cs b/src/Legerity.Web/Elements/Core/Button.cs index 70c41818..2fe764e8 100644 --- a/src/Legerity.Web/Elements/Core/Button.cs +++ b/src/Legerity.Web/Elements/Core/Button.cs @@ -1,48 +1,47 @@ -namespace Legerity.Web.Elements.Core -{ - using Legerity.Web.Elements; - using OpenQA.Selenium; - using OpenQA.Selenium.Remote; +namespace Legerity.Web.Elements.Core; + +using Legerity.Web.Elements; +using OpenQA.Selenium; +using OpenQA.Selenium.Remote; +/// +/// Defines a wrapper for the core web Button control. +/// +public class Button : WebElementWrapper +{ /// - /// Defines a wrapper for the core web Button control. + /// Initializes a new instance of the class. /// - public class Button : WebElementWrapper + /// + /// The reference. + /// + public Button(IWebElement element) + : this(element as RemoteWebElement) { - /// - /// Initializes a new instance of the class. - /// - /// - /// The reference. - /// - public Button(IWebElement element) - : this(element as RemoteWebElement) - { - } + } - /// - /// Initializes a new instance of the class. - /// - /// - /// The reference. - /// - public Button(RemoteWebElement element) - : base(element) - { - } + /// + /// Initializes a new instance of the class. + /// + /// + /// The reference. + /// + public Button(RemoteWebElement element) + : base(element) + { + } - /// - /// Allows conversion of a to the without direct casting. - /// - /// - /// The . - /// - /// - /// The . - /// - public static implicit operator Button(RemoteWebElement element) - { - return new Button(element); - } + /// + /// Allows conversion of a to the without direct casting. + /// + /// + /// The . + /// + /// + /// The . + /// + public static implicit operator Button(RemoteWebElement element) + { + return new Button(element); } } \ No newline at end of file diff --git a/src/Legerity.Web/Elements/Core/CheckBox.cs b/src/Legerity.Web/Elements/Core/CheckBox.cs index 5a024ac1..38d1cc6e 100644 --- a/src/Legerity.Web/Elements/Core/CheckBox.cs +++ b/src/Legerity.Web/Elements/Core/CheckBox.cs @@ -1,79 +1,85 @@ -namespace Legerity.Web.Elements.Core +namespace Legerity.Web.Elements.Core; + +using Legerity.Web.Elements; +using OpenQA.Selenium; +using OpenQA.Selenium.Remote; + +/// +/// Defines a wrapper for the core web Input checkbox control. +/// +public class CheckBox : WebElementWrapper { - using Legerity.Web.Elements; - using OpenQA.Selenium; - using OpenQA.Selenium.Remote; + /// + /// Initializes a new instance of the class. + /// + /// + /// The reference. + /// + public CheckBox(IWebElement element) + : this(element as RemoteWebElement) + { + } /// - /// Defines a wrapper for the core web Input checkbox control. + /// Initializes a new instance of the class. /// - public class CheckBox : WebElementWrapper + /// + /// The reference. + /// + public CheckBox(RemoteWebElement element) + : base(element) { - /// - /// Initializes a new instance of the class. - /// - /// - /// The reference. - /// - public CheckBox(IWebElement element) - : this(element as RemoteWebElement) - { - } + } - /// - /// Initializes a new instance of the class. - /// - /// - /// The reference. - /// - public CheckBox(RemoteWebElement element) - : base(element) - { - } + /// + /// Gets a value indicating whether the check box is in the checked state. + /// + /// Thrown when an element is no longer valid in the document DOM. + public virtual bool IsChecked => this.Element.Selected; - /// - /// Gets a value indicating whether the check box is in the checked state. - /// - public virtual bool IsChecked => this.Element.Selected; + /// + /// Allows conversion of a to the without direct casting. + /// + /// + /// The . + /// + /// + /// The . + /// + public static implicit operator CheckBox(RemoteWebElement element) + { + return new CheckBox(element); + } - /// - /// Allows conversion of a to the without direct casting. - /// - /// - /// The . - /// - /// - /// The . - /// - public static implicit operator CheckBox(RemoteWebElement element) + /// + /// Checks the check box on. + /// + /// Thrown when an element is not enabled. + /// Thrown when an element is not visible. + /// Thrown when an element is no longer valid in the document DOM. + public virtual void CheckOn() + { + if (this.IsChecked) { - return new CheckBox(element); + return; } - /// - /// Checks the check box on. - /// - public virtual void CheckOn() - { - if (this.IsChecked) - { - return; - } - - this.Click(); - } + this.Click(); + } - /// - /// Checks the check box off. - /// - public virtual void CheckOff() + /// + /// Checks the check box off. + /// + /// Thrown when an element is not enabled. + /// Thrown when an element is not visible. + /// Thrown when an element is no longer valid in the document DOM. + public virtual void CheckOff() + { + if (!this.IsChecked) { - if (!this.IsChecked) - { - return; - } - - this.Click(); + return; } + + this.Click(); } } \ No newline at end of file diff --git a/src/Legerity.Web/Elements/Core/DateInput.cs b/src/Legerity.Web/Elements/Core/DateInput.cs index 49889c84..97675523 100644 --- a/src/Legerity.Web/Elements/Core/DateInput.cs +++ b/src/Legerity.Web/Elements/Core/DateInput.cs @@ -36,6 +36,7 @@ public DateInput(RemoteWebElement element) /// /// Gets the value of the date picker. /// + /// Thrown when an element is no longer valid in the document DOM. public virtual string Value => this.GetValue(); /// @@ -61,6 +62,7 @@ public static implicit operator DateInput(RemoteWebElement element) /// Sets the date to the specified date. /// /// The date to set. + /// Thrown when this instance does not implement . public virtual void SetDate(DateTime date) { this.ElementDriver.ExecuteJavaScript( diff --git a/src/Legerity.Web/Elements/Core/FileInput.cs b/src/Legerity.Web/Elements/Core/FileInput.cs index 1b44083f..8f3dbdd3 100644 --- a/src/Legerity.Web/Elements/Core/FileInput.cs +++ b/src/Legerity.Web/Elements/Core/FileInput.cs @@ -1,72 +1,76 @@ -namespace Legerity.Web.Elements.Core -{ - using Legerity.Web.Elements; - using Legerity.Web.Extensions; - using OpenQA.Selenium; - using OpenQA.Selenium.Remote; +namespace Legerity.Web.Elements.Core; + +using Legerity.Web.Elements; +using Legerity.Web.Extensions; +using OpenQA.Selenium; +using OpenQA.Selenium.Remote; +/// +/// Defines a wrapper for the core web Input file control. +/// +public class FileInput : WebElementWrapper +{ /// - /// Defines a wrapper for the core web Input file control. + /// Initializes a new instance of the class. /// - public class FileInput : WebElementWrapper + /// + /// The reference. + /// + public FileInput(IWebElement element) + : this(element as RemoteWebElement) { - /// - /// Initializes a new instance of the class. - /// - /// - /// The reference. - /// - public FileInput(IWebElement element) - : this(element as RemoteWebElement) - { - } + } - /// - /// Initializes a new instance of the class. - /// - /// - /// The reference. - /// - public FileInput(RemoteWebElement element) - : base(element) - { - } + /// + /// Initializes a new instance of the class. + /// + /// + /// The reference. + /// + public FileInput(RemoteWebElement element) + : base(element) + { + } - /// - /// Gets the file path for the selected file. - /// - public virtual string FilePath => this.GetValue(); + /// + /// Gets the file path for the selected file. + /// + /// Thrown when an element is no longer valid in the document DOM. + public virtual string FilePath => this.GetValue(); - /// - /// Allows conversion of a to the without direct casting. - /// - /// - /// The . - /// - /// - /// The . - /// - public static implicit operator FileInput(RemoteWebElement element) - { - return new FileInput(element); - } + /// + /// Allows conversion of a to the without direct casting. + /// + /// + /// The . + /// + /// + /// The . + /// + public static implicit operator FileInput(RemoteWebElement element) + { + return new FileInput(element); + } - /// - /// Sets the selected file by an absolute file path. - /// - /// The file path. - public virtual void SetAbsoluteFilePath(string filePath) - { - this.ClearFile(); - this.Element.SendKeys(filePath); - } + /// + /// Sets the selected file by an absolute file path. + /// + /// The file path. + /// Thrown when an element is not enabled. + /// Thrown when an element is not visible. + /// Thrown when an element is no longer valid in the document DOM. + public virtual void SetAbsoluteFilePath(string filePath) + { + this.ClearFile(); + this.Element.SendKeys(filePath); + } - /// - /// Clears the selected file. - /// - public virtual void ClearFile() - { - this.Element.Clear(); - } + /// + /// Clears the selected file. + /// + /// Thrown when an element is no longer valid in the document DOM. + public virtual void ClearFile() + { + this.Element.Clear(); } } \ No newline at end of file diff --git a/src/Legerity.Web/Elements/Core/Image.cs b/src/Legerity.Web/Elements/Core/Image.cs index d1cf201a..d46344a6 100644 --- a/src/Legerity.Web/Elements/Core/Image.cs +++ b/src/Legerity.Web/Elements/Core/Image.cs @@ -1,68 +1,72 @@ -namespace Legerity.Web.Elements.Core -{ - using Legerity.Web.Elements; - using OpenQA.Selenium; - using OpenQA.Selenium.Remote; +namespace Legerity.Web.Elements.Core; + +using Extensions; +using Legerity.Web.Elements; +using OpenQA.Selenium; +using OpenQA.Selenium.Remote; +/// +/// Defines a wrapper for the core web Image control. +/// +public class Image : WebElementWrapper +{ /// - /// Defines a wrapper for the core web Image control. + /// Initializes a new instance of the class. /// - public class Image : WebElementWrapper + /// + /// The reference. + /// + public Image(IWebElement element) + : this(element as RemoteWebElement) { - /// - /// Initializes a new instance of the class. - /// - /// - /// The reference. - /// - public Image(IWebElement element) - : this(element as RemoteWebElement) - { - } + } - /// - /// Initializes a new instance of the class. - /// - /// - /// The reference. - /// - public Image(RemoteWebElement element) - : base(element) - { - } + /// + /// Initializes a new instance of the class. + /// + /// + /// The reference. + /// + public Image(RemoteWebElement element) + : base(element) + { + } - /// - /// Gets the source URI of the image. - /// - public virtual string Source => this.GetAttribute("src"); + /// + /// Gets the source URI of the image. + /// + /// Thrown when an element is no longer valid in the document DOM. + public virtual string Source => this.GetAttribute("src"); - /// - /// Gets the alt text of the image. - /// - public virtual string AltText => this.GetAttribute("alt"); + /// + /// Gets the alt text of the image. + /// + /// Thrown when an element is no longer valid in the document DOM. + public virtual string AltText => this.GetAttribute("alt"); - /// - /// Gets the width of the image. - /// - public virtual double Width => double.Parse(this.GetAttribute("width")); + /// + /// Gets the width of the image. + /// + /// Thrown when an element is no longer valid in the document DOM. + public virtual double Width => this.GetWidth(); - /// - /// Gets the height of the image. - /// - public virtual double Height => double.Parse(this.GetAttribute("height")); + /// + /// Gets the height of the image. + /// + /// Thrown when an element is no longer valid in the document DOM. + public virtual double Height => this.GetHeight(); - /// - /// Allows conversion of a to the without direct casting. - /// - /// - /// The . - /// - /// - /// The . - /// - public static implicit operator Image(RemoteWebElement element) - { - return new Image(element); - } + /// + /// Allows conversion of a to the without direct casting. + /// + /// + /// The . + /// + /// + /// The . + /// + public static implicit operator Image(RemoteWebElement element) + { + return new Image(element); } } \ No newline at end of file diff --git a/src/Legerity.Web/Elements/Core/List.cs b/src/Legerity.Web/Elements/Core/List.cs index fdcb07f5..420ee387 100644 --- a/src/Legerity.Web/Elements/Core/List.cs +++ b/src/Legerity.Web/Elements/Core/List.cs @@ -1,54 +1,53 @@ -namespace Legerity.Web.Elements.Core -{ - using System.Collections.ObjectModel; - using Legerity.Web.Elements; - using OpenQA.Selenium; - using OpenQA.Selenium.Remote; +namespace Legerity.Web.Elements.Core; + +using System.Collections.ObjectModel; +using Legerity.Web.Elements; +using OpenQA.Selenium; +using OpenQA.Selenium.Remote; +/// +/// Defines a wrapper for the core web ol or ul control. +/// +public class List : WebElementWrapper +{ /// - /// Defines a wrapper for the core web ol or ul control. + /// Initializes a new instance of the class. /// - public class List : WebElementWrapper + /// + /// The reference. + /// + public List(IWebElement element) + : this(element as RemoteWebElement) { - /// - /// Initializes a new instance of the class. - /// - /// - /// The reference. - /// - public List(IWebElement element) - : this(element as RemoteWebElement) - { - } + } - /// - /// Initializes a new instance of the class. - /// - /// - /// The reference. - /// - public List(RemoteWebElement element) - : base(element) - { - } + /// + /// Initializes a new instance of the class. + /// + /// + /// The reference. + /// + public List(RemoteWebElement element) + : base(element) + { + } - /// - /// Gets the collection of items associated with the list. - /// - public virtual ReadOnlyCollection Items => this.Element.FindElements(WebByExtras.ListItem()); + /// + /// Gets the collection of items associated with the list. + /// + public virtual ReadOnlyCollection Items => this.Element.FindElements(WebByExtras.ListItem()); - /// - /// Allows conversion of a to the without direct casting. - /// - /// - /// The . - /// - /// - /// The . - /// - public static implicit operator List(RemoteWebElement element) - { - return new List(element); - } + /// + /// Allows conversion of a to the without direct casting. + /// + /// + /// The . + /// + /// + /// The . + /// + public static implicit operator List(RemoteWebElement element) + { + return new List(element); } } \ No newline at end of file diff --git a/src/Legerity.Web/Elements/Core/NumberInput.cs b/src/Legerity.Web/Elements/Core/NumberInput.cs index 43541729..57369b82 100644 --- a/src/Legerity.Web/Elements/Core/NumberInput.cs +++ b/src/Legerity.Web/Elements/Core/NumberInput.cs @@ -1,112 +1,124 @@ -namespace Legerity.Web.Elements.Core +namespace Legerity.Web.Elements.Core; + +using System; +using Extensions; +using OpenQA.Selenium; +using OpenQA.Selenium.Remote; + +/// +/// Defines a wrapper for the core web Input number control. +/// +public class NumberInput : TextInput { - using System; - using OpenQA.Selenium; - using OpenQA.Selenium.Remote; + /// + /// Initializes a new instance of the class. + /// + /// + /// The reference. + /// + public NumberInput(IWebElement element) + : this(element as RemoteWebElement) + { + } /// - /// Defines a wrapper for the core web Input number control. + /// Initializes a new instance of the class. /// - public class NumberInput : TextInput + /// + /// The reference. + /// + public NumberInput(RemoteWebElement element) + : base(element) { - /// - /// Initializes a new instance of the class. - /// - /// - /// The reference. - /// - public NumberInput(IWebElement element) - : this(element as RemoteWebElement) - { - } + } - /// - /// Initializes a new instance of the class. - /// - /// - /// The reference. - /// - public NumberInput(RemoteWebElement element) - : base(element) - { - } + /// + /// Gets the minimum value of the NumberBox. + /// + /// Thrown when an element is no longer valid in the document DOM. + public virtual double Minimum => this.GetMinimum(); - /// - /// Gets the minimum value of the NumberBox. - /// - public virtual double Minimum => double.Parse(this.GetAttribute("min")); + /// + /// Gets the maximum value of the NumberBox. + /// + /// Thrown when an element is no longer valid in the document DOM. + public virtual double Maximum => this.GetMaximum(); - /// - /// Gets the maximum value of the NumberBox. - /// - public virtual double Maximum => double.Parse(this.GetAttribute("max")); + /// + /// Gets the value of the NumberBox. + /// + /// Thrown when an element is no longer valid in the document DOM. + public virtual double Value => double.TryParse(this.Text, out double val) ? val : 0; - /// - /// Gets the value of the NumberBox. - /// - public virtual double Value => double.TryParse(this.Text, out double val) ? val : 0; + /// + /// Allows conversion of a to the without direct casting. + /// + /// + /// The . + /// + /// + /// The . + /// + public static implicit operator NumberInput(RemoteWebElement element) + { + return new NumberInput(element); + } - /// - /// Allows conversion of a to the without direct casting. - /// - /// - /// The . - /// - /// - /// The . - /// - public static implicit operator NumberInput(RemoteWebElement element) - { - return new NumberInput(element); - } + /// + /// Sets the value of the NumberBox. + /// + /// + /// The value. + /// + /// + /// Thrown when the value is out of the minimum and maximum range of the NumberBox. + /// + /// Thrown when an element is no longer valid in the document DOM. + /// Thrown when an element is not enabled. + /// Thrown when an element is not visible. + public virtual void SetValue(double value) + { + double min = this.Minimum; + double max = this.Maximum; - /// - /// Sets the value of the NumberBox. - /// - /// - /// The value. - /// - /// - /// Thrown if the value is out of the minimum and maximum range of the NumberBox. - /// - public virtual void SetValue(double value) + if (value < this.Minimum) { - double min = this.Minimum; - double max = this.Maximum; - - if (value < this.Minimum) - { - throw new ArgumentOutOfRangeException( - nameof(value), - value, - $"Value must be greater than or equal to the minimum value {min}"); - } - - if (value > this.Maximum) - { - throw new ArgumentOutOfRangeException( - nameof(value), - value, - $"Value must be less than or equal to the maximum value {max}"); - } - - this.SetText(value.ToString()); + throw new ArgumentOutOfRangeException( + nameof(value), + value, + $"Value must be greater than or equal to the minimum value {min}"); } - /// - /// Increases the number box value. - /// - public virtual void Increment() + if (value > this.Maximum) { - this.Element.SendKeys(Keys.ArrowUp); + throw new ArgumentOutOfRangeException( + nameof(value), + value, + $"Value must be less than or equal to the maximum value {max}"); } - /// - /// Decreases the number box value. - /// - public virtual void Decrement() - { - this.Element.SendKeys(Keys.ArrowDown); - } + this.SetText(value.ToString()); + } + + /// + /// Increases the number box value. + /// + /// Thrown when an element is not enabled. + /// Thrown when an element is not visible. + /// Thrown when an element is no longer valid in the document DOM. + public virtual void Increment() + { + this.Element.SendKeys(Keys.ArrowUp); + } + + /// + /// Decreases the number box value. + /// + /// Thrown when an element is not enabled. + /// Thrown when an element is not visible. + /// Thrown when an element is no longer valid in the document DOM. + public virtual void Decrement() + { + this.Element.SendKeys(Keys.ArrowDown); } } \ No newline at end of file diff --git a/src/Legerity.Web/Elements/Core/Option.cs b/src/Legerity.Web/Elements/Core/Option.cs index 624e8a54..c35f31eb 100644 --- a/src/Legerity.Web/Elements/Core/Option.cs +++ b/src/Legerity.Web/Elements/Core/Option.cs @@ -1,72 +1,77 @@ -namespace Legerity.Web.Elements.Core -{ - using Legerity.Web.Elements; - using Legerity.Web.Extensions; - using OpenQA.Selenium; - using OpenQA.Selenium.Remote; +namespace Legerity.Web.Elements.Core; + +using Legerity.Web.Elements; +using Legerity.Web.Extensions; +using OpenQA.Selenium; +using OpenQA.Selenium.Remote; +/// +/// Defines a wrapper for the core web Option control. +/// +public class Option : WebElementWrapper +{ /// - /// Defines a wrapper for the core web Option control. + /// Initializes a new instance of the class. /// - public class Option : WebElementWrapper + /// + /// The reference. + /// + public Option(IWebElement element) + : this(element as RemoteWebElement) { - /// - /// Initializes a new instance of the class. - /// - /// - /// The reference. - /// - public Option(IWebElement element) - : this(element as RemoteWebElement) - { - } + } - /// - /// Initializes a new instance of the class. - /// - /// - /// The reference. - /// - public Option(RemoteWebElement element) - : base(element) - { - } + /// + /// Initializes a new instance of the class. + /// + /// + /// The reference. + /// + public Option(RemoteWebElement element) + : base(element) + { + } - /// - /// Gets the value of the option. - /// - public virtual string Value => this.GetValue(); + /// + /// Gets the value of the option. + /// + /// Thrown when an element is no longer valid in the document DOM. + public virtual string Value => this.GetValue(); - /// - /// Gets the display value of the option. - /// - public virtual string DisplayValue => this.Element.Text; + /// + /// Gets the display value of the option. + /// + /// Thrown when an element is no longer valid in the document DOM. + public virtual string DisplayValue => this.Element.Text; - /// - /// Gets a value indicating whether the option is selected. - /// - public virtual bool IsSelected => this.Element.Selected; + /// + /// Gets a value indicating whether the option is selected. + /// + /// Thrown when an element is no longer valid in the document DOM. + public virtual bool IsSelected => this.Element.Selected; - /// - /// Allows conversion of a to the without direct casting. - /// - /// - /// The . - /// - /// - /// The . - /// - public static implicit operator Option(RemoteWebElement element) - { - return new Option(element); - } + /// + /// Allows conversion of a to the without direct casting. + /// + /// + /// The . + /// + /// + /// The . + /// + public static implicit operator Option(RemoteWebElement element) + { + return new Option(element); + } - /// - /// Selects the option. - /// - public virtual void Select() - { - this.Click(); - } + /// + /// Selects the option. + /// + /// Thrown when an element is not enabled. + /// Thrown when an element is no longer valid in the document DOM. + /// Thrown when an element is not visible. + public virtual void Select() + { + this.Click(); } } \ No newline at end of file diff --git a/src/Legerity.Web/Elements/Core/RadioButton.cs b/src/Legerity.Web/Elements/Core/RadioButton.cs index 764fc4ab..0f85cfb5 100644 --- a/src/Legerity.Web/Elements/Core/RadioButton.cs +++ b/src/Legerity.Web/Elements/Core/RadioButton.cs @@ -1,58 +1,59 @@ -namespace Legerity.Web.Elements.Core -{ - using Legerity.Web.Extensions; - using OpenQA.Selenium; - using OpenQA.Selenium.Remote; +namespace Legerity.Web.Elements.Core; + +using Legerity.Web.Extensions; +using OpenQA.Selenium; +using OpenQA.Selenium.Remote; +/// +/// Defines a wrapper for the core web Input radio control. +/// +public class RadioButton : Button +{ /// - /// Defines a wrapper for the core web Input radio control. + /// Initializes a new instance of the class. /// - public class RadioButton : Button + /// + /// The reference. + /// + public RadioButton(IWebElement element) + : this(element as RemoteWebElement) { - /// - /// Initializes a new instance of the class. - /// - /// - /// The reference. - /// - public RadioButton(IWebElement element) - : this(element as RemoteWebElement) - { - } + } - /// - /// Initializes a new instance of the class. - /// - /// - /// The reference. - /// - public RadioButton(RemoteWebElement element) - : base(element) - { - } + /// + /// Initializes a new instance of the class. + /// + /// + /// The reference. + /// + public RadioButton(RemoteWebElement element) + : base(element) + { + } - /// - /// Gets a value indicating whether the radio button is selected. - /// - public virtual bool IsSelected => this.Element.Selected; + /// + /// Gets a value indicating whether the radio button is selected. + /// + /// Thrown when an element is no longer valid in the document DOM. + public virtual bool IsSelected => this.Element.Selected; - /// - /// Gets the name of the group for the radio button. - /// - public virtual string Group => this.GetName(); + /// + /// Gets the name of the group for the radio button. + /// + /// Thrown when an element is no longer valid in the document DOM. + public virtual string Group => this.GetName(); - /// - /// Allows conversion of a to the without direct casting. - /// - /// - /// The . - /// - /// - /// The . - /// - public static implicit operator RadioButton(RemoteWebElement element) - { - return new RadioButton(element); - } + /// + /// Allows conversion of a to the without direct casting. + /// + /// + /// The . + /// + /// + /// The . + /// + public static implicit operator RadioButton(RemoteWebElement element) + { + return new RadioButton(element); } } \ No newline at end of file diff --git a/src/Legerity.Web/Elements/Core/RangeInput.cs b/src/Legerity.Web/Elements/Core/RangeInput.cs index 014037e8..5a31a3e8 100644 --- a/src/Legerity.Web/Elements/Core/RangeInput.cs +++ b/src/Legerity.Web/Elements/Core/RangeInput.cs @@ -1,119 +1,131 @@ -namespace Legerity.Web.Elements.Core +namespace Legerity.Web.Elements.Core; + +using System; +using Extensions; +using OpenQA.Selenium; +using OpenQA.Selenium.Remote; + +/// +/// Defines a wrapper for the core web Input range control. +/// +public class RangeInput : TextInput { - using System; - using OpenQA.Selenium; - using OpenQA.Selenium.Remote; + /// + /// Initializes a new instance of the class. + /// + /// + /// The reference. + /// + public RangeInput(IWebElement element) + : this(element as RemoteWebElement) + { + } /// - /// Defines a wrapper for the core web Input range control. + /// Initializes a new instance of the class. /// - public class RangeInput : TextInput + /// + /// The reference. + /// + public RangeInput(RemoteWebElement element) + : base(element) { - /// - /// Initializes a new instance of the class. - /// - /// - /// The reference. - /// - public RangeInput(IWebElement element) - : this(element as RemoteWebElement) - { - } + } - /// - /// Initializes a new instance of the class. - /// - /// - /// The reference. - /// - public RangeInput(RemoteWebElement element) - : base(element) - { - } + /// + /// Gets the minimum value of the range input. + /// + /// Thrown when an element is no longer valid in the document DOM. + public virtual double Minimum => this.GetMinimum(); - /// - /// Gets the minimum value of the range input. - /// - public virtual double Minimum => double.Parse(this.GetAttribute("min")); + /// + /// Gets the maximum value of the range input. + /// + /// Thrown when an element is no longer valid in the document DOM. + public virtual double Maximum => this.GetMaximum(); - /// - /// Gets the maximum value of the range input. - /// - public virtual double Maximum => double.Parse(this.GetAttribute("max")); + /// + /// Gets the value of the range input. + /// + /// Thrown when an element is no longer valid in the document DOM. + public virtual double Value => double.TryParse(this.Text, out double val) ? val : 0; - /// - /// Gets the value of the range input. - /// - public virtual double Value => double.TryParse(this.Text, out double val) ? val : 0; + /// + /// Allows conversion of a to the without direct casting. + /// + /// + /// The . + /// + /// + /// The . + /// + public static implicit operator RangeInput(RemoteWebElement element) + { + return new RangeInput(element); + } - /// - /// Allows conversion of a to the without direct casting. - /// - /// - /// The . - /// - /// - /// The . - /// - public static implicit operator RangeInput(RemoteWebElement element) - { - return new RangeInput(element); - } + /// + /// Sets the value of the range input. + /// + /// + /// The value. + /// + /// + /// Thrown when the value is out of the minimum and maximum range of the range input. + /// + /// Thrown when an element is not enabled. + /// Thrown when an element is not visible. + /// Thrown when an element is no longer valid in the document DOM. + public virtual void SetValue(double value) + { + double min = this.Minimum; + double max = this.Maximum; - /// - /// Sets the value of the range input. - /// - /// - /// The value. - /// - /// - /// Thrown if the value is out of the minimum and maximum range of the range input. - /// - public virtual void SetValue(double value) + if (value < this.Minimum) { - double min = this.Minimum; - double max = this.Maximum; - - if (value < this.Minimum) - { - throw new ArgumentOutOfRangeException( - nameof(value), - value, - $"Value must be greater than or equal to the minimum value {min}"); - } - - if (value > this.Maximum) - { - throw new ArgumentOutOfRangeException( - nameof(value), - value, - $"Value must be less than or equal to the maximum value {max}"); - } - - this.Click(); - - double currentValue = this.Value; - while (Math.Abs(currentValue - value) > double.Epsilon) - { - this.Element.SendKeys(currentValue < value ? Keys.ArrowRight : Keys.ArrowLeft); - currentValue = this.Value; - } + throw new ArgumentOutOfRangeException( + nameof(value), + value, + $"Value must be greater than or equal to the minimum value {min}"); } - /// - /// Increases the range input value. - /// - public virtual void Increment() + if (value > this.Maximum) { - this.Element.SendKeys(Keys.ArrowUp); + throw new ArgumentOutOfRangeException( + nameof(value), + value, + $"Value must be less than or equal to the maximum value {max}"); } - /// - /// Decreases the range input value. - /// - public virtual void Decrement() + this.Click(); + + double currentValue = this.Value; + while (Math.Abs(currentValue - value) > double.Epsilon) { - this.Element.SendKeys(Keys.ArrowDown); + this.Element.SendKeys(currentValue < value ? Keys.ArrowRight : Keys.ArrowLeft); + currentValue = this.Value; } } + + /// + /// Increases the range input value. + /// + /// Thrown when an element is not enabled. + /// Thrown when an element is not visible. + /// Thrown when an element is no longer valid in the document DOM. + public virtual void Increment() + { + this.Element.SendKeys(Keys.ArrowUp); + } + + /// + /// Decreases the range input value. + /// + /// Thrown when an element is not enabled. + /// Thrown when an element is not visible. + /// Thrown when an element is no longer valid in the document DOM. + public virtual void Decrement() + { + this.Element.SendKeys(Keys.ArrowDown); + } } \ No newline at end of file diff --git a/src/Legerity.Web/Elements/Core/Select.cs b/src/Legerity.Web/Elements/Core/Select.cs index d2d5e4b7..d34a1fb4 100644 --- a/src/Legerity.Web/Elements/Core/Select.cs +++ b/src/Legerity.Web/Elements/Core/Select.cs @@ -1,147 +1,190 @@ -namespace Legerity.Web.Elements.Core +namespace Legerity.Web.Elements.Core; + +using System; +using System.Collections.Generic; +using System.Globalization; +using System.Linq; +using Legerity.Extensions; +using Legerity.Web.Elements; +using OpenQA.Selenium; +using OpenQA.Selenium.Remote; + +/// +/// Defines a wrapper for the core web Select control. +/// +public class Select : WebElementWrapper { - using System; - using System.Collections.Generic; - using System.Globalization; - using System.Linq; - using Legerity.Extensions; - using Legerity.Web.Elements; - using OpenQA.Selenium; - using OpenQA.Selenium.Remote; + /// + /// Initializes a new instance of the class. + /// + /// + /// The reference. + /// + public Select(IWebElement element) + : this(element as RemoteWebElement) + { + } /// - /// Defines a wrapper for the core web Select control. + /// Initializes a new instance of the class. /// - public class Select : WebElementWrapper + /// + /// The reference. + /// + public Select(RemoteWebElement element) + : base(element) { - /// - /// Initializes a new instance of the class. - /// - /// - /// The reference. - /// - public Select(IWebElement element) - : this(element as RemoteWebElement) - { - } + } - /// - /// Initializes a new instance of the class. - /// - /// - /// The reference. - /// - public Select(RemoteWebElement element) - : base(element) - { - } + /// + /// Gets a value indicating whether multiple items can be selected. + /// + /// Thrown when an element is no longer valid in the document DOM. + public virtual bool IsMultiple => this.GetIsMultiple(); - /// - /// Gets a value indicating whether multiple items can be selected. - /// - public virtual bool IsMultiple => this.GetIsMultiple(); - - /// - /// Gets the collection of items associated with the select. - /// - public virtual IEnumerable