From 07aba8928643042e29154c36488ebf5cdb25d494 Mon Sep 17 00:00:00 2001 From: James Croft Date: Thu, 28 Apr 2022 18:18:45 +0100 Subject: [PATCH 1/3] Updated packages --- samples/AndroidCoreSamples/AndroidCoreSamples.csproj | 4 ++-- samples/MADESampleApp/MADESampleApp.csproj | 4 ++-- samples/TelerikUwpSdkSample/TelerikUwpSdkSample.csproj | 4 ++-- samples/W3SchoolsWebTests/W3SchoolsWebTests.csproj | 4 ++-- samples/WebTests/WebTests.csproj | 6 +++--- samples/WindowsAlarmsAndClock/WindowsAlarmsAndClock.csproj | 4 ++-- .../WindowsCommunityToolkitSampleApp.csproj | 4 ++-- samples/XamlControlsGallery/XamlControlsGallery.csproj | 4 ++-- 8 files changed, 17 insertions(+), 17 deletions(-) diff --git a/samples/AndroidCoreSamples/AndroidCoreSamples.csproj b/samples/AndroidCoreSamples/AndroidCoreSamples.csproj index b083c2d7..d0bd09fe 100644 --- a/samples/AndroidCoreSamples/AndroidCoreSamples.csproj +++ b/samples/AndroidCoreSamples/AndroidCoreSamples.csproj @@ -9,8 +9,8 @@ - - + + diff --git a/samples/MADESampleApp/MADESampleApp.csproj b/samples/MADESampleApp/MADESampleApp.csproj index 75672e1c..82da9b3c 100644 --- a/samples/MADESampleApp/MADESampleApp.csproj +++ b/samples/MADESampleApp/MADESampleApp.csproj @@ -9,8 +9,8 @@ - - + + diff --git a/samples/TelerikUwpSdkSample/TelerikUwpSdkSample.csproj b/samples/TelerikUwpSdkSample/TelerikUwpSdkSample.csproj index ac24625f..8b486c0f 100644 --- a/samples/TelerikUwpSdkSample/TelerikUwpSdkSample.csproj +++ b/samples/TelerikUwpSdkSample/TelerikUwpSdkSample.csproj @@ -9,8 +9,8 @@ - - + + diff --git a/samples/W3SchoolsWebTests/W3SchoolsWebTests.csproj b/samples/W3SchoolsWebTests/W3SchoolsWebTests.csproj index f5b8a25a..50142043 100644 --- a/samples/W3SchoolsWebTests/W3SchoolsWebTests.csproj +++ b/samples/W3SchoolsWebTests/W3SchoolsWebTests.csproj @@ -11,8 +11,8 @@ - - + + diff --git a/samples/WebTests/WebTests.csproj b/samples/WebTests/WebTests.csproj index c744f84a..ed2be74d 100644 --- a/samples/WebTests/WebTests.csproj +++ b/samples/WebTests/WebTests.csproj @@ -9,9 +9,9 @@ - - - + + + diff --git a/samples/WindowsAlarmsAndClock/WindowsAlarmsAndClock.csproj b/samples/WindowsAlarmsAndClock/WindowsAlarmsAndClock.csproj index 081a347b..1ca9543e 100644 --- a/samples/WindowsAlarmsAndClock/WindowsAlarmsAndClock.csproj +++ b/samples/WindowsAlarmsAndClock/WindowsAlarmsAndClock.csproj @@ -9,8 +9,8 @@ - - + + diff --git a/samples/WindowsCommunityToolkitSampleApp/WindowsCommunityToolkitSampleApp.csproj b/samples/WindowsCommunityToolkitSampleApp/WindowsCommunityToolkitSampleApp.csproj index 2703f88d..869710fa 100644 --- a/samples/WindowsCommunityToolkitSampleApp/WindowsCommunityToolkitSampleApp.csproj +++ b/samples/WindowsCommunityToolkitSampleApp/WindowsCommunityToolkitSampleApp.csproj @@ -9,8 +9,8 @@ - - + + diff --git a/samples/XamlControlsGallery/XamlControlsGallery.csproj b/samples/XamlControlsGallery/XamlControlsGallery.csproj index b511c7a1..afd53e64 100644 --- a/samples/XamlControlsGallery/XamlControlsGallery.csproj +++ b/samples/XamlControlsGallery/XamlControlsGallery.csproj @@ -9,8 +9,8 @@ - - + + From 099e68f36356cc481ea049531b0f739bd301397d Mon Sep 17 00:00:00 2001 From: James Croft Date: Thu, 28 Apr 2022 18:20:31 +0100 Subject: [PATCH 2/3] Moved similar core properties from platform specific wrappers to root base element wrapper class --- .../Elements/AndroidElementWrapper.cs | 5 ---- src/Legerity.Core/ElementWrapper`1.cs | 25 ++++++++++++++++++- src/Legerity.Core/IElementWrapper.cs | 17 +++++++++++++ .../Elements/IOSElementWrapper.cs | 5 ---- .../Elements/WebElementWrapper.cs | 22 ++++++++++++++-- .../Elements/WindowsElementWrapper.cs | 5 ---- 6 files changed, 61 insertions(+), 18 deletions(-) diff --git a/src/Legerity.Android/Elements/AndroidElementWrapper.cs b/src/Legerity.Android/Elements/AndroidElementWrapper.cs index fb8c7903..cf59f91d 100644 --- a/src/Legerity.Android/Elements/AndroidElementWrapper.cs +++ b/src/Legerity.Android/Elements/AndroidElementWrapper.cs @@ -29,11 +29,6 @@ protected AndroidElementWrapper(AndroidElement element) /// public AndroidDriver Driver => AppManager.AndroidApp; - /// - /// Gets a value indicating whether the element is enabled. - /// - public bool IsEnabled => this.Element.Enabled; - /// /// Determines whether the specified element is shown with the specified timeout. /// diff --git a/src/Legerity.Core/ElementWrapper`1.cs b/src/Legerity.Core/ElementWrapper`1.cs index 4d2c1440..5f5f9fe1 100644 --- a/src/Legerity.Core/ElementWrapper`1.cs +++ b/src/Legerity.Core/ElementWrapper`1.cs @@ -39,7 +39,30 @@ protected ElementWrapper(TElement element) /// /// Gets a value indicating whether the element is visible. /// - public bool IsVisible => this.Element.Displayed; + 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. + public string GetAttribute(string attributeName) + { + return this.Element.GetAttribute(attributeName); + } /// /// Finds a child element by the specified locator. diff --git a/src/Legerity.Core/IElementWrapper.cs b/src/Legerity.Core/IElementWrapper.cs index 265adfaf..a8124960 100644 --- a/src/Legerity.Core/IElementWrapper.cs +++ b/src/Legerity.Core/IElementWrapper.cs @@ -20,6 +20,23 @@ public interface IElementWrapper /// bool IsVisible { get; } + /// + /// Gets a value indicating whether the element is enabled. + /// + bool IsEnabled { get; } + + /// + /// 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); + /// /// Determines whether the given element is shown. /// diff --git a/src/Legerity.IOS/Elements/IOSElementWrapper.cs b/src/Legerity.IOS/Elements/IOSElementWrapper.cs index d670d7a4..038f4c64 100644 --- a/src/Legerity.IOS/Elements/IOSElementWrapper.cs +++ b/src/Legerity.IOS/Elements/IOSElementWrapper.cs @@ -29,11 +29,6 @@ protected IOSElementWrapper(IOSElement element) /// public IOSDriver Driver => AppManager.IOSApp; - /// - /// Gets a value indicating whether the element is enabled. - /// - public bool IsEnabled => this.Element.Enabled; - /// /// Determines whether the specified element is shown with the specified timeout. /// diff --git a/src/Legerity.Web/Elements/WebElementWrapper.cs b/src/Legerity.Web/Elements/WebElementWrapper.cs index ae4aab03..84611f6c 100644 --- a/src/Legerity.Web/Elements/WebElementWrapper.cs +++ b/src/Legerity.Web/Elements/WebElementWrapper.cs @@ -51,12 +51,12 @@ protected WebElementWrapper(RemoteWebElement element) /// /// Gets a value indicating whether the element is enabled. /// - public bool IsEnabled => this.Element.Enabled; + public virtual bool IsEnabled => this.Element.Enabled; /// /// Gets a value indicating whether the element is visible. /// - public bool IsVisible => this.Element.Displayed; + public virtual bool IsVisible => this.Element.Displayed; /// /// Finds a child element by the specified locator. @@ -95,6 +95,24 @@ public void VerifyElementNotShown(By locator) } } + /// + /// 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. + public string GetAttribute(string attributeName) + { + return this.Element.GetAttribute(attributeName); + } + /// /// Determines whether the given element is shown. /// diff --git a/src/Legerity.Windows/Elements/WindowsElementWrapper.cs b/src/Legerity.Windows/Elements/WindowsElementWrapper.cs index a6f72b67..b14971c4 100644 --- a/src/Legerity.Windows/Elements/WindowsElementWrapper.cs +++ b/src/Legerity.Windows/Elements/WindowsElementWrapper.cs @@ -28,11 +28,6 @@ protected WindowsElementWrapper(WindowsElement element) /// public WindowsDriver Driver => AppManager.WindowsApp; - /// - /// Gets a value indicating whether the element is enabled. - /// - public bool IsEnabled => this.Element.Enabled; - /// /// Determines whether the specified element is shown with the specified timeout. /// From 24ec86145f7207fd2435ad3ddf2fbda3dfab4343 Mon Sep 17 00:00:00 2001 From: James Croft Date: Thu, 28 Apr 2022 18:21:23 +0100 Subject: [PATCH 3/3] Updated element wrappers with virtual properties and methods for overrides, and added partial item matching --- src/Legerity.Android/Elements/Core/Button.cs | 8 - .../Elements/Core/CheckBox.cs | 10 +- .../Elements/Core/DatePicker.cs | 14 +- .../Elements/Core/EditText.cs | 12 +- .../Elements/Core/RadioButton.cs | 6 +- src/Legerity.Android/Elements/Core/Spinner.cs | 22 +- src/Legerity.Android/Elements/Core/Switch.cs | 13 +- .../Elements/Core/TextView.cs | 2 +- .../Elements/Core/ToggleButton.cs | 9 +- src/Legerity.Android/Elements/Core/View.cs | 8 - src/Legerity.Core/Web/WebAppManagerOptions.cs | 1 - src/Legerity.IOS/Elements/Core/Button.cs | 10 +- src/Legerity.IOS/Elements/Core/Label.cs | 2 +- .../Elements/Core/ProgressView.cs | 4 +- src/Legerity.IOS/Elements/Core/Slider.cs | 8 +- src/Legerity.IOS/Elements/Core/Switch.cs | 10 +- src/Legerity.IOS/Elements/Core/TextField.cs | 14 +- src/Legerity.MADE/DropDownList.cs | 29 ++- src/Legerity.MADE/InputValidator.cs | 6 +- .../RadAutoCompleteBox.cs | 25 +- src/Legerity.Telerik.Uwp/RadBulletGraph.cs | 7 +- src/Legerity.Telerik.Uwp/RadBusyIndicator.cs | 2 +- src/Legerity.Telerik.Uwp/RadNumericBox.cs | 23 +- src/Legerity.WCT/BladeView.cs | 28 ++- src/Legerity.WCT/BladeViewItem.cs | 6 +- src/Legerity.WCT/Carousel.cs | 31 ++- src/Legerity.WCT/Expander.cs | 14 +- src/Legerity.WCT/InAppNotification.cs | 2 +- src/Legerity.WCT/RadialGauge.cs | 27 ++- src/Legerity.Web/Elements/Core/Button.cs | 8 - src/Legerity.Web/Elements/Core/CheckBox.cs | 10 +- src/Legerity.Web/Elements/Core/FileInput.cs | 7 +- src/Legerity.Web/Elements/Core/Image.cs | 8 +- src/Legerity.Web/Elements/Core/List.cs | 2 +- src/Legerity.Web/Elements/Core/NumberInput.cs | 12 +- src/Legerity.Web/Elements/Core/Option.cs | 11 +- src/Legerity.Web/Elements/Core/RadioButton.cs | 5 +- src/Legerity.Web/Elements/Core/RangeInput.cs | 14 +- src/Legerity.Web/Elements/Core/Select.cs | 51 +++- src/Legerity.Web/Elements/Core/Table.cs | 14 +- src/Legerity.Web/Elements/Core/TableRow.cs | 2 +- src/Legerity.Web/Elements/Core/TextArea.cs | 4 +- src/Legerity.Web/Elements/Core/TextInput.cs | 13 +- .../Extensions/AttributeExtensions.cs | 83 +++++++ .../Extensions/IWebElementExtensions.cs | 34 ++- src/Legerity.Web/WebByExtras.cs | 46 ++++ src/Legerity.WinUI/InfoBar.cs | 14 +- src/Legerity.WinUI/MenuBar.cs | 23 +- src/Legerity.WinUI/MenuBarItem.cs | 47 +++- src/Legerity.WinUI/NavigationView.cs | 48 +++- src/Legerity.WinUI/NavigationViewItem.cs | 27 ++- src/Legerity.WinUI/NumberBox.cs | 25 +- src/Legerity.WinUI/RatingControl.cs | 29 ++- src/Legerity.WinUI/TabView.cs | 39 ++- .../Elements/Core/AppBarToggleButton.cs | 9 +- .../Elements/Core/AutoSuggestBox.cs | 28 ++- src/Legerity.Windows/Elements/Core/Button.cs | 8 - .../Elements/Core/CalendarDatePicker.cs | 9 +- .../Elements/Core/CalendarView.cs | 11 +- .../Elements/Core/CheckBox.cs | 17 +- .../Elements/Core/ComboBox.cs | 34 ++- .../Elements/Core/CommandBar.cs | 62 ++++- .../Elements/Core/DatePicker.cs | 4 +- .../Elements/Core/FlipView.cs | 23 +- .../Elements/Core/FlipViewItem.cs | 6 - .../Elements/Core/GridView.cs | 27 ++- src/Legerity.Windows/Elements/Core/Hub.cs | 2 +- .../Core/InkToolbar.BallpointPenFlyout.cs | 2 +- .../Core/InkToolbar.ColorFlyoutBase.cs | 28 ++- .../Core/InkToolbar.HighlighterFlyout.cs | 2 +- .../Elements/Core/InkToolbar.PencilFlyout.cs | 2 +- .../Elements/Core/InkToolbar.cs | 95 ++++++-- src/Legerity.Windows/Elements/Core/ListBox.cs | 22 +- .../Elements/Core/ListView.cs | 22 +- .../Elements/Core/MenuFlyoutItem.cs | 8 - .../Elements/Core/MenuFlyoutSubItem.cs | 47 +++- .../Elements/Core/PasswordBox.cs | 2 +- src/Legerity.Windows/Elements/Core/Pivot.cs | 25 +- .../Elements/Core/ProgressBar.cs | 5 +- .../Elements/Core/RadioButton.cs | 7 +- src/Legerity.Windows/Elements/Core/Slider.cs | 25 +- .../Elements/Core/TextBlock.cs | 2 +- src/Legerity.Windows/Elements/Core/TextBox.cs | 17 +- .../Elements/Core/TimePicker.cs | 4 +- .../Elements/Core/ToggleButton.cs | 9 +- .../Elements/Core/ToggleState.cs | 23 ++ .../Elements/Core/ToggleSwitch.cs | 13 +- .../Extensions/AttributeExtensions.cs | 226 +++++++++++++++++- .../Extensions/WindowsElementExtensions.cs | 51 +++- 89 files changed, 1319 insertions(+), 487 deletions(-) create mode 100644 src/Legerity.Web/Extensions/AttributeExtensions.cs create mode 100644 src/Legerity.Web/WebByExtras.cs delete mode 100644 src/Legerity.Windows/Elements/Core/FlipViewItem.cs create mode 100644 src/Legerity.Windows/Elements/Core/ToggleState.cs diff --git a/src/Legerity.Android/Elements/Core/Button.cs b/src/Legerity.Android/Elements/Core/Button.cs index 2d196d72..82961589 100644 --- a/src/Legerity.Android/Elements/Core/Button.cs +++ b/src/Legerity.Android/Elements/Core/Button.cs @@ -47,13 +47,5 @@ public static implicit operator Button(AppiumWebElement element) { return new Button(element as AndroidElement); } - - /// - /// Clicks the button. - /// - public void Click() - { - this.Element.Click(); - } } } \ 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 9a7057e4..0862b60f 100644 --- a/src/Legerity.Android/Elements/Core/CheckBox.cs +++ b/src/Legerity.Android/Elements/Core/CheckBox.cs @@ -24,7 +24,7 @@ public CheckBox(AndroidElement element) /// /// Gets a value indicating whether the check box is in the checked state. /// - public bool IsChecked => this.Element.GetAttribute("Checked") == CheckedValue; + public virtual bool IsChecked => this.GetAttribute("Checked") == CheckedValue; /// /// Allows conversion of a to the without direct casting. @@ -57,27 +57,27 @@ public static implicit operator CheckBox(AppiumWebElement element) /// /// Checks the check box on. /// - public void CheckOn() + public virtual void CheckOn() { if (this.IsChecked) { return; } - this.Element.Click(); + this.Click(); } /// /// Checks the check box off. /// - public void CheckOff() + public virtual void CheckOff() { if (!this.IsChecked) { return; } - this.Element.Click(); + 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 8bb0a160..9b4e728c 100644 --- a/src/Legerity.Android/Elements/Core/DatePicker.cs +++ b/src/Legerity.Android/Elements/Core/DatePicker.cs @@ -45,7 +45,7 @@ public DatePicker(AndroidElement element) /// This will be in the format, 'ddd, MMM d'. /// /// - public TextView DateTextView => this.Element.FindElement(By.Id("android:id/date_picker_header_date")); + public virtual TextView DateTextView => this.Element.FindElement(By.Id("android:id/date_picker_header_date")); /// /// Gets the element associated with the year text. @@ -53,27 +53,27 @@ public DatePicker(AndroidElement element) /// This will be in the format, 'YYYY'. /// /// - public TextView YearTextView => this.Element.FindElement(By.Id("android:id/date_picker_header_year")); + public virtual TextView YearTextView => this.Element.FindElement(By.Id("android:id/date_picker_header_year")); /// /// Gets the element associated with the day picker. /// - public View DayPickerView => this.Element.FindElement(By.Id("android:id/day_picker_view_pager")); + 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 Button NextMonthButton => this.Element.FindElementByAndroidUIAutomator("UiSelector().description(\"Next month\")"); + public virtual Button NextMonthButton => this.Element.FindElementByAndroidUIAutomator("UiSelector().description(\"Next month\")"); /// /// Gets the element associated with the previous month button. /// - public Button PreviousMonthButton => this.Element.FindElementByAndroidUIAutomator("UiSelector().description(\"Previous month\")"); + public virtual Button PreviousMonthButton => this.Element.FindElementByAndroidUIAutomator("UiSelector().description(\"Previous month\")"); /// /// Gets the selected date/time value. /// - public DateTime SelectedDate => this.GetCurrentViewDate(); + public virtual DateTime SelectedDate => this.GetCurrentViewDate(); /// /// Allows conversion of a to the without direct casting. @@ -107,7 +107,7 @@ public static implicit operator DatePicker(AppiumWebElement element) /// Sets the selected date of the date picker. /// /// The date to set to. - public void SetDate(DateTime date) + public virtual void SetDate(DateTime date) { DateTime currentViewDate = this.GetCurrentViewDate(); diff --git a/src/Legerity.Android/Elements/Core/EditText.cs b/src/Legerity.Android/Elements/Core/EditText.cs index d285e18d..d2f90d01 100644 --- a/src/Legerity.Android/Elements/Core/EditText.cs +++ b/src/Legerity.Android/Elements/Core/EditText.cs @@ -20,7 +20,7 @@ public EditText(AndroidElement element) /// /// Gets the text value of the text box. /// - public string Text => this.Element.Text; + public virtual string Text => this.Element.Text; /// /// Allows conversion of a to the without direct casting. @@ -54,7 +54,7 @@ public static implicit operator EditText(AppiumWebElement element) /// Sets the text of the text box to the specified text. /// /// The text to display. - public void SetText(string text) + public virtual void SetText(string text) { this.ClearText(); this.AppendText(text); @@ -64,18 +64,18 @@ public void SetText(string text) /// Appends the specified text to the text box. /// /// The text to append. - public void AppendText(string text) + public virtual void AppendText(string text) { - this.Element.Click(); + this.Click(); this.Element.SendKeys(text); } /// /// Clears the text from the text box. /// - public void ClearText() + public virtual void ClearText() { - this.Element.Click(); + this.Click(); this.Element.Clear(); } } diff --git a/src/Legerity.Android/Elements/Core/RadioButton.cs b/src/Legerity.Android/Elements/Core/RadioButton.cs index ab85f08d..b9b0ef0e 100644 --- a/src/Legerity.Android/Elements/Core/RadioButton.cs +++ b/src/Legerity.Android/Elements/Core/RadioButton.cs @@ -23,10 +23,8 @@ public RadioButton(AndroidElement element) /// /// Gets a value indicating whether the radio button is selected. /// - public bool IsSelected => - this.Element.GetAttribute("Checked").Equals( - "True", - StringComparison.CurrentCultureIgnoreCase); + public virtual bool IsSelected => + this.GetAttribute("Checked").Equals("True", StringComparison.CurrentCultureIgnoreCase); /// /// Allows conversion of a to the without direct casting. diff --git a/src/Legerity.Android/Elements/Core/Spinner.cs b/src/Legerity.Android/Elements/Core/Spinner.cs index c1db0bc3..1ba0e0dd 100644 --- a/src/Legerity.Android/Elements/Core/Spinner.cs +++ b/src/Legerity.Android/Elements/Core/Spinner.cs @@ -23,7 +23,7 @@ public Spinner(AndroidElement element) /// /// Gets the currently selected item. /// - public string SelectedItem => this.GetSelectedItem(); + public virtual string SelectedItem => this.GetSelectedItem(); /// /// Allows conversion of a to the without direct casting. @@ -59,9 +59,9 @@ public static implicit operator Spinner(AppiumWebElement element) /// /// The name of the item to select. /// - public void SelectItem(string name) + public virtual void SelectItem(string name) { - this.Element.Click(); + this.Click(); var locator = new ByAndroidUIAutomator( @@ -71,6 +71,22 @@ public void SelectItem(string name) 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(); + + var locator = + new ByAndroidUIAutomator( + $"new UiScrollable(new UiSelector()).scrollIntoView(new UiSelector().textContains(\"{partialName}\"));"); + AndroidElement item = this.Driver.FindElement(locator); + + item.Click(); + } + private string GetSelectedItem() { TextView textElement = this.Element.FindElement(By.ClassName("android.widget.TextView")); diff --git a/src/Legerity.Android/Elements/Core/Switch.cs b/src/Legerity.Android/Elements/Core/Switch.cs index 365d6000..7a9479e4 100644 --- a/src/Legerity.Android/Elements/Core/Switch.cs +++ b/src/Legerity.Android/Elements/Core/Switch.cs @@ -1,5 +1,6 @@ namespace Legerity.Android.Elements.Core { + using System; using OpenQA.Selenium.Appium; using OpenQA.Selenium.Appium.Android; @@ -8,8 +9,6 @@ namespace Legerity.Android.Elements.Core /// public class Switch : AndroidElementWrapper { - private const string ToggleOnValue = "true"; - /// /// Initializes a new instance of the class. /// @@ -24,7 +23,7 @@ public Switch(AndroidElement element) /// /// Gets a value indicating whether the toggle switch is in the on position. /// - public bool IsOn => this.Element.GetAttribute("Checked") == ToggleOnValue; + public virtual bool IsOn => this.GetAttribute("Checked").Equals("True", StringComparison.CurrentCultureIgnoreCase); /// /// Allows conversion of a to the without direct casting. @@ -57,27 +56,27 @@ public static implicit operator Switch(AppiumWebElement element) /// /// Toggles the switch on. /// - public void ToggleOn() + public virtual void ToggleOn() { if (this.IsOn) { return; } - this.Element.Click(); + this.Click(); } /// /// Toggles the switch off. /// - public void ToggleOff() + public virtual void ToggleOff() { if (!this.IsOn) { return; } - this.Element.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 1b9b5003..5456fb47 100644 --- a/src/Legerity.Android/Elements/Core/TextView.cs +++ b/src/Legerity.Android/Elements/Core/TextView.cs @@ -22,7 +22,7 @@ public TextView(AndroidElement element) /// /// Gets the text value of the text view. /// - public string Text => this.Element.Text; + public virtual string Text => this.Element.Text; /// /// Allows conversion of a to the without direct casting. diff --git a/src/Legerity.Android/Elements/Core/ToggleButton.cs b/src/Legerity.Android/Elements/Core/ToggleButton.cs index 670dd1f9..1e63fbaa 100644 --- a/src/Legerity.Android/Elements/Core/ToggleButton.cs +++ b/src/Legerity.Android/Elements/Core/ToggleButton.cs @@ -1,5 +1,6 @@ namespace Legerity.Android.Elements.Core { + using System; using OpenQA.Selenium.Appium; using OpenQA.Selenium.Appium.Android; @@ -8,8 +9,6 @@ namespace Legerity.Android.Elements.Core /// public class ToggleButton : Button { - private const string ToggleOnValue = "true"; - /// /// Initializes a new instance of the class. /// @@ -24,7 +23,7 @@ public ToggleButton(AndroidElement element) /// /// Gets a value indicating whether the toggle button is in the on position. /// - public bool IsOn => this.Element.GetAttribute("Checked") == ToggleOnValue; + public virtual bool IsOn => this.GetAttribute("Checked").Equals("True", StringComparison.CurrentCultureIgnoreCase); /// /// Allows conversion of a to the without direct casting. @@ -57,7 +56,7 @@ public static implicit operator ToggleButton(AppiumWebElement element) /// /// Toggles the button on. /// - public void ToggleOn() + public virtual void ToggleOn() { if (this.IsOn) { @@ -70,7 +69,7 @@ public void ToggleOn() /// /// Toggles the button off. /// - public void ToggleOff() + public virtual void ToggleOff() { if (!this.IsOn) { diff --git a/src/Legerity.Android/Elements/Core/View.cs b/src/Legerity.Android/Elements/Core/View.cs index 3b7aecf8..759c42bf 100644 --- a/src/Legerity.Android/Elements/Core/View.cs +++ b/src/Legerity.Android/Elements/Core/View.cs @@ -47,13 +47,5 @@ public static implicit operator View(AppiumWebElement element) { return new View(element as AndroidElement); } - - /// - /// Clicks the element. - /// - public void Click() - { - this.Element.Click(); - } } } \ No newline at end of file diff --git a/src/Legerity.Core/Web/WebAppManagerOptions.cs b/src/Legerity.Core/Web/WebAppManagerOptions.cs index eb1fef71..fdef1b69 100644 --- a/src/Legerity.Core/Web/WebAppManagerOptions.cs +++ b/src/Legerity.Core/Web/WebAppManagerOptions.cs @@ -11,7 +11,6 @@ public class WebAppManagerOptions : AppManagerOptions /// /// Initializes a new instance of the class. /// - public WebAppManagerOptions() { } diff --git a/src/Legerity.IOS/Elements/Core/Button.cs b/src/Legerity.IOS/Elements/Core/Button.cs index d14c4bc6..42b4594b 100644 --- a/src/Legerity.IOS/Elements/Core/Button.cs +++ b/src/Legerity.IOS/Elements/Core/Button.cs @@ -23,7 +23,7 @@ public Button(IOSElement element) /// /// Gets the button's label content. /// - public string Label => this.Element.GetLabel(); + public virtual string Label => this.Element.GetLabel(); /// /// Allows conversion of a to the without direct casting. @@ -52,13 +52,5 @@ public static implicit operator Button(AppiumWebElement element) { return new Button(element as IOSElement); } - - /// - /// Clicks the button. - /// - public void Click() - { - this.Element.Click(); - } } } \ 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 f0caa4e7..089edaf1 100644 --- a/src/Legerity.IOS/Elements/Core/Label.cs +++ b/src/Legerity.IOS/Elements/Core/Label.cs @@ -23,7 +23,7 @@ public Label(IOSElement element) /// /// Gets the text value of the label. /// - public string Text => this.Element.GetLabel(); + public virtual string Text => this.Element.GetLabel(); /// /// Allows conversion of a to the without direct casting. diff --git a/src/Legerity.IOS/Elements/Core/ProgressView.cs b/src/Legerity.IOS/Elements/Core/ProgressView.cs index 17c18e91..b71c8d70 100644 --- a/src/Legerity.IOS/Elements/Core/ProgressView.cs +++ b/src/Legerity.IOS/Elements/Core/ProgressView.cs @@ -23,8 +23,8 @@ public ProgressView(IOSElement element) /// /// Gets the value of the progress bar. /// - public double Percentage => double.Parse(this.Element.GetValue().TrimEnd('%')); - + public virtual double Percentage => double.Parse(this.Element.GetValue().TrimEnd('%')); + /// /// Allows conversion of a to the without direct casting. /// diff --git a/src/Legerity.IOS/Elements/Core/Slider.cs b/src/Legerity.IOS/Elements/Core/Slider.cs index a9484bad..78a31776 100644 --- a/src/Legerity.IOS/Elements/Core/Slider.cs +++ b/src/Legerity.IOS/Elements/Core/Slider.cs @@ -25,12 +25,12 @@ public Slider(IOSElement element) /// /// Gets the value of the slider as a percentage between 0 and 100. /// - public double Value => double.Parse(this.Element.GetValue().TrimEnd('%')); + public virtual double Value => double.Parse(this.Element.GetValue().TrimEnd('%')); /// /// Gets a value indicating whether the control is in a readonly state. /// - public bool IsReadonly => !this.IsEnabled; + public virtual bool IsReadonly => !this.IsEnabled; /// /// Allows conversion of a to the without direct casting. @@ -66,9 +66,9 @@ public static implicit operator Slider(AppiumWebElement element) /// /// The value. /// - public void SetValue(double value) + public virtual void SetValue(double value) { - this.Element.Click(); + this.Click(); double currentValue = this.Value; while (Math.Abs(currentValue - value) > double.Epsilon) diff --git a/src/Legerity.IOS/Elements/Core/Switch.cs b/src/Legerity.IOS/Elements/Core/Switch.cs index a21468a3..4ac487ca 100644 --- a/src/Legerity.IOS/Elements/Core/Switch.cs +++ b/src/Legerity.IOS/Elements/Core/Switch.cs @@ -25,7 +25,7 @@ public Switch(IOSElement element) /// /// Gets a value indicating whether the toggle switch is in the on position. /// - public bool IsOn => this.Element.GetValue() == ToggleOnValue; + public virtual bool IsOn => this.Element.GetValue() == ToggleOnValue; /// /// Allows conversion of a to the without direct casting. @@ -58,27 +58,27 @@ public static implicit operator Switch(AppiumWebElement element) /// /// Toggles the switch on. /// - public void ToggleOn() + public virtual void ToggleOn() { if (this.IsOn) { return; } - this.Element.Click(); + this.Click(); } /// /// Toggles the switch off. /// - public void ToggleOff() + public virtual void ToggleOff() { if (!this.IsOn) { return; } - this.Element.Click(); + 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 9ce1a9af..9052289d 100644 --- a/src/Legerity.IOS/Elements/Core/TextField.cs +++ b/src/Legerity.IOS/Elements/Core/TextField.cs @@ -22,12 +22,12 @@ public TextField(IOSElement element) /// /// Gets the text value of the text field. /// - public string Text => this.Element.GetValue(); + public virtual string Text => this.Element.GetValue(); /// /// Gets the element associated with the clear text button, if shown. /// - public Button ClearTextButton => this.Element.FindElement(IOSByExtras.Label("Clear text")); + public virtual Button ClearTextButton => this.Element.FindElement(IOSByExtras.Label("Clear text")); /// /// Allows conversion of a to the without direct casting. @@ -61,7 +61,7 @@ public static implicit operator TextField(AppiumWebElement element) /// Sets the text of the text field to the specified text. /// /// The text to display. - public void SetText(string text) + public virtual void SetText(string text) { this.ClearText(); this.AppendText(text); @@ -71,18 +71,18 @@ public void SetText(string text) /// Appends the specified text to the text field. /// /// The text to append. - public void AppendText(string text) + public virtual void AppendText(string text) { - this.Element.Click(); + this.Click(); this.Element.SendKeys(text); } /// /// Clears the text from the text field. /// - public void ClearText() + public virtual void ClearText() { - this.Element.Click(); + this.Click(); this.Element.Clear(); } } diff --git a/src/Legerity.MADE/DropDownList.cs b/src/Legerity.MADE/DropDownList.cs index ca825167..94b84828 100644 --- a/src/Legerity.MADE/DropDownList.cs +++ b/src/Legerity.MADE/DropDownList.cs @@ -25,7 +25,7 @@ public DropDownList(WindowsElement element) /// /// Gets the element associated with the drop down content. /// - public ListView DropDown => this.Element.FindElement(WindowsByExtras.AutomationId("DropDownContent")); + public virtual ListView DropDown => this.Element.FindElement(WindowsByExtras.AutomationId("DropDownContent")); /// /// Allows conversion of a to the without direct casting. @@ -61,21 +61,38 @@ public static implicit operator DropDownList(AppiumWebElement element) /// /// The name of the item to select. /// - public void SelectItem(string name) + public virtual void SelectItem(string name) + { + this.OpenDropDown(); + this.DropDown.ClickItem(name); + } + + /// + /// 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.OpenDropDown(); + this.DropDown.ClickItemByPartialName(partialName); + } + + /// + /// Opens the drop down if it is not already open. + /// + public virtual void OpenDropDown() { if (!this.IsDropDownOpen()) { - this.Element.Click(); + this.Click(); } - - this.DropDown.ClickItem(name); } /// /// Determines whether the drop down is open. /// /// True if the drop down is open; otherwise, false. - public bool IsDropDownOpen() + public virtual bool IsDropDownOpen() { bool isVisible; diff --git a/src/Legerity.MADE/InputValidator.cs b/src/Legerity.MADE/InputValidator.cs index 44cc7fd7..8de76e90 100644 --- a/src/Legerity.MADE/InputValidator.cs +++ b/src/Legerity.MADE/InputValidator.cs @@ -24,12 +24,12 @@ public InputValidator(WindowsElement element) /// /// Gets the associated with the validation feedback message. /// - public TextBlock ValidationFeedback => this.Element.FindElement(WindowsByExtras.AutomationId("ValidatorFeedbackMessage")); + public virtual TextBlock ValidationFeedback => this.Element.FindElement(WindowsByExtras.AutomationId("ValidatorFeedbackMessage")); /// /// Gets the validation feedback message associated with the element. /// - public string Message => this.ValidationFeedback?.Text; + public virtual string Message => this.ValidationFeedback?.Text; /// /// Allows conversion of a to the without direct casting. @@ -73,7 +73,7 @@ public AppiumWebElement Input(By locator) /// Retrieves the feedback message text if the is shown. /// /// The feedback message text of the element. - public string FeedbackMessage() + public virtual string FeedbackMessage() { string message; diff --git a/src/Legerity.Telerik.Uwp/RadAutoCompleteBox.cs b/src/Legerity.Telerik.Uwp/RadAutoCompleteBox.cs index dc42cfc3..044098b0 100644 --- a/src/Legerity.Telerik.Uwp/RadAutoCompleteBox.cs +++ b/src/Legerity.Telerik.Uwp/RadAutoCompleteBox.cs @@ -27,12 +27,12 @@ public RadAutoCompleteBox(WindowsElement element) /// /// Gets the element associated with the text box. /// - public TextBox TextBox => this.Element.FindElement(By.ClassName("TextBox")); + public virtual TextBox TextBox => this.Element.FindElement(By.ClassName("TextBox")); /// /// Gets the value of the auto-suggest box. /// - public string Text => this.TextBox.Text; + public virtual string Text => this.TextBox.Text; /// /// Allows conversion of a to the without direct casting. @@ -66,7 +66,7 @@ public static implicit operator RadAutoCompleteBox(AppiumWebElement element) /// Selects a suggestion from the auto-suggest box. /// /// The suggestion to select. - public void SelectSuggestion(string suggestion) + public virtual void SelectSuggestion(string suggestion) { this.SelectSuggestion(suggestion, suggestion); } @@ -76,7 +76,7 @@ public void SelectSuggestion(string suggestion) /// /// The initial value to set. /// The suggestion to select. - public void SelectSuggestion(string value, string suggestion) + public virtual void SelectSuggestion(string value, string suggestion) { this.SetText(value); @@ -86,11 +86,26 @@ public void SelectSuggestion(string value, string suggestion) 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 void SetText(string value) + public virtual void SetText(string value) { this.TextBox.SetText(value); } diff --git a/src/Legerity.Telerik.Uwp/RadBulletGraph.cs b/src/Legerity.Telerik.Uwp/RadBulletGraph.cs index 429786d8..b5448f4d 100644 --- a/src/Legerity.Telerik.Uwp/RadBulletGraph.cs +++ b/src/Legerity.Telerik.Uwp/RadBulletGraph.cs @@ -1,5 +1,6 @@ namespace Legerity.Windows.Elements.Telerik { + using Legerity.Windows.Extensions; using OpenQA.Selenium.Appium; using OpenQA.Selenium.Appium.Windows; @@ -22,17 +23,17 @@ public RadBulletGraph(WindowsElement element) /// /// Gets the minimum value of the bullet graph. /// - public double Minimum => double.Parse(this.Element.GetAttribute("RangeValue.Minimum")); + public virtual double Minimum => this.GetRangeMinimum(); /// /// Gets the maximum value of the bullet graph. /// - public double Maximum => double.Parse(this.Element.GetAttribute("RangeValue.Maximum")); + public virtual double Maximum => this.GetRangeMaximum(); /// /// Gets the value of the bullet graph. /// - public double Value => double.Parse(this.Element.GetAttribute("RangeValue.Value")); + public virtual double Value => this.GetRangeValue(); /// /// Allows conversion of a to the without direct casting. diff --git a/src/Legerity.Telerik.Uwp/RadBusyIndicator.cs b/src/Legerity.Telerik.Uwp/RadBusyIndicator.cs index 5cc3a346..4ca4540b 100644 --- a/src/Legerity.Telerik.Uwp/RadBusyIndicator.cs +++ b/src/Legerity.Telerik.Uwp/RadBusyIndicator.cs @@ -24,7 +24,7 @@ public RadBusyIndicator(WindowsElement element) /// /// Gets a value indicating whether the busy indicator is on. /// - public bool IsOn => this.Element.GetAttribute("ItemStatus") == OnValue; + public virtual bool IsOn => this.GetAttribute("ItemStatus") == OnValue; /// /// Allows conversion of a to the without direct casting. diff --git a/src/Legerity.Telerik.Uwp/RadNumericBox.cs b/src/Legerity.Telerik.Uwp/RadNumericBox.cs index 7413738c..24c7152c 100644 --- a/src/Legerity.Telerik.Uwp/RadNumericBox.cs +++ b/src/Legerity.Telerik.Uwp/RadNumericBox.cs @@ -2,6 +2,7 @@ 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; @@ -25,42 +26,42 @@ public RadNumericBox(WindowsElement element) /// /// Gets the minimum value of the RadNumericBox. /// - public double Minimum => double.Parse(this.Element.GetAttribute("RangeValue.Minimum")); + public virtual double Minimum => this.GetRangeMinimum(); /// /// Gets the maximum value of the RadNumericBox. /// - public double Maximum => double.Parse(this.Element.GetAttribute("RangeValue.Maximum")); + public virtual double Maximum => this.GetRangeMaximum(); /// /// Gets the small change (step) value of the RadNumericBox. /// - public double SmallChange => double.Parse(this.Element.GetAttribute("RangeValue.SmallChange")); + public virtual double SmallChange => this.GetRangeSmallChange(); /// /// Gets the value of the RadNumericBox. /// - public double Value => double.Parse(this.Element.GetAttribute("RangeValue.Value")); + public virtual double Value => this.GetRangeValue(); /// /// Gets a value indicating whether the control is in a readonly state. /// - public bool IsReadonly => bool.Parse(this.Element.GetAttribute("RangeValue.IsReadOnly")); + public virtual bool IsReadonly => this.IsRangeReadonly(); /// /// Gets the element associated with the increase button. /// - public Button Increase => this.Element.FindElement(WindowsByExtras.AutomationId("PART_IncreaseButton")); + public virtual Button Increase => this.Element.FindElement(WindowsByExtras.AutomationId("PART_IncreaseButton")); /// /// Gets the element associated with the decrease button. /// - public Button DecreaseButton => this.Element.FindElement(WindowsByExtras.AutomationId("PART_DecreaseButton")); + public virtual Button DecreaseButton => this.Element.FindElement(WindowsByExtras.AutomationId("PART_DecreaseButton")); /// /// Gets the element associated with the input text box. /// - public TextBox InputBox => this.Element.FindElement(WindowsByExtras.AutomationId("PART_TextBox")); + public virtual TextBox InputBox => this.Element.FindElement(WindowsByExtras.AutomationId("PART_TextBox")); /// /// Allows conversion of a to the without direct casting. @@ -99,7 +100,7 @@ public static implicit operator RadNumericBox(AppiumWebElement element) /// /// Thrown if the value is out of the minimum and maximum range of the RadNumericBox. /// - public void SetValue(double value) + public virtual void SetValue(double value) { double min = this.Minimum; double max = this.Maximum; @@ -127,7 +128,7 @@ public void SetValue(double value) /// /// Increases the number box value by the value. /// - public void Increment() + public virtual void Increment() { this.Increase.Click(); } @@ -135,7 +136,7 @@ public void Increment() /// /// Decreases the number box value by the value. /// - public void Decrement() + public virtual void Decrement() { this.DecreaseButton.Click(); } diff --git a/src/Legerity.WCT/BladeView.cs b/src/Legerity.WCT/BladeView.cs index d15d1bfe..aa1437f1 100644 --- a/src/Legerity.WCT/BladeView.cs +++ b/src/Legerity.WCT/BladeView.cs @@ -26,7 +26,7 @@ public BladeView(WindowsElement element) /// /// Gets the UI components associated with the child blades. /// - public IEnumerable Blades => + public virtual IEnumerable Blades => this.Element.FindElements(By.ClassName("BladeItem")) .Select(element => new BladeViewItem(this, element as WindowsElement)); @@ -63,19 +63,39 @@ public static implicit operator BladeView(AppiumWebElement element) /// /// The name of the blade to retrieve. /// A instance if found; otherwise, null. - public BladeViewItem GetBlade(string name) + public virtual BladeViewItem GetBlade(string name) { return this.Blades.FirstOrDefault(element => element.Element.VerifyNameOrAutomationIdEquals(name)); } /// - /// Closes an open blade. + /// 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)); + } + + /// + /// Closes an open blade by name. /// /// The name of the blade to close. - public void CloseBlade(string name) + 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(); + } } } \ No newline at end of file diff --git a/src/Legerity.WCT/BladeViewItem.cs b/src/Legerity.WCT/BladeViewItem.cs index 1b629857..f2a83319 100644 --- a/src/Legerity.WCT/BladeViewItem.cs +++ b/src/Legerity.WCT/BladeViewItem.cs @@ -51,17 +51,17 @@ public BladeViewItem( /// /// Gets the element associated with the blade enlarge option. /// - public Button EnlargeButton => this.Element.FindElement(WindowsByExtras.AutomationId("EnlargeButton")); + public virtual Button EnlargeButton => this.Element.FindElement(WindowsByExtras.AutomationId("EnlargeButton")); /// /// Gets the element associated with the blade close option. /// - public Button CloseButton => this.Element.FindElement(WindowsByExtras.AutomationId("CloseButton")); + public virtual Button CloseButton => this.Element.FindElement(WindowsByExtras.AutomationId("CloseButton")); /// /// Closes the blade item. /// - public void Close() + public virtual void Close() { this.CloseButton.Click(); } diff --git a/src/Legerity.WCT/Carousel.cs b/src/Legerity.WCT/Carousel.cs index d18b84fa..c97e10ad 100644 --- a/src/Legerity.WCT/Carousel.cs +++ b/src/Legerity.WCT/Carousel.cs @@ -30,21 +30,17 @@ public Carousel(WindowsElement element) /// /// Gets the collection of items associated with the carousel. /// - public ReadOnlyCollection Items => this.Element.FindElements(this.carouselItemLocator); + public virtual ReadOnlyCollection Items => this.Element.FindElements(this.carouselItemLocator); /// /// Gets the element associated with the currently selected item. /// - public AppiumWebElement SelectedItem => - this.Items.FirstOrDefault( - i => i.GetAttribute("SelectionItem.IsSelected").Equals( - "True", - StringComparison.CurrentCultureIgnoreCase)); + public virtual AppiumWebElement SelectedItem => this.Items.FirstOrDefault(i => i.IsSelected()); /// /// Gets the index of the element associated with the currently selected item. /// - public int SelectedIndex => this.Items.IndexOf(this.SelectedItem); + public virtual int SelectedIndex => this.Items.IndexOf(this.SelectedItem); /// /// Allows conversion of a to the without direct casting. @@ -80,7 +76,7 @@ public static implicit operator Carousel(AppiumWebElement element) /// /// The name of the item to click. /// - public void SelectItem(string name) + public virtual void SelectItem(string name) { this.VerifyElementsShown(this.carouselItemLocator, TimeSpan.FromSeconds(2)); @@ -93,6 +89,25 @@ public void SelectItem(string name) } } + /// + /// 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)); + + int index = this.Items.IndexOf(this.Items.FirstOrDefault(element => element.VerifyNameOrAutomationIdContains(partialName))); + int selectedIndex = this.SelectedIndex; + while (Math.Abs(index - selectedIndex) > double.Epsilon) + { + this.Element.SendKeys(selectedIndex < index ? Keys.ArrowRight : Keys.ArrowLeft); + selectedIndex = this.SelectedIndex; + } + } + /// /// Clicks on an item in the carousel with the specified item name. /// diff --git a/src/Legerity.WCT/Expander.cs b/src/Legerity.WCT/Expander.cs index 453e73c0..9cce942c 100644 --- a/src/Legerity.WCT/Expander.cs +++ b/src/Legerity.WCT/Expander.cs @@ -1,6 +1,7 @@ namespace Legerity.Windows.Elements.WCT { using Legerity.Windows.Elements.Core; + using Legerity.Windows.Extensions; using OpenQA.Selenium.Appium; using OpenQA.Selenium.Appium.Windows; @@ -9,8 +10,6 @@ namespace Legerity.Windows.Elements.WCT /// public class Expander : WindowsElementWrapper { - private const string ToggleOnValue = "1"; - /// /// Initializes a new instance of the class. /// @@ -25,9 +24,12 @@ public Expander(WindowsElement element) /// /// Gets a value indicating whether the expander has the content expanded (visible). /// - public bool IsExpanded => this.Element.GetAttribute("Toggle.ToggleState") == ToggleOnValue; + public virtual bool IsExpanded => this.GetToggleState() == ToggleState.Checked; - private ToggleButton ToggleButton => this.Element.FindElement(WindowsByExtras.AutomationId("PART_ExpanderToggleButton")); + /// + /// Gets the associated with the expander. + /// + public virtual ToggleButton ToggleButton => this.Element.FindElement(WindowsByExtras.AutomationId("PART_ExpanderToggleButton")); /// /// Allows conversion of a to the without direct casting. @@ -60,7 +62,7 @@ public static implicit operator Expander(AppiumWebElement element) /// /// Expands the content of the expander. /// - public void Expand() + public virtual void Expand() { if (this.IsExpanded) { @@ -73,7 +75,7 @@ public void Expand() /// /// Collapses the content of the expander. /// - public void Collapse() + public virtual void Collapse() { if (!this.IsExpanded) { diff --git a/src/Legerity.WCT/InAppNotification.cs b/src/Legerity.WCT/InAppNotification.cs index 964f1d4e..bc5304e3 100644 --- a/src/Legerity.WCT/InAppNotification.cs +++ b/src/Legerity.WCT/InAppNotification.cs @@ -32,7 +32,7 @@ public InAppNotification(WindowsElement element) /// Note, this only works if the Content is based on a or if the ContentTemplate includes a TextBlock element with the message. /// /// - public string Message => this.Element.FindElementsByClassName("TextBlock").FirstOrDefault()?.Text; + public virtual string Message => this.Element.FindElementsByClassName("TextBlock").FirstOrDefault()?.Text; /// /// Allows conversion of a to the without direct casting. diff --git a/src/Legerity.WCT/RadialGauge.cs b/src/Legerity.WCT/RadialGauge.cs index c734e587..9cedc6a6 100644 --- a/src/Legerity.WCT/RadialGauge.cs +++ b/src/Legerity.WCT/RadialGauge.cs @@ -1,6 +1,7 @@ namespace Legerity.Windows.Elements.WCT { using System; + using Legerity.Windows.Extensions; using OpenQA.Selenium; using OpenQA.Selenium.Appium; using OpenQA.Selenium.Appium.Windows; @@ -24,27 +25,27 @@ public RadialGauge(WindowsElement element) /// /// Gets the minimum value of the gauge. /// - public double Minimum => double.Parse(this.Element.GetAttribute("RangeValue.Minimum")); + public virtual double Minimum => this.GetRangeMinimum(); /// /// Gets the maximum value of the gauge. /// - public double Maximum => double.Parse(this.Element.GetAttribute("RangeValue.Maximum")); + public virtual double Maximum => this.GetRangeMaximum(); /// /// Gets the small change (step) value of the gauge. /// - public double SmallChange => double.Parse(this.Element.GetAttribute("RangeValue.SmallChange")); + public virtual double SmallChange => this.GetRangeSmallChange(); /// /// Gets the value of the gauge. /// - public double Value => double.Parse(this.Element.GetAttribute("RangeValue.Value")); + public virtual double Value => this.GetRangeValue(); /// /// Gets a value indicating whether the control is in a readonly state. /// - public bool IsReadonly => bool.Parse(this.Element.GetAttribute("RangeValue.IsReadOnly")); + public virtual bool IsReadonly => this.IsRangeReadonly(); /// /// Allows conversion of a to the without direct casting. @@ -83,22 +84,28 @@ public static implicit operator RadialGauge(AppiumWebElement element) /// /// Thrown if the value is out of the minimum and maximum range of the gauge. /// - public void SetValue(double value) + public virtual void SetValue(double value) { 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}"); + 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.Element.Click(); + this.Click(); double currentValue = this.Value; while (Math.Abs(currentValue - value) > double.Epsilon) @@ -108,4 +115,4 @@ public void SetValue(double value) } } } -} +} \ 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 bdb651c5..70c41818 100644 --- a/src/Legerity.Web/Elements/Core/Button.cs +++ b/src/Legerity.Web/Elements/Core/Button.cs @@ -44,13 +44,5 @@ public static implicit operator Button(RemoteWebElement element) { return new Button(element); } - - /// - /// Clicks the button. - /// - public void Click() - { - this.Element.Click(); - } } } \ 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 a9f56fe7..5a024ac1 100644 --- a/src/Legerity.Web/Elements/Core/CheckBox.cs +++ b/src/Legerity.Web/Elements/Core/CheckBox.cs @@ -34,7 +34,7 @@ public CheckBox(RemoteWebElement element) /// /// Gets a value indicating whether the check box is in the checked state. /// - public bool IsChecked => this.Element.Selected; + public virtual bool IsChecked => this.Element.Selected; /// /// Allows conversion of a to the without direct casting. @@ -53,27 +53,27 @@ public static implicit operator CheckBox(RemoteWebElement element) /// /// Checks the check box on. /// - public void CheckOn() + public virtual void CheckOn() { if (this.IsChecked) { return; } - this.Element.Click(); + this.Click(); } /// /// Checks the check box off. /// - public void CheckOff() + public virtual void CheckOff() { if (!this.IsChecked) { return; } - this.Element.Click(); + this.Click(); } } } \ No newline at end of file diff --git a/src/Legerity.Web/Elements/Core/FileInput.cs b/src/Legerity.Web/Elements/Core/FileInput.cs index d3ae85de..1b44083f 100644 --- a/src/Legerity.Web/Elements/Core/FileInput.cs +++ b/src/Legerity.Web/Elements/Core/FileInput.cs @@ -1,6 +1,7 @@ namespace Legerity.Web.Elements.Core { using Legerity.Web.Elements; + using Legerity.Web.Extensions; using OpenQA.Selenium; using OpenQA.Selenium.Remote; @@ -34,7 +35,7 @@ public FileInput(RemoteWebElement element) /// /// Gets the file path for the selected file. /// - public string FilePath => this.Element.GetAttribute("value"); + public virtual string FilePath => this.GetValue(); /// /// Allows conversion of a to the without direct casting. @@ -54,7 +55,7 @@ public static implicit operator FileInput(RemoteWebElement element) /// Sets the selected file by an absolute file path. /// /// The file path. - public void SetAbsoluteFilePath(string filePath) + public virtual void SetAbsoluteFilePath(string filePath) { this.ClearFile(); this.Element.SendKeys(filePath); @@ -63,7 +64,7 @@ public void SetAbsoluteFilePath(string filePath) /// /// Clears the selected file. /// - public void ClearFile() + public virtual void ClearFile() { this.Element.Clear(); } diff --git a/src/Legerity.Web/Elements/Core/Image.cs b/src/Legerity.Web/Elements/Core/Image.cs index dcd1b2ed..d1cf201a 100644 --- a/src/Legerity.Web/Elements/Core/Image.cs +++ b/src/Legerity.Web/Elements/Core/Image.cs @@ -34,22 +34,22 @@ public Image(RemoteWebElement element) /// /// Gets the source URI of the image. /// - public string Source => this.Element.GetAttribute("src"); + public virtual string Source => this.GetAttribute("src"); /// /// Gets the alt text of the image. /// - public string AltText => this.Element.GetAttribute("alt"); + public virtual string AltText => this.GetAttribute("alt"); /// /// Gets the width of the image. /// - public double Width => double.Parse(this.Element.GetAttribute("width")); + public virtual double Width => double.Parse(this.GetAttribute("width")); /// /// Gets the height of the image. /// - public double Height => double.Parse(this.Element.GetAttribute("height")); + public virtual double Height => double.Parse(this.GetAttribute("height")); /// /// Allows conversion of a to the without direct casting. diff --git a/src/Legerity.Web/Elements/Core/List.cs b/src/Legerity.Web/Elements/Core/List.cs index 4c8deb4d..fdcb07f5 100644 --- a/src/Legerity.Web/Elements/Core/List.cs +++ b/src/Legerity.Web/Elements/Core/List.cs @@ -35,7 +35,7 @@ public List(RemoteWebElement element) /// /// Gets the collection of items associated with the list. /// - public ReadOnlyCollection Items => this.Element.FindElements(By.TagName("li")); + public virtual ReadOnlyCollection Items => this.Element.FindElements(WebByExtras.ListItem()); /// /// Allows conversion of a to the without direct casting. diff --git a/src/Legerity.Web/Elements/Core/NumberInput.cs b/src/Legerity.Web/Elements/Core/NumberInput.cs index 96004f6e..43541729 100644 --- a/src/Legerity.Web/Elements/Core/NumberInput.cs +++ b/src/Legerity.Web/Elements/Core/NumberInput.cs @@ -34,17 +34,17 @@ public NumberInput(RemoteWebElement element) /// /// Gets the minimum value of the NumberBox. /// - public double Minimum => double.Parse(this.Element.GetAttribute("min")); + public virtual double Minimum => double.Parse(this.GetAttribute("min")); /// /// Gets the maximum value of the NumberBox. /// - public double Maximum => double.Parse(this.Element.GetAttribute("max")); + public virtual double Maximum => double.Parse(this.GetAttribute("max")); /// /// Gets the value of the NumberBox. /// - public double Value => double.TryParse(this.Text, out double val) ? val : 0; + public virtual double Value => double.TryParse(this.Text, out double val) ? val : 0; /// /// Allows conversion of a to the without direct casting. @@ -69,7 +69,7 @@ public static implicit operator NumberInput(RemoteWebElement element) /// /// Thrown if the value is out of the minimum and maximum range of the NumberBox. /// - public void SetValue(double value) + public virtual void SetValue(double value) { double min = this.Minimum; double max = this.Maximum; @@ -96,7 +96,7 @@ public void SetValue(double value) /// /// Increases the number box value. /// - public void Increment() + public virtual void Increment() { this.Element.SendKeys(Keys.ArrowUp); } @@ -104,7 +104,7 @@ public void Increment() /// /// Decreases the number box value. /// - public void Decrement() + public virtual void Decrement() { this.Element.SendKeys(Keys.ArrowDown); } diff --git a/src/Legerity.Web/Elements/Core/Option.cs b/src/Legerity.Web/Elements/Core/Option.cs index c87e7ac5..624e8a54 100644 --- a/src/Legerity.Web/Elements/Core/Option.cs +++ b/src/Legerity.Web/Elements/Core/Option.cs @@ -1,6 +1,7 @@ namespace Legerity.Web.Elements.Core { using Legerity.Web.Elements; + using Legerity.Web.Extensions; using OpenQA.Selenium; using OpenQA.Selenium.Remote; @@ -34,17 +35,17 @@ public Option(RemoteWebElement element) /// /// Gets the value of the option. /// - public string Value => this.Element.GetAttribute("value"); + public virtual string Value => this.GetValue(); /// /// Gets the display value of the option. /// - public string DisplayValue => this.Element.Text; + public virtual string DisplayValue => this.Element.Text; /// /// Gets a value indicating whether the option is selected. /// - public bool IsSelected => this.Element.Selected; + public virtual bool IsSelected => this.Element.Selected; /// /// Allows conversion of a to the without direct casting. @@ -63,9 +64,9 @@ public static implicit operator Option(RemoteWebElement element) /// /// Selects the option. /// - public void Select() + public virtual void Select() { - this.Element.Click(); + 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 25c2116b..764fc4ab 100644 --- a/src/Legerity.Web/Elements/Core/RadioButton.cs +++ b/src/Legerity.Web/Elements/Core/RadioButton.cs @@ -1,5 +1,6 @@ namespace Legerity.Web.Elements.Core { + using Legerity.Web.Extensions; using OpenQA.Selenium; using OpenQA.Selenium.Remote; @@ -33,12 +34,12 @@ public RadioButton(RemoteWebElement element) /// /// Gets a value indicating whether the radio button is selected. /// - public bool IsSelected => this.Element.Selected; + public virtual bool IsSelected => this.Element.Selected; /// /// Gets the name of the group for the radio button. /// - public string Group => this.Element.GetAttribute("name"); + public virtual string Group => this.GetName(); /// /// Allows conversion of a to the without direct casting. diff --git a/src/Legerity.Web/Elements/Core/RangeInput.cs b/src/Legerity.Web/Elements/Core/RangeInput.cs index a9cc635d..014037e8 100644 --- a/src/Legerity.Web/Elements/Core/RangeInput.cs +++ b/src/Legerity.Web/Elements/Core/RangeInput.cs @@ -34,17 +34,17 @@ public RangeInput(RemoteWebElement element) /// /// Gets the minimum value of the range input. /// - public double Minimum => double.Parse(this.Element.GetAttribute("min")); + public virtual double Minimum => double.Parse(this.GetAttribute("min")); /// /// Gets the maximum value of the range input. /// - public double Maximum => double.Parse(this.Element.GetAttribute("max")); + public virtual double Maximum => double.Parse(this.GetAttribute("max")); /// /// Gets the value of the range input. /// - public double Value => double.TryParse(this.Text, out double val) ? val : 0; + public virtual double Value => double.TryParse(this.Text, out double val) ? val : 0; /// /// Allows conversion of a to the without direct casting. @@ -69,7 +69,7 @@ public static implicit operator RangeInput(RemoteWebElement element) /// /// Thrown if the value is out of the minimum and maximum range of the range input. /// - public void SetValue(double value) + public virtual void SetValue(double value) { double min = this.Minimum; double max = this.Maximum; @@ -90,7 +90,7 @@ public void SetValue(double value) $"Value must be less than or equal to the maximum value {max}"); } - this.Element.Click(); + this.Click(); double currentValue = this.Value; while (Math.Abs(currentValue - value) > double.Epsilon) @@ -103,7 +103,7 @@ public void SetValue(double value) /// /// Increases the range input value. /// - public void Increment() + public virtual void Increment() { this.Element.SendKeys(Keys.ArrowUp); } @@ -111,7 +111,7 @@ public void Increment() /// /// Decreases the range input value. /// - public void Decrement() + public virtual void Decrement() { this.Element.SendKeys(Keys.ArrowDown); } diff --git a/src/Legerity.Web/Elements/Core/Select.cs b/src/Legerity.Web/Elements/Core/Select.cs index 0fd2415a..d2d5e4b7 100644 --- a/src/Legerity.Web/Elements/Core/Select.cs +++ b/src/Legerity.Web/Elements/Core/Select.cs @@ -2,7 +2,9 @@ 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; @@ -37,22 +39,23 @@ public Select(RemoteWebElement element) /// /// Gets a value indicating whether multiple items can be selected. /// - public bool IsMultiple => this.GetIsMultiple(); + public virtual bool IsMultiple => this.GetIsMultiple(); /// /// Gets the collection of items associated with the select. /// - public IEnumerable /// The specified column index of data to retrieve. /// A collection of values for each row in the column. - public IEnumerable GetColumnDataByIndex(int idx) + public virtual IEnumerable GetColumnDataByIndex(int idx) { if (idx == -1) { diff --git a/src/Legerity.Web/Elements/Core/TableRow.cs b/src/Legerity.Web/Elements/Core/TableRow.cs index e78a5b64..9f0e84ec 100644 --- a/src/Legerity.Web/Elements/Core/TableRow.cs +++ b/src/Legerity.Web/Elements/Core/TableRow.cs @@ -37,6 +37,6 @@ public TableRow(RemoteWebElement element) /// /// Gets all of the values for each column in the row. /// - public IEnumerable Values => this.GetAllChildElements().Select(x => x.GetInnerHtml()); + public virtual IEnumerable Values => this.GetAllChildElements().Select(x => x.GetInnerHtml()); } } \ No newline at end of file diff --git a/src/Legerity.Web/Elements/Core/TextArea.cs b/src/Legerity.Web/Elements/Core/TextArea.cs index 067ef562..5dae7c1e 100644 --- a/src/Legerity.Web/Elements/Core/TextArea.cs +++ b/src/Legerity.Web/Elements/Core/TextArea.cs @@ -33,12 +33,12 @@ public TextArea(RemoteWebElement element) /// /// Gets the number of visible text lines. /// - public int Rows => int.Parse(this.Element.GetAttribute("rows")); + public virtual int Rows => int.Parse(this.GetAttribute("rows")); /// /// Gets the visible width. /// - public int Cols => int.Parse(this.Element.GetAttribute("cols")); + public virtual int Cols => int.Parse(this.GetAttribute("cols")); /// /// Allows conversion of a to the without direct casting. diff --git a/src/Legerity.Web/Elements/Core/TextInput.cs b/src/Legerity.Web/Elements/Core/TextInput.cs index 67e6683a..bb6666a3 100644 --- a/src/Legerity.Web/Elements/Core/TextInput.cs +++ b/src/Legerity.Web/Elements/Core/TextInput.cs @@ -1,6 +1,7 @@ namespace Legerity.Web.Elements.Core { using Legerity.Web.Elements; + using Legerity.Web.Extensions; using OpenQA.Selenium; using OpenQA.Selenium.Remote; @@ -34,7 +35,7 @@ public TextInput(RemoteWebElement element) /// /// Gets the text value of the text input. /// - public string Text => this.Element.GetAttribute("value"); + public virtual string Text => this.GetValue(); /// /// Allows conversion of a to the without direct casting. @@ -54,7 +55,7 @@ public static implicit operator TextInput(RemoteWebElement element) /// Sets the text of the text box to the specified text. /// /// The text to display. - public void SetText(string text) + public virtual void SetText(string text) { this.ClearText(); this.AppendText(text); @@ -64,18 +65,18 @@ public void SetText(string text) /// Appends the specified text to the text box. /// /// The text to append. - public void AppendText(string text) + public virtual void AppendText(string text) { - this.Element.Click(); + this.Click(); this.Element.SendKeys(text); } /// /// Clears the text from the text box. /// - public void ClearText() + public virtual void ClearText() { - this.Element.Click(); + this.Click(); this.Element.Clear(); } } diff --git a/src/Legerity.Web/Extensions/AttributeExtensions.cs b/src/Legerity.Web/Extensions/AttributeExtensions.cs new file mode 100644 index 00000000..ea9e20ae --- /dev/null +++ b/src/Legerity.Web/Extensions/AttributeExtensions.cs @@ -0,0 +1,83 @@ +namespace Legerity.Web.Extensions +{ + using OpenQA.Selenium; + using OpenQA.Selenium.Remote; + + /// + /// Defines a collection of extensions for retrieving element attributes. + /// + public static class AttributeExtensions + { + /// + /// 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"); + } + + /// + /// 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 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 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 class attribute from the specified element. + /// + /// The to retrieve a class from. + /// The class of the element. + public static string GetClass(this IWebElement element) + { + return element.GetAttribute("class"); + } + + /// + /// Retrieves the class attribute from the specified element. + /// + /// + /// The type of . + /// + /// The to retrieve a class from. + /// The class of the element. + public static string GetClass(this IElementWrapper element) + where TElement : IWebElement + { + return GetClass(element.Element); + } + } +} diff --git a/src/Legerity.Web/Extensions/IWebElementExtensions.cs b/src/Legerity.Web/Extensions/IWebElementExtensions.cs index 33465102..15533f6e 100644 --- a/src/Legerity.Web/Extensions/IWebElementExtensions.cs +++ b/src/Legerity.Web/Extensions/IWebElementExtensions.cs @@ -1,6 +1,7 @@ namespace Legerity.Web.Extensions { using OpenQA.Selenium; + using OpenQA.Selenium.Remote; /// /// Defines a collection of extensions for the class. @@ -17,6 +18,20 @@ public static string GetInnerHtml(this IWebElement element) return element.GetAttribute("innerHTML"); } + /// + /// Retrieves the value attribute from the specified element. + /// + /// + /// The type of . + /// + /// The to retrieve the inner HTML from. + /// The inner HTML of the element. + public static string GetInnerHtml(this IElementWrapper element) + where TElement : IWebElement + { + return GetInnerHtml(element.Element); + } + /// /// Determines whether the specified has the specified class. /// @@ -25,7 +40,22 @@ public static string GetInnerHtml(this IWebElement element) /// True if the element has the class; otherwise, false. public static bool HasClass(this IWebElement element, string className) { - return element.GetAttribute("class").Contains(className); + return element.GetClass().Contains(className); + } + + /// + /// Determines whether the specified has the specified class. + /// + /// + /// The type of . + /// + /// The to check. + /// The name of the class the element should have. + /// True if the element has the class; otherwise, false. + public static bool HasClass(this IElementWrapper element, string className) + where TElement : IWebElement + { + return HasClass(element.Element, className); } } -} +} \ No newline at end of file diff --git a/src/Legerity.Web/WebByExtras.cs b/src/Legerity.Web/WebByExtras.cs new file mode 100644 index 00000000..0eb7db34 --- /dev/null +++ b/src/Legerity.Web/WebByExtras.cs @@ -0,0 +1,46 @@ +namespace Legerity.Web +{ + using OpenQA.Selenium; + + /// + /// Defines a collection of extra locator constraints for . + /// + public static class WebByExtras + { + /// + /// Gets a mechanism to find elements by the HTML li tag. + /// + /// A object the driver can use to find elements. + public static By ListItem() + { + return By.TagName("li"); + } + + /// + /// Gets a mechanism to find elements by the HTML option tag. + /// + /// A object the driver can use to find elements. + public static By Option() + { + return By.TagName("option"); + } + + /// + /// Gets a mechanism to find elements by the HTML th tag. + /// + /// A object the driver can use to find elements. + public static By TableHeaderCell() + { + return By.TagName("th"); + } + + /// + /// Gets a mechanism to find elements by the HTML tr tag. + /// + /// A object the driver can use to find elements. + public static By TableRow() + { + return By.TagName("tr"); + } + } +} diff --git a/src/Legerity.WinUI/InfoBar.cs b/src/Legerity.WinUI/InfoBar.cs index 9333145f..43412058 100644 --- a/src/Legerity.WinUI/InfoBar.cs +++ b/src/Legerity.WinUI/InfoBar.cs @@ -23,32 +23,32 @@ public InfoBar(WindowsElement element) /// /// Gets the title of the info bar. /// - public string Title => this.TitleTextBlock.Text; + public virtual string Title => this.TitleTextBlock.Text; /// /// Gets the message of the info bar. /// - public string Message => this.MessageTextBlock.Text; + public virtual string Message => this.MessageTextBlock.Text; /// /// Gets a value indicating whether the info bar is open. /// - public bool IsOpen => !bool.Parse(this.Element.GetAttribute("IsOffscreen")); + public virtual bool IsOpen => !bool.Parse(this.GetAttribute("IsOffscreen")); /// /// Gets the element associated with the title . /// - public TextBlock TitleTextBlock => this.FindElement(WindowsByExtras.AutomationId("Title")); + public virtual TextBlock TitleTextBlock => this.FindElement(WindowsByExtras.AutomationId("Title")); /// /// Gets the element associated with the message . /// - public TextBlock MessageTextBlock => this.FindElement(WindowsByExtras.AutomationId("Message")); + public virtual TextBlock MessageTextBlock => this.FindElement(WindowsByExtras.AutomationId("Message")); /// /// Gets the element associated with the close . /// - public Button CloseButton => this.FindElement(WindowsByExtras.AutomationId("CloseButton")); + public virtual Button CloseButton => this.FindElement(WindowsByExtras.AutomationId("CloseButton")); /// /// Allows conversion of a to the without direct casting. @@ -81,7 +81,7 @@ public static implicit operator InfoBar(AppiumWebElement element) /// /// Closes the info bar. /// - public void Close() + public virtual void Close() { this.CloseButton.Click(); } diff --git a/src/Legerity.WinUI/MenuBar.cs b/src/Legerity.WinUI/MenuBar.cs index c554a797..ca93c3fa 100644 --- a/src/Legerity.WinUI/MenuBar.cs +++ b/src/Legerity.WinUI/MenuBar.cs @@ -2,6 +2,7 @@ namespace Legerity.Windows.Elements.WinUI { using System; using System.Collections.Generic; + using System.Globalization; using System.Linq; using Legerity.Extensions; using OpenQA.Selenium; @@ -27,7 +28,7 @@ public MenuBar(WindowsElement element) /// /// Gets the UI components associated with the menu items. /// - public IEnumerable MenuItems => + public virtual IEnumerable MenuItems => this.Element.FindElements(By.ClassName("Microsoft.UI.Xaml.Controls.MenuBarItem")) .Select(element => new MenuBarItem(this, element as WindowsElement)); @@ -68,7 +69,7 @@ public static implicit operator MenuBar(AppiumWebElement element) /// /// The clicked . /// - public MenuBarItem ClickOption(string name) + public virtual MenuBarItem ClickOption(string name) { MenuBarItem item = this.MenuItems.FirstOrDefault( element => element.GetName() @@ -76,5 +77,23 @@ public MenuBarItem ClickOption(string name) item.Click(); return item; } + + /// + /// Clicks on a child menu option with the specified partial item name. + /// + /// + /// The partial name of the item to click. + /// + /// + /// The clicked . + /// + public virtual MenuBarItem ClickOptionByPartialName(string name) + { + MenuBarItem item = this.MenuItems.FirstOrDefault( + element => element.GetName() + .Contains(name, CultureInfo.CurrentCulture, CompareOptions.IgnoreCase)); + item.Click(); + return item; + } } } \ No newline at end of file diff --git a/src/Legerity.WinUI/MenuBarItem.cs b/src/Legerity.WinUI/MenuBarItem.cs index deb78b86..cd900a08 100644 --- a/src/Legerity.WinUI/MenuBarItem.cs +++ b/src/Legerity.WinUI/MenuBarItem.cs @@ -2,6 +2,7 @@ namespace Legerity.Windows.Elements.WinUI { using System; using System.Collections.Generic; + using System.Globalization; using System.Linq; using Legerity.Extensions; using Legerity.Windows.Elements.Core; @@ -47,7 +48,7 @@ public MenuBarItem( } /// Gets the original parent reference object. - public MenuBar ParentMenuBar => + public virtual MenuBar ParentMenuBar => this.parentMenuBarReference != null && this.parentMenuBarReference.IsAlive ? this.parentMenuBarReference.Target as MenuBar : null; @@ -55,35 +56,45 @@ public MenuBarItem( /// /// Gets the UI components associated with the child menu items. /// - public IEnumerable ChildMenuItems => this.GetChildMenuItems(); + public virtual IEnumerable ChildMenuItems => this.GetChildMenuItems(); /// /// Gets the UI components associated with the child menu sub-items. /// - public IEnumerable ChildMenuSubItems => this.GetChildMenuSubItems(); + public virtual IEnumerable ChildMenuSubItems => this.GetChildMenuSubItems(); /// - /// Clicks the item. + /// Clicks on a child menu option with the specified item name. /// - public void Click() + /// + /// The name of the item to click. + /// + /// + /// The clicked . + /// + public virtual MenuFlyoutItem ClickChildOption(string name) { - this.Element.Click(); + MenuFlyoutItem item = this.ChildMenuItems.FirstOrDefault( + element => element.GetName() + .Equals(name, StringComparison.CurrentCultureIgnoreCase)); + item.Click(); + return item; } /// - /// Clicks on a child menu option with the specified item name. + /// Clicks on a child menu option with the specified partial item name. /// /// - /// The name of the item to click. + /// The partial name of the item to click. /// /// /// The clicked . /// - public MenuFlyoutItem ClickChildOption(string name) + public virtual MenuFlyoutItem ClickChildOptionByPartialName(string name) { MenuFlyoutItem item = this.ChildMenuItems.FirstOrDefault( element => element.GetName() - .Equals(name, StringComparison.CurrentCultureIgnoreCase)); + .Contains(name, CultureInfo.CurrentCulture, CompareOptions.IgnoreCase)); item.Click(); return item; } @@ -93,7 +104,7 @@ public MenuFlyoutItem ClickChildOption(string name) /// /// The name of the sub-item to click. /// The clicked . - public MenuFlyoutSubItem ClickChildSubOption(string name) + public virtual MenuFlyoutSubItem ClickChildSubOption(string name) { MenuFlyoutSubItem item = this.ChildMenuSubItems.FirstOrDefault( element => element.GetName() @@ -102,6 +113,20 @@ public MenuFlyoutSubItem ClickChildSubOption(string name) return item; } + /// + /// Clicks on a child menu sub option with the specified partial item name. + /// + /// The partial name of the sub-item to click. + /// The clicked . + public virtual MenuFlyoutSubItem ClickChildSubOptionByPartialName(string name) + { + MenuFlyoutSubItem item = this.ChildMenuSubItems.FirstOrDefault( + element => element.GetName() + .Contains(name, CultureInfo.CurrentCulture, CompareOptions.IgnoreCase)); + item.Click(); + return item; + } + private IEnumerable GetChildMenuItems() { return this.Driver.FindElement(By.ClassName("MenuFlyout")) diff --git a/src/Legerity.WinUI/NavigationView.cs b/src/Legerity.WinUI/NavigationView.cs index aad17c1f..9903c2e1 100644 --- a/src/Legerity.WinUI/NavigationView.cs +++ b/src/Legerity.WinUI/NavigationView.cs @@ -2,6 +2,7 @@ namespace Legerity.Windows.Elements.WinUI { using System; using System.Collections.Generic; + using System.Globalization; using System.Linq; using Legerity.Extensions; using Legerity.Windows.Elements.Core; @@ -28,39 +29,43 @@ public NavigationView(WindowsElement element) /// /// Gets the UI component associated with displaying the menu items. /// - public AppiumWebElement MenuItemsView => this.Element.FindElement(WindowsByExtras.AutomationId("MenuItemsHost")); + public virtual AppiumWebElement MenuItemsView => + this.Element.FindElement(WindowsByExtras.AutomationId("MenuItemsHost")); /// /// Gets the UI components associated with the menu items. /// - public IEnumerable MenuItems => + public virtual IEnumerable MenuItems => this.MenuItemsView.FindElements(By.ClassName("Microsoft.UI.Xaml.Controls.NavigationViewItem")) .Select(element => new NavigationViewItem(this, element as WindowsElement)); /// /// Gets the UI component associated with the settings menu item. /// - public AppiumWebElement SettingsMenuItem => this.Element.FindElement(WindowsByExtras.AutomationId("SettingsItem")); + public virtual AppiumWebElement SettingsMenuItem => + this.Element.FindElement(WindowsByExtras.AutomationId("SettingsItem")); /// /// Gets the UI component associated with the navigation pane toggle button. /// - public Button ToggleNavigationPaneButton => this.Element.FindElement(WindowsByExtras.AutomationId("TogglePaneButton")); + public virtual Button ToggleNavigationPaneButton => + this.Element.FindElement(WindowsByExtras.AutomationId("TogglePaneButton")); /// /// Gets the UI component associated with the navigation back button. /// - public Button BackButton => this.Element.FindElement(WindowsByExtras.AutomationId("NavigationViewBackButton")); + public virtual Button BackButton => + this.Element.FindElement(WindowsByExtras.AutomationId("NavigationViewBackButton")); /// /// Gets a value indicating whether the pane is currently open. /// - public bool IsPaneOpen => this.VerifyPaneOpen(this.ExpectedCompactPaneWidth); + public virtual bool IsPaneOpen => this.VerifyPaneOpen(this.ExpectedCompactPaneWidth); /// /// Gets or sets the expected compact pane width used to determine the pane open state. /// - public int ExpectedCompactPaneWidth { get; set; } = 72; + public virtual int ExpectedCompactPaneWidth { get; set; } = 72; /// /// Allows conversion of a to the without direct casting. @@ -93,7 +98,7 @@ public static implicit operator NavigationView(AppiumWebElement element) /// /// Opens the navigation pane. /// - public void OpenNavigationPane() + public virtual void OpenNavigationPane() { if (this.IsPaneOpen) { @@ -106,7 +111,7 @@ public void OpenNavigationPane() /// /// Collapses the navigation pane. /// - public void CloseNavigationPane() + public virtual void CloseNavigationPane() { if (!this.IsPaneOpen) { @@ -119,7 +124,7 @@ public void CloseNavigationPane() /// /// Navigates the view back. /// - public void GoBack() + public virtual void GoBack() { if (this.BackButton.IsEnabled) { @@ -136,7 +141,7 @@ public void GoBack() /// /// The clicked . /// - public NavigationViewItem ClickMenuOption(string name) + public virtual NavigationViewItem ClickMenuOption(string name) { NavigationViewItem item = this.MenuItems.FirstOrDefault( element => element.GetName().Equals(name, StringComparison.CurrentCultureIgnoreCase)); @@ -144,10 +149,27 @@ public NavigationViewItem ClickMenuOption(string name) return item; } + /// + /// Clicks on a menu option in the navigation view with the specified partial item name. + /// + /// + /// The partial name of the item to click. + /// + /// + /// The clicked . + /// + public virtual NavigationViewItem ClickMenuOptionByPartialName(string name) + { + NavigationViewItem item = this.MenuItems.FirstOrDefault( + element => element.GetName().Contains(name, CultureInfo.CurrentCulture, CompareOptions.IgnoreCase)); + item.Click(); + return item; + } + /// /// Opens the settings option. /// - public void OpenSettings() + public virtual void OpenSettings() { this.SettingsMenuItem.Click(); } @@ -157,7 +179,7 @@ public void OpenSettings() /// /// The expected compact pane width when closed. /// True if the pane is open; otherwise, false. - public bool VerifyPaneOpen(int expectedCompactPaneWidth) + public virtual bool VerifyPaneOpen(int expectedCompactPaneWidth) { AppiumWebElement pane = this.Element.FindElement(WindowsByExtras.AutomationId("PaneRoot")); int paneWidth = pane.Rect.Width; diff --git a/src/Legerity.WinUI/NavigationViewItem.cs b/src/Legerity.WinUI/NavigationViewItem.cs index 38b66d64..bb3afb09 100644 --- a/src/Legerity.WinUI/NavigationViewItem.cs +++ b/src/Legerity.WinUI/NavigationViewItem.cs @@ -2,6 +2,7 @@ namespace Legerity.Windows.Elements.WinUI { using System; using System.Collections.Generic; + using System.Globalization; using System.Linq; using Legerity.Extensions; using OpenQA.Selenium; @@ -101,30 +102,40 @@ public NavigationViewItem( /// /// Gets the UI components associated with the child menu items. /// - public IEnumerable ChildMenuItems => this.GetChildMenuItems(); + public virtual IEnumerable ChildMenuItems => this.GetChildMenuItems(); /// - /// Clicks the item. + /// Clicks on a child menu option with the specified item name. /// - public void Click() + /// + /// The name of the item to click. + /// + /// + /// The clicked . + /// + public virtual NavigationViewItem ClickChildOption(string name) { - this.Element.Click(); + NavigationViewItem item = this.ChildMenuItems.FirstOrDefault( + element => element.GetName() + .Equals(name, StringComparison.CurrentCultureIgnoreCase)); + item.Click(); + return item; } /// - /// Clicks on a child menu option with the specified item name. + /// Clicks on a child menu option with the specified partial item name. /// /// - /// The name of the item to click. + /// The partial name of the item to click. /// /// /// The clicked . /// - public NavigationViewItem ClickChildOption(string name) + public virtual NavigationViewItem ClickChildOptionByPartialName(string name) { NavigationViewItem item = this.ChildMenuItems.FirstOrDefault( element => element.GetName() - .Equals(name, StringComparison.CurrentCultureIgnoreCase)); + .Contains(name, CultureInfo.CurrentCulture, CompareOptions.IgnoreCase)); item.Click(); return item; } diff --git a/src/Legerity.WinUI/NumberBox.cs b/src/Legerity.WinUI/NumberBox.cs index 52ce5de5..e175a9a6 100644 --- a/src/Legerity.WinUI/NumberBox.cs +++ b/src/Legerity.WinUI/NumberBox.cs @@ -1,8 +1,8 @@ namespace Legerity.Windows.Elements.WinUI { using System; - using Legerity.Windows.Elements.Core; + using Legerity.Windows.Extensions; using OpenQA.Selenium; using OpenQA.Selenium.Appium; using OpenQA.Selenium.Appium.Windows; @@ -26,42 +26,43 @@ public NumberBox(WindowsElement element) /// /// Gets the minimum value of the NumberBox. /// - public double Minimum => double.Parse(this.Element.GetAttribute("RangeValue.Minimum")); + public virtual double Minimum => this.GetRangeMinimum(); /// /// Gets the maximum value of the NumberBox. /// - public double Maximum => double.Parse(this.Element.GetAttribute("RangeValue.Maximum")); + public virtual double Maximum => this.GetRangeMaximum(); /// /// Gets the small change (step) value of the NumberBox. /// - public double SmallChange => double.Parse(this.Element.GetAttribute("RangeValue.SmallChange")); + public virtual double SmallChange => this.GetRangeSmallChange(); /// /// Gets the value of the NumberBox. /// - public double Value => double.Parse(this.Element.GetAttribute("RangeValue.Value")); + public virtual double Value => this.GetRangeValue(); /// /// Gets a value indicating whether the control is in a readonly state. /// - public bool IsReadonly => bool.Parse(this.Element.GetAttribute("RangeValue.IsReadOnly")); + public virtual bool IsReadonly => this.IsRangeReadonly(); /// /// Gets the element associated with the inline up button. /// - public Button InlineUpButton => this.Element.FindElement(WindowsByExtras.AutomationId("UpSpinButton")); + public virtual Button InlineUpButton => this.Element.FindElement(WindowsByExtras.AutomationId("UpSpinButton")); /// /// Gets the element associated with the inline down button. /// - public Button InlineDownButton => this.Element.FindElement(WindowsByExtras.AutomationId("DownSpinButton")); + public virtual Button InlineDownButton => + this.Element.FindElement(WindowsByExtras.AutomationId("DownSpinButton")); /// /// Gets the element associated with the input text box. /// - public TextBox InputBox => this.Element.FindElement(WindowsByExtras.AutomationId("InputBox")); + public virtual TextBox InputBox => this.Element.FindElement(WindowsByExtras.AutomationId("InputBox")); /// /// Allows conversion of a to the without direct casting. @@ -100,7 +101,7 @@ public static implicit operator NumberBox(AppiumWebElement element) /// /// Thrown if the value is out of the minimum and maximum range of the NumberBox. /// - public void SetValue(double value) + public virtual void SetValue(double value) { double min = this.Minimum; double max = this.Maximum; @@ -128,7 +129,7 @@ public void SetValue(double value) /// /// Increases the number box value by the value. /// - public void Increment() + public virtual void Increment() { this.Element.SendKeys(Keys.ArrowUp); } @@ -136,7 +137,7 @@ public void Increment() /// /// Decreases the number box value by the value. /// - public void Decrement() + public virtual void Decrement() { this.Element.SendKeys(Keys.ArrowDown); } diff --git a/src/Legerity.WinUI/RatingControl.cs b/src/Legerity.WinUI/RatingControl.cs index a3980291..c02501c9 100644 --- a/src/Legerity.WinUI/RatingControl.cs +++ b/src/Legerity.WinUI/RatingControl.cs @@ -1,6 +1,7 @@ namespace Legerity.Windows.Elements.WinUI { using System; + using Legerity.Windows.Extensions; using OpenQA.Selenium; using OpenQA.Selenium.Appium; using OpenQA.Selenium.Appium.Windows; @@ -24,16 +25,22 @@ public RatingControl(WindowsElement element) /// /// Gets the value of the rating out of 5. /// - public double Value => double.Parse(this.Element.GetAttribute("RangeValue.Value")); + public virtual double Value => this.GetRangeValue(); /// /// Gets a value indicating whether the control is in a readonly state. /// - public bool IsReadonly => bool.Parse(this.Element.GetAttribute("RangeValue.IsReadOnly")); + public virtual bool IsReadonly => this.IsRangeReadonly(); - private double Minimum => double.Parse(this.Element.GetAttribute("RangeValue.Minimum")); + /// + /// Gets the minimum rating value. + /// + public virtual double Minimum => this.GetRangeMinimum(); - private double Maximum => double.Parse(this.Element.GetAttribute("RangeValue.Maximum")); + /// + /// Gets the maximum rating value. + /// + public virtual double Maximum => this.GetRangeMaximum(); /// /// Allows conversion of a to the without direct casting. @@ -72,22 +79,28 @@ public static implicit operator RatingControl(AppiumWebElement element) /// /// Thrown if the value is out of the minimum and maximum range of the slider. /// - public void SetValue(double value) + public virtual void SetValue(double value) { 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}"); + 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.Element.Click(); + this.Click(); double currentValue = this.Value; while (Math.Abs(currentValue - value) > double.Epsilon) diff --git a/src/Legerity.WinUI/TabView.cs b/src/Legerity.WinUI/TabView.cs index 15c60227..cfb32e4a 100644 --- a/src/Legerity.WinUI/TabView.cs +++ b/src/Legerity.WinUI/TabView.cs @@ -3,10 +3,8 @@ namespace Legerity.Windows.Elements.WinUI 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; @@ -32,17 +30,17 @@ public TabView(WindowsElement element) /// /// Gets the element associated with the add tab button. /// - public Button AddTabButton => this.Element.FindElement(WindowsByExtras.AutomationId("AddButton")); + public virtual Button AddTabButton => this.Element.FindElement(WindowsByExtras.AutomationId("AddButton")); /// /// Gets the collection of items associated with the pivot. /// - public ReadOnlyCollection Tabs => this.TabsListView.Items; + public virtual ReadOnlyCollection Tabs => this.TabsListView.Items; /// /// Gets the element associated with the currently selected item. /// - public AppiumWebElement SelectedItem => this.TabsListView.SelectedItem; + public virtual AppiumWebElement SelectedItem => this.TabsListView.SelectedItem; private ListView TabsListView => this.Element.FindElement(this.tabListViewLocator); @@ -77,7 +75,7 @@ public static implicit operator TabView(AppiumWebElement element) /// /// Adds a new tab to the tab view. /// - public void CreateTab() + public virtual void CreateTab() { this.VerifyElementShown(this.tabListViewLocator, TimeSpan.FromSeconds(2)); this.AddTabButton.Click(); @@ -89,23 +87,48 @@ public void CreateTab() /// /// The name of the item to click. /// - public void SelectTab(string name) + public virtual void SelectTab(string name) { this.VerifyElementShown(this.tabListViewLocator, TimeSpan.FromSeconds(2)); AppiumWebElement item = this.Tabs.FirstOrDefault(element => element.VerifyNameOrAutomationIdEquals(name)); item.Click(); } + /// + /// Clicks on a tab in the view with the specified partial item name. + /// + /// + /// The partial name of the item to click. + /// + public virtual void SelectTabByPartialName(string name) + { + this.VerifyElementShown(this.tabListViewLocator, TimeSpan.FromSeconds(2)); + AppiumWebElement item = this.Tabs.FirstOrDefault(element => element.VerifyNameOrAutomationIdContains(name)); + item.Click(); + } + /// /// Closes a tab in the view with the specified item name. /// /// The name of the item to close. - public void CloseTab(string name) + public virtual void CloseTab(string name) { this.VerifyElementShown(this.tabListViewLocator, TimeSpan.FromSeconds(2)); AppiumWebElement item = this.Tabs.FirstOrDefault(element => element.VerifyNameOrAutomationIdEquals(name)); Button closeButton = item.FindElement(WindowsByExtras.AutomationId("CloseButton")); closeButton.Click(); } + + /// + /// Closes a tab in the view with the specified partial item name. + /// + /// The partial name of the item to close. + public virtual void CloseTabByPartialName(string name) + { + this.VerifyElementShown(this.tabListViewLocator, TimeSpan.FromSeconds(2)); + AppiumWebElement item = this.Tabs.FirstOrDefault(element => element.VerifyNameOrAutomationIdContains(name)); + Button closeButton = item.FindElement(WindowsByExtras.AutomationId("CloseButton")); + closeButton.Click(); + } } } \ No newline at end of file diff --git a/src/Legerity.Windows/Elements/Core/AppBarToggleButton.cs b/src/Legerity.Windows/Elements/Core/AppBarToggleButton.cs index dbb332a1..40492bf8 100644 --- a/src/Legerity.Windows/Elements/Core/AppBarToggleButton.cs +++ b/src/Legerity.Windows/Elements/Core/AppBarToggleButton.cs @@ -1,5 +1,6 @@ namespace Legerity.Windows.Elements.Core { + using Legerity.Windows.Extensions; using OpenQA.Selenium.Appium; using OpenQA.Selenium.Appium.Windows; @@ -8,8 +9,6 @@ namespace Legerity.Windows.Elements.Core /// public class AppBarToggleButton : AppBarButton { - private const string ToggleOnValue = "1"; - /// /// Initializes a new instance of the class. /// @@ -24,7 +23,7 @@ public AppBarToggleButton(WindowsElement element) /// /// Gets a value indicating whether the toggle button is in the on position. /// - public bool IsOn => this.Element.GetAttribute("Toggle.ToggleState") == ToggleOnValue; + public virtual bool IsOn => this.GetToggleState() == ToggleState.Checked; /// /// Allows conversion of a to the without direct casting. @@ -57,7 +56,7 @@ public static implicit operator AppBarToggleButton(AppiumWebElement element) /// /// Toggles the button on. /// - public void ToggleOn() + public virtual void ToggleOn() { if (this.IsOn) { @@ -70,7 +69,7 @@ public void ToggleOn() /// /// Toggles the button off. /// - public void ToggleOff() + public virtual void ToggleOff() { if (!this.IsOn) { diff --git a/src/Legerity.Windows/Elements/Core/AutoSuggestBox.cs b/src/Legerity.Windows/Elements/Core/AutoSuggestBox.cs index 12421360..bbb8ef31 100644 --- a/src/Legerity.Windows/Elements/Core/AutoSuggestBox.cs +++ b/src/Legerity.Windows/Elements/Core/AutoSuggestBox.cs @@ -26,22 +26,22 @@ public AutoSuggestBox(WindowsElement element) /// /// Gets the element associated with the suggestions popup. /// - public AppiumWebElement SuggestionsPopup => this.Element.FindElement(this.suggestionsPopupLocator); + public virtual AppiumWebElement SuggestionsPopup => this.Element.FindElement(this.suggestionsPopupLocator); /// /// Gets the element associated with the suggestion list when the is shown. /// - public ListView SuggestionList => this.SuggestionsPopup.FindElement(WindowsByExtras.AutomationId("SuggestionsList")); + public virtual ListView SuggestionList => this.SuggestionsPopup.FindElement(WindowsByExtras.AutomationId("SuggestionsList")); /// /// Gets the element associated with the text box. /// - public TextBox TextBox => this.Element.FindElement(WindowsByExtras.AutomationId("TextBox")); + public virtual TextBox TextBox => this.Element.FindElement(WindowsByExtras.AutomationId("TextBox")); /// /// Gets the value of the auto-suggest box. /// - public string Text => this.TextBox.Text; + public virtual string Text => this.TextBox.Text; /// /// Allows conversion of a to the without direct casting. @@ -75,7 +75,7 @@ public static implicit operator AutoSuggestBox(AppiumWebElement element) /// Selects a suggestion from the auto-suggest box. /// /// The suggestion to select. - public void SelectSuggestion(string suggestion) + public virtual void SelectSuggestion(string suggestion) { this.SelectSuggestion(suggestion, suggestion); } @@ -85,7 +85,7 @@ public void SelectSuggestion(string suggestion) /// /// The initial value to set. /// The suggestion to select. - public void SelectSuggestion(string value, string suggestion) + public virtual void SelectSuggestion(string value, string suggestion) { this.SetText(value); @@ -94,11 +94,25 @@ public void SelectSuggestion(string value, string suggestion) this.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.suggestionsPopupLocator, TimeSpan.FromSeconds(2)); + + this.SuggestionList.ClickItemByPartialName(partialSuggestion); + } + /// /// Sets the value of the auto-suggest box. /// /// The value to set. - public void SetText(string value) + public virtual void SetText(string value) { this.TextBox.SetText(value); } diff --git a/src/Legerity.Windows/Elements/Core/Button.cs b/src/Legerity.Windows/Elements/Core/Button.cs index e3158027..198fa83a 100644 --- a/src/Legerity.Windows/Elements/Core/Button.cs +++ b/src/Legerity.Windows/Elements/Core/Button.cs @@ -46,13 +46,5 @@ public static implicit operator Button(AppiumWebElement element) { return new Button(element as WindowsElement); } - - /// - /// Clicks the button. - /// - public void Click() - { - this.Element.Click(); - } } } \ No newline at end of file diff --git a/src/Legerity.Windows/Elements/Core/CalendarDatePicker.cs b/src/Legerity.Windows/Elements/Core/CalendarDatePicker.cs index f002c724..61249d7c 100644 --- a/src/Legerity.Windows/Elements/Core/CalendarDatePicker.cs +++ b/src/Legerity.Windows/Elements/Core/CalendarDatePicker.cs @@ -1,6 +1,7 @@ namespace Legerity.Windows.Elements.Core { using System; + using Legerity.Windows.Extensions; using OpenQA.Selenium; using OpenQA.Selenium.Appium; using OpenQA.Selenium.Appium.Windows; @@ -26,13 +27,13 @@ public CalendarDatePicker(WindowsElement element) /// /// Gets the element associated with the calendar flyout. /// - public CalendarView CalendarViewFlyout => + public virtual CalendarView CalendarViewFlyout => this.Driver.FindElement(this.calendarPopupLocator).FindElement(WindowsByExtras.AutomationId("CalendarView")); /// /// Gets the value of the calendar date picker. /// - public string Value => this.Element.GetAttribute("Value.Value"); + public virtual string Value => this.GetValue(); /// /// Allows conversion of a to the without direct casting. @@ -66,9 +67,9 @@ public static implicit operator CalendarDatePicker(AppiumWebElement element) /// Sets the selected date of the calendar view. /// /// The date to set to. - public void SetDate(DateTime date) + public virtual void SetDate(DateTime date) { - this.Element.Click(); + this.Click(); this.VerifyDriverElementShown(this.calendarPopupLocator, TimeSpan.FromSeconds(2)); diff --git a/src/Legerity.Windows/Elements/Core/CalendarView.cs b/src/Legerity.Windows/Elements/Core/CalendarView.cs index b4f72e05..6ece98bd 100644 --- a/src/Legerity.Windows/Elements/Core/CalendarView.cs +++ b/src/Legerity.Windows/Elements/Core/CalendarView.cs @@ -6,6 +6,7 @@ namespace Legerity.Windows.Elements.Core using System.Linq; using System.Threading; using Legerity.Extensions; + using Legerity.Windows.Extensions; using OpenQA.Selenium; using OpenQA.Selenium.Appium; using OpenQA.Selenium.Appium.Windows; @@ -45,27 +46,27 @@ public CalendarView(WindowsElement element) /// /// Gets the element associated with the header button (change month, year). /// - public Button HeaderButton => this.Element.FindElement(WindowsByExtras.AutomationId("HeaderButton")); + public virtual Button HeaderButton => this.Element.FindElement(WindowsByExtras.AutomationId("HeaderButton")); /// /// Gets the element associated with the next month button. /// - public Button NextMonthButton => this.Element.FindElement(WindowsByExtras.AutomationId("NextButton")); + public virtual Button NextMonthButton => this.Element.FindElement(WindowsByExtras.AutomationId("NextButton")); /// /// Gets the element associated with the previous month button. /// - public Button PreviousMonthButton => this.Element.FindElement(WindowsByExtras.AutomationId("PreviousButton")); + public virtual Button PreviousMonthButton => this.Element.FindElement(WindowsByExtras.AutomationId("PreviousButton")); /// /// Gets the collection of days associated with the current month in the calendar view. /// - public ReadOnlyCollection Days => this.Element.FindElements(By.ClassName("CalendarViewDayItem")); + public virtual ReadOnlyCollection Days => this.Element.FindElements(By.ClassName("CalendarViewDayItem")); /// /// Gets the value of the calendar view. /// - public string Value => this.Element.GetAttribute("Value.Value"); + public virtual string Value => this.GetValue(); /// /// Allows conversion of a to the without direct casting. diff --git a/src/Legerity.Windows/Elements/Core/CheckBox.cs b/src/Legerity.Windows/Elements/Core/CheckBox.cs index 442f8120..672d61f4 100644 --- a/src/Legerity.Windows/Elements/Core/CheckBox.cs +++ b/src/Legerity.Windows/Elements/Core/CheckBox.cs @@ -1,5 +1,6 @@ namespace Legerity.Windows.Elements.Core { + using Legerity.Windows.Extensions; using OpenQA.Selenium.Appium; using OpenQA.Selenium.Appium.Windows; @@ -8,10 +9,6 @@ namespace Legerity.Windows.Elements.Core /// public class CheckBox : WindowsElementWrapper { - private const string CheckedValue = "1"; - - private const string IndeterminateValue = "2"; - /// /// Initializes a new instance of the class. /// @@ -26,12 +23,12 @@ public CheckBox(WindowsElement element) /// /// Gets a value indicating whether the check box is in the checked state. /// - public bool IsChecked => this.Element.GetAttribute("Toggle.ToggleState") == CheckedValue; + public virtual bool IsChecked => this.GetToggleState() == ToggleState.Checked; /// /// Gets a value indicating whether the check box is in the indeterminate state. /// - public bool IsIndeterminate => this.Element.GetAttribute("Toggle.ToggleState") == IndeterminateValue; + public virtual bool IsIndeterminate => this.GetToggleState() == ToggleState.Indeterminate; /// /// Allows conversion of a to the without direct casting. @@ -64,27 +61,27 @@ public static implicit operator CheckBox(AppiumWebElement element) /// /// Checks the check box on. /// - public void CheckOn() + public virtual void CheckOn() { if (this.IsChecked) { return; } - this.Element.Click(); + this.Click(); } /// /// Checks the check box off. /// - public void CheckOff() + public virtual void CheckOff() { if (!this.IsChecked) { return; } - this.Element.Click(); + this.Click(); } } } \ No newline at end of file diff --git a/src/Legerity.Windows/Elements/Core/ComboBox.cs b/src/Legerity.Windows/Elements/Core/ComboBox.cs index 3f8dd02a..88a8f3da 100644 --- a/src/Legerity.Windows/Elements/Core/ComboBox.cs +++ b/src/Legerity.Windows/Elements/Core/ComboBox.cs @@ -1,7 +1,9 @@ namespace Legerity.Windows.Elements.Core { using System; + using System.Collections.Generic; using System.Collections.ObjectModel; + using System.Globalization; using System.Linq; using Legerity.Extensions; using OpenQA.Selenium; @@ -29,7 +31,7 @@ public ComboBox(WindowsElement element) /// /// Gets the currently selected item. /// - public string SelectedItem => this.GetSelectedItem(); + public virtual string SelectedItem => this.GetSelectedItem(); /// /// Allows conversion of a to the without direct casting. @@ -65,16 +67,28 @@ public static implicit operator ComboBox(AppiumWebElement element) /// /// The name of the item to select. /// - public void SelectItem(string name) + public virtual void SelectItem(string name) { - this.Element.Click(); + IEnumerable listElements = this.GetItemsToSelect(); - this.VerifyElementsShown(this.comboBoxItemLocator, TimeSpan.FromSeconds(2)); + AppiumWebElement item = listElements.FirstOrDefault( + element => element.GetName().Equals(name, StringComparison.CurrentCultureIgnoreCase)); - ReadOnlyCollection listElements = this.Element.FindElements(this.comboBoxItemLocator); + item.Click(); + } + + /// + /// Selects an item in the combo-box with the specified partial item name. + /// + /// + /// The partial name of the item to select. + /// + public virtual void SelectItemByPartialName(string name) + { + IEnumerable listElements = this.GetItemsToSelect(); AppiumWebElement item = listElements.FirstOrDefault( - element => element.GetName().Equals(name, StringComparison.CurrentCultureIgnoreCase)); + element => element.GetName().Contains(name, CultureInfo.CurrentCulture, CompareOptions.IgnoreCase)); item.Click(); } @@ -84,5 +98,13 @@ private string GetSelectedItem() ReadOnlyCollection listElements = this.Element.FindElements(this.comboBoxItemLocator); return listElements.Count == 1 ? listElements.FirstOrDefault().GetName() : null; } + + private IEnumerable GetItemsToSelect() + { + this.Click(); + this.VerifyElementsShown(this.comboBoxItemLocator, TimeSpan.FromSeconds(2)); + ReadOnlyCollection listElements = this.Element.FindElements(this.comboBoxItemLocator); + return listElements; + } } } \ No newline at end of file diff --git a/src/Legerity.Windows/Elements/Core/CommandBar.cs b/src/Legerity.Windows/Elements/Core/CommandBar.cs index 99de1a33..f99db96c 100644 --- a/src/Legerity.Windows/Elements/Core/CommandBar.cs +++ b/src/Legerity.Windows/Elements/Core/CommandBar.cs @@ -3,9 +3,7 @@ namespace Legerity.Windows.Elements.Core using System; using System.Collections.Generic; using System.Linq; - using Legerity.Windows.Extensions; - using OpenQA.Selenium; using OpenQA.Selenium.Appium; using OpenQA.Selenium.Appium.Windows; @@ -35,17 +33,22 @@ public CommandBar(WindowsElement element) /// /// Gets the collection of primary buttons. /// - public IEnumerable PrimaryButtons => + public virtual IEnumerable PrimaryButtons => this.Element.FindElements(this.appBarButtonLocator) .Select(element => element); + /// + /// Gets the for opening the secondary button menu. + /// + public virtual AppBarButton SecondaryMenuButton => this.Element.FindElement(this.moreButtonLocator); + /// /// Gets the collection of secondary buttons. /// /// Note, this property will only return a result when the secondary buttons are shown in the flyout. /// /// - public IEnumerable SecondaryButtons => + public virtual IEnumerable SecondaryButtons => this.Driver.FindElement(this.overflowPopupLocator).FindElements(this.appBarButtonLocator) .Select(element => element); @@ -78,12 +81,12 @@ public static implicit operator CommandBar(AppiumWebElement element) } /// - /// Clicks a primary button in the command bar with the specified button name. + /// Clicks a primary button in the command bar with the specified button name or Automation ID. /// /// /// The name of the button to click. /// - public void ClickPrimaryButton(string name) + public virtual void ClickPrimaryButton(string name) { AppBarButton item = this.PrimaryButtons.FirstOrDefault( element => element.Element.VerifyNameOrAutomationIdEquals(name)); @@ -91,25 +94,60 @@ public void ClickPrimaryButton(string name) item.Click(); } + /// + /// Clicks a primary button in the command bar with the specified partial button name or Automation ID. + /// + /// + /// The partial name of the button to click. + /// + public virtual void ClickPrimaryButtonByPartialName(string partialName) + { + AppBarButton item = this.PrimaryButtons.FirstOrDefault( + element => element.Element.VerifyNameOrAutomationIdContains(partialName)); + + item.Click(); + } + /// /// Clicks a secondary button in the command bar with the specified button name. /// /// /// The name of the button to click. /// - public void ClickSecondaryButton(string name) + public virtual void ClickSecondaryButton(string name) { - this.VerifyElementShown(this.moreButtonLocator, TimeSpan.FromSeconds(2)); + this.OpenSecondaryButtonMenu(); - AppBarButton secondaryOverflowButton = this.Element.FindElement(this.moreButtonLocator); - secondaryOverflowButton.Click(); + AppBarButton secondaryButton = this.SecondaryButtons.FirstOrDefault( + button => button.Element.VerifyNameOrAutomationIdEquals(name)); - this.VerifyDriverElementShown(this.overflowPopupLocator, TimeSpan.FromSeconds(2)); + secondaryButton.Click(); + } + + /// + /// Clicks a secondary button in the command bar with the specified partial button name. + /// + /// + /// The partial name of the button to click. + /// + public virtual void ClickSecondaryButtonByPartialName(string partialName) + { + this.OpenSecondaryButtonMenu(); AppBarButton secondaryButton = this.SecondaryButtons.FirstOrDefault( - button => button.Element.VerifyNameOrAutomationIdEquals(name)); + button => button.Element.VerifyNameOrAutomationIdContains(partialName)); secondaryButton.Click(); } + + /// + /// Opens the menu associated with the secondary button options. + /// + public virtual void OpenSecondaryButtonMenu() + { + this.VerifyElementShown(this.moreButtonLocator, TimeSpan.FromSeconds(2)); + this.SecondaryMenuButton.Click(); + this.VerifyDriverElementShown(this.overflowPopupLocator, TimeSpan.FromSeconds(2)); + } } } \ No newline at end of file diff --git a/src/Legerity.Windows/Elements/Core/DatePicker.cs b/src/Legerity.Windows/Elements/Core/DatePicker.cs index d6453b62..f0b6d1ff 100644 --- a/src/Legerity.Windows/Elements/Core/DatePicker.cs +++ b/src/Legerity.Windows/Elements/Core/DatePicker.cs @@ -52,10 +52,10 @@ public static implicit operator DatePicker(AppiumWebElement element) /// Sets the date to the specified date. /// /// The date to set. - public void SetDate(DateTime date) + public virtual void SetDate(DateTime date) { // Taps the time picker to show the popup. - this.Element.Click(); + this.Click(); // Finds the popup and changes the time. WindowsElement popup = this.Driver.FindElement(WindowsByExtras.AutomationId("DatePickerFlyoutPresenter")); diff --git a/src/Legerity.Windows/Elements/Core/FlipView.cs b/src/Legerity.Windows/Elements/Core/FlipView.cs index 21d59ecc..9fddfaa2 100644 --- a/src/Legerity.Windows/Elements/Core/FlipView.cs +++ b/src/Legerity.Windows/Elements/Core/FlipView.cs @@ -5,6 +5,7 @@ namespace Legerity.Windows.Elements.Core using System.Globalization; using System.Linq; using Legerity.Extensions; + using Legerity.Windows.Extensions; using OpenQA.Selenium; using OpenQA.Selenium.Appium; using OpenQA.Selenium.Appium.Windows; @@ -28,26 +29,22 @@ public FlipView(WindowsElement element) /// /// Gets the collection of items associated with the flip view. /// - public ReadOnlyCollection Items => this.Element.FindElements(By.ClassName("FlipViewItem")); + public virtual ReadOnlyCollection Items => this.Element.FindElements(By.ClassName("FlipViewItem")); /// /// Gets the element associated with the next item button. /// - public Button NextButton => this.Element.FindElement(WindowsByExtras.AutomationId("NextButtonHorizontal")); + public virtual Button NextButton => this.Element.FindElement(WindowsByExtras.AutomationId("NextButtonHorizontal")); /// /// Gets the element associated with the previous item button. /// - public Button PreviousButton => this.Element.FindElement(WindowsByExtras.AutomationId("PreviousButtonHorizontal")); + public virtual Button PreviousButton => this.Element.FindElement(WindowsByExtras.AutomationId("PreviousButtonHorizontal")); /// /// Gets the currently selected item. /// - public AppiumWebElement SelectedItem => - this.Items.FirstOrDefault( - i => i.GetAttribute("SelectionItem.IsSelected").Equals( - "True", - StringComparison.CurrentCultureIgnoreCase)); + public virtual AppiumWebElement SelectedItem => this.Items.FirstOrDefault(i => i.IsSelected()); /// /// Allows conversion of a to the without direct casting. @@ -83,7 +80,7 @@ public static implicit operator FlipView(AppiumWebElement element) /// /// The name of the item. /// - public void SelectItem(string name) + public virtual void SelectItem(string name) { int currentItemIdx = this.Items.IndexOf(this.SelectedItem); int expectedItemIdx = this.Items.IndexOf( @@ -109,18 +106,18 @@ public void SelectItem(string name) /// /// Selects the next item in the flip view. /// - public void SelectNext() + public virtual void SelectNext() { - this.Element.Click(); + this.Click(); this.Element.SendKeys(Keys.ArrowRight); } /// /// Selects the previous item in the flip view. /// - public void SelectPrevious() + public virtual void SelectPrevious() { - this.Element.Click(); + this.Click(); this.Element.SendKeys(Keys.ArrowLeft); } } diff --git a/src/Legerity.Windows/Elements/Core/FlipViewItem.cs b/src/Legerity.Windows/Elements/Core/FlipViewItem.cs deleted file mode 100644 index c7d500e4..00000000 --- a/src/Legerity.Windows/Elements/Core/FlipViewItem.cs +++ /dev/null @@ -1,6 +0,0 @@ -namespace Legerity.Windows.Elements.Core -{ - internal class FlipViewItem - { - } -} diff --git a/src/Legerity.Windows/Elements/Core/GridView.cs b/src/Legerity.Windows/Elements/Core/GridView.cs index f4bf0ea3..4c3b8b1f 100644 --- a/src/Legerity.Windows/Elements/Core/GridView.cs +++ b/src/Legerity.Windows/Elements/Core/GridView.cs @@ -30,16 +30,13 @@ public GridView(WindowsElement element) /// /// Gets the collection of items associated with the grid view. /// - public ReadOnlyCollection Items => this.Element.FindElements(this.gridViewItemLocator); + public virtual ReadOnlyCollection Items => + this.Element.FindElements(this.gridViewItemLocator); /// /// Gets the element associated with the currently selected item. /// - public AppiumWebElement SelectedItem => - this.Items.FirstOrDefault( - i => i.GetAttribute("SelectionItem.IsSelected").Equals( - "True", - StringComparison.CurrentCultureIgnoreCase)); + public virtual AppiumWebElement SelectedItem => this.Items.FirstOrDefault(i => i.IsSelected()); /// /// Allows conversion of a to the without direct casting. @@ -75,7 +72,7 @@ public static implicit operator GridView(AppiumWebElement element) /// /// The name of the item to click. /// - public void ClickItem(string name) + public virtual void ClickItem(string name) { this.VerifyElementsShown(this.gridViewItemLocator, TimeSpan.FromSeconds(2)); @@ -83,5 +80,21 @@ public void ClickItem(string name) item.Click(); } + + /// + /// Clicks on an item in the list view with the specified partial item name. + /// + /// + /// The partial name of the item to click. + /// + public virtual void ClickItemByPartialName(string partialName) + { + this.VerifyElementsShown(this.gridViewItemLocator, TimeSpan.FromSeconds(2)); + + AppiumWebElement item = + this.Items.FirstOrDefault(element => element.VerifyNameOrAutomationIdContains(partialName)); + + item.Click(); + } } } \ No newline at end of file diff --git a/src/Legerity.Windows/Elements/Core/Hub.cs b/src/Legerity.Windows/Elements/Core/Hub.cs index 51612917..00233c0d 100644 --- a/src/Legerity.Windows/Elements/Core/Hub.cs +++ b/src/Legerity.Windows/Elements/Core/Hub.cs @@ -24,7 +24,7 @@ public Hub(WindowsElement element) /// /// Gets the collection of items associated with the hub. /// - public ReadOnlyCollection Items => this.Element.FindElements(By.ClassName("HubSection")); + public virtual ReadOnlyCollection Items => this.Element.FindElements(By.ClassName("HubSection")); /// /// Allows conversion of a to the without direct casting. diff --git a/src/Legerity.Windows/Elements/Core/InkToolbar.BallpointPenFlyout.cs b/src/Legerity.Windows/Elements/Core/InkToolbar.BallpointPenFlyout.cs index 24418341..4d7e5cb2 100644 --- a/src/Legerity.Windows/Elements/Core/InkToolbar.BallpointPenFlyout.cs +++ b/src/Legerity.Windows/Elements/Core/InkToolbar.BallpointPenFlyout.cs @@ -11,7 +11,7 @@ public partial class InkToolbar /// /// Defines a color flyout for the ballpoint pen in the . /// - private class InkToolbarBallpointPenFlyout : InkToolbarColorFlyoutBase + public class InkToolbarBallpointPenFlyout : InkToolbarColorFlyoutBase { /// /// Initializes a new instance of the class. diff --git a/src/Legerity.Windows/Elements/Core/InkToolbar.ColorFlyoutBase.cs b/src/Legerity.Windows/Elements/Core/InkToolbar.ColorFlyoutBase.cs index 2ac5b3b8..a091be3a 100644 --- a/src/Legerity.Windows/Elements/Core/InkToolbar.ColorFlyoutBase.cs +++ b/src/Legerity.Windows/Elements/Core/InkToolbar.ColorFlyoutBase.cs @@ -3,6 +3,7 @@ namespace Legerity.Windows.Elements.Core using System; using System.Linq; using Legerity.Extensions; + using Legerity.Windows.Extensions; using OpenQA.Selenium; using OpenQA.Selenium.Appium; using OpenQA.Selenium.Appium.Windows; @@ -15,7 +16,7 @@ public partial class InkToolbar /// /// Defines a base for a color flyout in the . /// - private abstract class InkToolbarColorFlyoutBase : WindowsElementWrapper + public abstract class InkToolbarColorFlyoutBase : WindowsElementWrapper { private readonly By penColorPaletteLocator = WindowsByExtras.AutomationId("PenColorPalette"); @@ -33,40 +34,47 @@ protected InkToolbarColorFlyoutBase(WindowsElement element) /// /// Gets the element associated with the color grid. /// - public GridView ColorGridView => this.Driver.FindElement(this.penColorPaletteLocator); + public virtual GridView ColorGridView => this.Driver.FindElement(this.penColorPaletteLocator); /// /// Gets the element associated with the size of the ink. /// - public Slider SizeSlider => this.Driver.FindElement(WindowsByExtras.AutomationId("PenStrokeWidthSlider")); + public virtual Slider SizeSlider => + this.Driver.FindElement(WindowsByExtras.AutomationId("PenStrokeWidthSlider")); /// /// Gets the currently selected color. /// - public string SelectedColor => this.GetSelectedColor().GetName(); + public virtual string SelectedColor => this.GetSelectedColor().GetName(); /// /// Gets the currently selected size. /// - public double SelectedSize => this.SizeSlider.Value; + public virtual double SelectedSize => this.SizeSlider.Value; /// /// Sets the color of the ink. /// /// The color to select. - public void SetColor(string color) + public virtual void SetColor(string color) { this.ColorGridView.ClickItem(color); } + /// + /// Sets the color of the ink by partial color name match. + /// + /// The partial color name to select. + public virtual void SetColorByPartialName(string partialColor) + { + this.ColorGridView.ClickItemByPartialName(partialColor); + } + private AppiumWebElement GetSelectedColor() { this.VerifyElementShown(this.penColorPaletteLocator, TimeSpan.FromSeconds(2)); - return this.ColorGridView.Items.FirstOrDefault( - i => i.GetAttribute("SelectionItem.IsSelected").Equals( - "True", - StringComparison.CurrentCultureIgnoreCase)); + return this.ColorGridView.Items.FirstOrDefault(i => i.IsSelected()); } } } diff --git a/src/Legerity.Windows/Elements/Core/InkToolbar.HighlighterFlyout.cs b/src/Legerity.Windows/Elements/Core/InkToolbar.HighlighterFlyout.cs index 4c44bc45..4b001e48 100644 --- a/src/Legerity.Windows/Elements/Core/InkToolbar.HighlighterFlyout.cs +++ b/src/Legerity.Windows/Elements/Core/InkToolbar.HighlighterFlyout.cs @@ -11,7 +11,7 @@ public partial class InkToolbar /// /// Defines a color flyout for the highlighter in the . /// - private class InkToolbarHighlighterFlyout : InkToolbarColorFlyoutBase + public class InkToolbarHighlighterFlyout : InkToolbarColorFlyoutBase { /// /// Initializes a new instance of the class. diff --git a/src/Legerity.Windows/Elements/Core/InkToolbar.PencilFlyout.cs b/src/Legerity.Windows/Elements/Core/InkToolbar.PencilFlyout.cs index 35e7532a..b4cf410d 100644 --- a/src/Legerity.Windows/Elements/Core/InkToolbar.PencilFlyout.cs +++ b/src/Legerity.Windows/Elements/Core/InkToolbar.PencilFlyout.cs @@ -11,7 +11,7 @@ public partial class InkToolbar /// /// Defines a color flyout for the pencil in the . /// - private class InkToolbarPencilFlyout : InkToolbarColorFlyoutBase + public class InkToolbarPencilFlyout : InkToolbarColorFlyoutBase { /// /// Initializes a new instance of the class. diff --git a/src/Legerity.Windows/Elements/Core/InkToolbar.cs b/src/Legerity.Windows/Elements/Core/InkToolbar.cs index 22914e41..7191e501 100644 --- a/src/Legerity.Windows/Elements/Core/InkToolbar.cs +++ b/src/Legerity.Windows/Elements/Core/InkToolbar.cs @@ -30,48 +30,67 @@ public InkToolbar(WindowsElement element) /// /// Gets the element associated with the ballpoint pen button. /// - public RadioButton BallpointPenButton => + public virtual RadioButton BallpointPenButton => this.Element.FindElement(WindowsByExtras.AutomationId("InkToolbarBallpointPenButton")); /// /// Gets the currently selected ballpoint pen color. /// - public string SelectedBallpointPenColor => this.BallpointPenFlyout.SelectedColor; + public virtual string SelectedBallpointPenColor => this.BallpointPenFlyout.SelectedColor; /// /// Gets the element associated with the pencil button. /// - public RadioButton PencilButton => + public virtual RadioButton PencilButton => this.Element.FindElement(WindowsByExtras.AutomationId("InkToolbarPencilButton")); /// /// Gets the currently selected pencil color. /// - public string SelectedPencilColor => this.PencilFlyout.SelectedColor; + public virtual string SelectedPencilColor => this.PencilFlyout.SelectedColor; /// /// Gets the element associated with the highlighter button. /// - public RadioButton HighlighterButton => + public virtual RadioButton HighlighterButton => this.Element.FindElement(WindowsByExtras.AutomationId("InkToolbarHighlighterButton")); /// /// Gets the currently selected highlighter color. /// - public string SelectedHighlighterColor => this.HighlighterFlyout.SelectedColor; + public virtual string SelectedHighlighterColor => this.HighlighterFlyout.SelectedColor; /// /// Gets the element associated with the ruler button. /// - public ToggleButton RulerButton => + public virtual ToggleButton RulerButton => this.Element.FindElement(WindowsByExtras.AutomationId("InkToolbarStencilButton")); - private InkToolbarBallpointPenFlyout BallpointPenFlyout => + /// + /// Gets the element associated with the ballpoint pen flyout. + /// + /// + /// This is only available when the ballpoint pen button is selected. + /// + public virtual InkToolbarBallpointPenFlyout BallpointPenFlyout => this.Driver.FindElement(this.ballpointPenFlyoutLocator); - private InkToolbarPencilFlyout PencilFlyout => this.Driver.FindElement(this.pencilFlyoutLocator); + /// + /// Gets the element associated with the pencil flyout. + /// + /// + /// This is only available when the pencil button is selected. + /// + public virtual InkToolbarPencilFlyout PencilFlyout => this.Driver.FindElement(this.pencilFlyoutLocator); - private InkToolbarHighlighterFlyout HighlighterFlyout => this.Driver.FindElement(this.highlighterFlyoutLocator); + /// + /// Gets the element associated with the highlighter flyout. + /// + /// + /// This is only available when the highlighter button is selected. + /// + public virtual InkToolbarHighlighterFlyout HighlighterFlyout => + this.Driver.FindElement(this.highlighterFlyoutLocator); /// /// Allows conversion of a to the without direct casting. @@ -104,7 +123,7 @@ public static implicit operator InkToolbar(AppiumWebElement element) /// /// Selects the ballpoint pen option. /// - public void SelectBallpointPen() + public virtual void SelectBallpointPen() { if (!this.BallpointPenButton.IsSelected) { @@ -115,7 +134,7 @@ public void SelectBallpointPen() /// /// Opens the ballpoint pen flyout. /// - public void OpenBallpointPenFlyout() + public virtual void OpenBallpointPenFlyout() { this.SelectBallpointPen(); @@ -129,16 +148,28 @@ public void OpenBallpointPenFlyout() /// /// The color to set. /// - public void SetBallpointPenColor(string color) + public virtual void SetBallpointPenColor(string color) { this.OpenBallpointPenFlyout(); this.BallpointPenFlyout.SetColor(color); } + /// + /// Sets the toolbar to the ballpoint pen with the given partial color name. + /// + /// + /// The partial color name to set. + /// + public virtual void SetBallpointPenColorByPartialName(string color) + { + this.OpenBallpointPenFlyout(); + this.BallpointPenFlyout.SetColorByPartialName(color); + } + /// /// Selects the pencil option. /// - public void SelectPencil() + public virtual void SelectPencil() { if (!this.PencilButton.IsSelected) { @@ -149,7 +180,7 @@ public void SelectPencil() /// /// Opens the pencil flyout. /// - public void OpenPencilFlyout() + public virtual void OpenPencilFlyout() { this.SelectPencil(); @@ -163,16 +194,28 @@ public void OpenPencilFlyout() /// /// The color to set. /// - public void SetPencilColor(string color) + public virtual void SetPencilColor(string color) { this.OpenPencilFlyout(); this.PencilFlyout.SetColor(color); } + /// + /// Sets the toolbar to the pencil with the given partial color name. + /// + /// + /// The partial color name to set. + /// + public virtual void SetPencilColorByPartialName(string color) + { + this.OpenPencilFlyout(); + this.PencilFlyout.SetColorByPartialName(color); + } + /// /// Selects the highlighter option. /// - public void SelectHighlighter() + public virtual void SelectHighlighter() { if (!this.HighlighterButton.IsSelected) { @@ -183,7 +226,7 @@ public void SelectHighlighter() /// /// Opens the pencil flyout. /// - public void OpenHighlighterFlyout() + public virtual void OpenHighlighterFlyout() { this.SelectHighlighter(); @@ -192,15 +235,27 @@ public void OpenHighlighterFlyout() } /// - /// Sets the toolbar to the pencil with the given color and size. + /// Sets the toolbar to the highlighter with the given color. /// /// /// The color to set. /// - public void SetHighlighterColor(string color) + public virtual void SetHighlighterColor(string color) { this.OpenHighlighterFlyout(); this.HighlighterFlyout.SetColor(color); } + + /// + /// Sets the toolbar to the highlighter with the given color. + /// + /// + /// The color to set. + /// + public virtual void SetHighlighterColorByPartialName(string color) + { + this.OpenHighlighterFlyout(); + this.HighlighterFlyout.SetColorByPartialName(color); + } } } \ No newline at end of file diff --git a/src/Legerity.Windows/Elements/Core/ListBox.cs b/src/Legerity.Windows/Elements/Core/ListBox.cs index e305fd99..d4c5b110 100644 --- a/src/Legerity.Windows/Elements/Core/ListBox.cs +++ b/src/Legerity.Windows/Elements/Core/ListBox.cs @@ -30,16 +30,12 @@ public ListBox(WindowsElement element) /// /// Gets the collection of items associated with the list box. /// - public ReadOnlyCollection Items => this.Element.FindElements(this.listBoxItemLocator); + public virtual ReadOnlyCollection Items => this.Element.FindElements(this.listBoxItemLocator); /// /// Gets the element associated with the currently selected item. /// - public AppiumWebElement SelectedItem => - this.Items.FirstOrDefault( - i => i.GetAttribute("SelectionItem.IsSelected").Equals( - "True", - StringComparison.CurrentCultureIgnoreCase)); + public virtual AppiumWebElement SelectedItem => this.Items.FirstOrDefault(i => i.IsSelected()); /// /// Allows conversion of a to the without direct casting. @@ -75,12 +71,22 @@ public static implicit operator ListBox(AppiumWebElement element) /// /// The name of the item to click. /// - public void ClickItem(string name) + public virtual void ClickItem(string name) { this.VerifyElementsShown(this.listBoxItemLocator, TimeSpan.FromSeconds(2)); - AppiumWebElement item = this.Items.FirstOrDefault(element => element.VerifyNameOrAutomationIdEquals(name)); + item.Click(); + } + /// + /// Clicks on an item in the list box with the specified partial item name. + /// + /// The partial name match for the item to click. + public virtual void ClickItemByPartialName(string partialName) + { + this.VerifyElementsShown(this.listBoxItemLocator, TimeSpan.FromSeconds(2)); + AppiumWebElement item = + this.Items.FirstOrDefault(element => element.VerifyNameOrAutomationIdContains(partialName)); item.Click(); } } diff --git a/src/Legerity.Windows/Elements/Core/ListView.cs b/src/Legerity.Windows/Elements/Core/ListView.cs index e79dc4f7..30b3a8e0 100644 --- a/src/Legerity.Windows/Elements/Core/ListView.cs +++ b/src/Legerity.Windows/Elements/Core/ListView.cs @@ -30,16 +30,12 @@ public ListView(WindowsElement element) /// /// Gets the collection of items associated with the list view. /// - public ReadOnlyCollection Items => this.Element.FindElements(this.listViewItemLocator); + public virtual ReadOnlyCollection Items => this.Element.FindElements(this.listViewItemLocator); /// /// Gets the element associated with the currently selected item. /// - public AppiumWebElement SelectedItem => - this.Items.FirstOrDefault( - i => i.GetAttribute("SelectionItem.IsSelected").Equals( - "True", - StringComparison.CurrentCultureIgnoreCase)); + public virtual AppiumWebElement SelectedItem => this.Items.FirstOrDefault(i => i.IsSelected()); /// /// Allows conversion of a to the without direct casting. @@ -75,11 +71,23 @@ public static implicit operator ListView(AppiumWebElement element) /// /// The name of the item to click. /// - public void ClickItem(string name) + public virtual void ClickItem(string name) { this.VerifyElementsShown(this.listViewItemLocator, TimeSpan.FromSeconds(2)); AppiumWebElement item = this.Items.FirstOrDefault(element => element.VerifyNameOrAutomationIdEquals(name)); item.Click(); } + + /// + /// Clicks on an item in the list view with the specified partial item name. + /// + /// The partial name match for the item to click. + public virtual void ClickItemByPartialName(string partialName) + { + this.VerifyElementsShown(this.listViewItemLocator, TimeSpan.FromSeconds(2)); + AppiumWebElement item = + this.Items.FirstOrDefault(element => element.VerifyNameOrAutomationIdContains(partialName)); + item.Click(); + } } } \ No newline at end of file diff --git a/src/Legerity.Windows/Elements/Core/MenuFlyoutItem.cs b/src/Legerity.Windows/Elements/Core/MenuFlyoutItem.cs index eb747d73..a81162f0 100644 --- a/src/Legerity.Windows/Elements/Core/MenuFlyoutItem.cs +++ b/src/Legerity.Windows/Elements/Core/MenuFlyoutItem.cs @@ -17,13 +17,5 @@ public MenuFlyoutItem(WindowsElement element) : base(element) { } - - /// - /// Clicks the item. - /// - public void Click() - { - this.Element.Click(); - } } } \ No newline at end of file diff --git a/src/Legerity.Windows/Elements/Core/MenuFlyoutSubItem.cs b/src/Legerity.Windows/Elements/Core/MenuFlyoutSubItem.cs index 98707bf4..308387ab 100644 --- a/src/Legerity.Windows/Elements/Core/MenuFlyoutSubItem.cs +++ b/src/Legerity.Windows/Elements/Core/MenuFlyoutSubItem.cs @@ -2,6 +2,7 @@ namespace Legerity.Windows.Elements.Core { using System; using System.Collections.Generic; + using System.Globalization; using System.Linq; using Legerity.Extensions; using OpenQA.Selenium; @@ -26,35 +27,46 @@ public MenuFlyoutSubItem(WindowsElement element) /// /// Gets the UI components associated with the child menu items. /// - public IEnumerable ChildMenuItems => this.GetChildMenuItems(); + public virtual IEnumerable ChildMenuItems => this.GetChildMenuItems(); /// /// Gets the UI components associated with the child menu sub-items. /// - public IEnumerable ChildMenuSubItems => this.GetChildMenuSubItems(); + public virtual IEnumerable ChildMenuSubItems => this.GetChildMenuSubItems(); /// - /// Clicks the item. + /// Clicks on a child menu option with the specified item name. /// - public void Click() + /// + /// The name of the item to click. + /// + /// + /// The clicked . + /// + public virtual MenuFlyoutItem ClickChildOption(string name) { - this.Element.Click(); + MenuFlyoutItem item = this.ChildMenuItems.FirstOrDefault( + element => element.GetName() + .Equals(name, StringComparison.CurrentCultureIgnoreCase)); + + item.Click(); + return item; } /// - /// Clicks on a child menu option with the specified item name. + /// Clicks on a child menu option with the specified partial item name. /// /// - /// The name of the item to click. + /// The partial name of the item to click. /// /// /// The clicked . /// - public MenuFlyoutItem ClickChildOption(string name) + public virtual MenuFlyoutItem ClickChildOptionByPartialName(string name) { MenuFlyoutItem item = this.ChildMenuItems.FirstOrDefault( element => element.GetName() - .Equals(name, StringComparison.CurrentCultureIgnoreCase)); + .Contains(name, CultureInfo.CurrentCulture, CompareOptions.IgnoreCase)); item.Click(); return item; @@ -65,7 +77,7 @@ public MenuFlyoutItem ClickChildOption(string name) /// /// The name of the sub-item to click. /// The clicked . - public MenuFlyoutSubItem ClickChildSubOption(string name) + public virtual MenuFlyoutSubItem ClickChildSubOption(string name) { MenuFlyoutSubItem item = this.ChildMenuSubItems.FirstOrDefault( element => element.GetName() @@ -74,6 +86,21 @@ public MenuFlyoutSubItem ClickChildSubOption(string name) return item; } + /// + /// Clicks on a child menu sub option with the specified partial item name. + /// + /// The name of the sub-item to click. + /// The clicked . + public virtual MenuFlyoutSubItem ClickChildSubOptionByPartialName(string name) + { + MenuFlyoutSubItem item = this.ChildMenuSubItems.FirstOrDefault( + element => element.GetName() + .Contains(name, CultureInfo.CurrentCulture, CompareOptions.IgnoreCase)); + + item.Click(); + return item; + } + private IEnumerable GetChildMenuItems() { return this.Driver.FindElement(By.ClassName("MenuFlyout")) diff --git a/src/Legerity.Windows/Elements/Core/PasswordBox.cs b/src/Legerity.Windows/Elements/Core/PasswordBox.cs index d0b96077..7806b2ce 100644 --- a/src/Legerity.Windows/Elements/Core/PasswordBox.cs +++ b/src/Legerity.Windows/Elements/Core/PasswordBox.cs @@ -22,7 +22,7 @@ public PasswordBox(WindowsElement element) /// /// Gets the element associated with the reveal password button. /// - public ToggleButton RevealButton => this.Element.FindElement(WindowsByExtras.AutomationId("RevealButton")); + public virtual ToggleButton RevealButton => this.Element.FindElement(WindowsByExtras.AutomationId("RevealButton")); /// /// Allows conversion of a to the without direct casting. diff --git a/src/Legerity.Windows/Elements/Core/Pivot.cs b/src/Legerity.Windows/Elements/Core/Pivot.cs index 5b675209..0698a5fa 100644 --- a/src/Legerity.Windows/Elements/Core/Pivot.cs +++ b/src/Legerity.Windows/Elements/Core/Pivot.cs @@ -30,16 +30,12 @@ public Pivot(WindowsElement element) /// /// Gets the collection of items associated with the pivot. /// - public ReadOnlyCollection Items => this.Element.FindElements(this.pivotItemLocator); + public virtual ReadOnlyCollection Items => this.Element.FindElements(this.pivotItemLocator); /// /// Gets the currently selected item. /// - public AppiumWebElement SelectedItem => - this.Items.FirstOrDefault( - i => i.GetAttribute("SelectionItem.IsSelected").Equals( - "True", - StringComparison.CurrentCultureIgnoreCase)); + public virtual AppiumWebElement SelectedItem => this.Items.FirstOrDefault(i => i.IsSelected()); /// /// Allows conversion of a to the without direct casting. @@ -75,7 +71,7 @@ public static implicit operator Pivot(AppiumWebElement element) /// /// The name of the item to click. /// - public void ClickItem(string name) + public virtual void ClickItem(string name) { this.VerifyElementsShown(this.pivotItemLocator, TimeSpan.FromSeconds(2)); @@ -83,5 +79,20 @@ public void ClickItem(string name) item.Click(); } + + /// + /// Clicks on an item in the pivot with the specified partial item name. + /// + /// + /// The partial name of the item to click. + /// + public virtual void ClickItemByPartialName(string name) + { + this.VerifyElementsShown(this.pivotItemLocator, TimeSpan.FromSeconds(2)); + + AppiumWebElement item = this.Items.FirstOrDefault(element => element.VerifyNameOrAutomationIdContains(name)); + + item.Click(); + } } } \ No newline at end of file diff --git a/src/Legerity.Windows/Elements/Core/ProgressBar.cs b/src/Legerity.Windows/Elements/Core/ProgressBar.cs index 8968dbc9..d35282d7 100644 --- a/src/Legerity.Windows/Elements/Core/ProgressBar.cs +++ b/src/Legerity.Windows/Elements/Core/ProgressBar.cs @@ -1,6 +1,7 @@ namespace Legerity.Windows.Elements.Core { using System; + using Legerity.Windows.Extensions; using OpenQA.Selenium.Appium; using OpenQA.Selenium.Appium.Windows; @@ -23,13 +24,13 @@ public ProgressBar(WindowsElement element) /// /// Gets the value of the progress bar. /// - public double Percentage => double.Parse(this.Element.GetAttribute("RangeValue.Value")); + public virtual double Percentage => this.GetRangeValue(); /// /// Gets a value indicating whether the control is in an indeterminate state. /// public bool IsIndeterminate => - this.Element.GetAttribute("IsRangeValuePatternAvailable").Equals( + this.GetAttribute("IsRangeValuePatternAvailable").Equals( "False", StringComparison.CurrentCultureIgnoreCase); diff --git a/src/Legerity.Windows/Elements/Core/RadioButton.cs b/src/Legerity.Windows/Elements/Core/RadioButton.cs index f5683bb2..b9167e60 100644 --- a/src/Legerity.Windows/Elements/Core/RadioButton.cs +++ b/src/Legerity.Windows/Elements/Core/RadioButton.cs @@ -1,6 +1,6 @@ namespace Legerity.Windows.Elements.Core { - using System; + using Legerity.Windows.Extensions; using OpenQA.Selenium.Appium; using OpenQA.Selenium.Appium.Windows; @@ -23,10 +23,7 @@ public RadioButton(WindowsElement element) /// /// Gets a value indicating whether the radio button is selected. /// - public bool IsSelected => - this.Element.GetAttribute("SelectionItem.IsSelected").Equals( - "True", - StringComparison.CurrentCultureIgnoreCase); + public virtual bool IsSelected => this.IsSelected(); /// /// Allows conversion of a to the without direct casting. diff --git a/src/Legerity.Windows/Elements/Core/Slider.cs b/src/Legerity.Windows/Elements/Core/Slider.cs index 34fee012..7db3f8a1 100644 --- a/src/Legerity.Windows/Elements/Core/Slider.cs +++ b/src/Legerity.Windows/Elements/Core/Slider.cs @@ -1,6 +1,7 @@ namespace Legerity.Windows.Elements.Core { using System; + using Legerity.Windows.Extensions; using OpenQA.Selenium; using OpenQA.Selenium.Appium; using OpenQA.Selenium.Appium.Windows; @@ -24,27 +25,27 @@ public Slider(WindowsElement element) /// /// Gets the minimum value of the slider. /// - public double Minimum => double.Parse(this.Element.GetAttribute("RangeValue.Minimum")); + public virtual double Minimum => this.GetRangeMinimum(); /// /// Gets the maximum value of the slider. /// - public double Maximum => double.Parse(this.Element.GetAttribute("RangeValue.Maximum")); + public virtual double Maximum => this.GetRangeMaximum(); /// /// Gets the small change (step) value of the slider. /// - public double SmallChange => double.Parse(this.Element.GetAttribute("RangeValue.SmallChange")); + public virtual double SmallChange => this.GetRangeSmallChange(); /// /// Gets the value of the slider. /// - public double Value => double.Parse(this.Element.GetAttribute("RangeValue.Value")); + public virtual double Value => this.GetRangeValue(); /// /// Gets a value indicating whether the control is in a readonly state. /// - public bool IsReadonly => bool.Parse(this.Element.GetAttribute("RangeValue.IsReadOnly")); + public virtual bool IsReadonly => this.IsRangeReadonly(); /// /// Allows conversion of a to the without direct casting. @@ -83,22 +84,28 @@ public static implicit operator Slider(AppiumWebElement element) /// /// Thrown if the value is out of the minimum and maximum range of the slider. /// - public void SetValue(double value) + public virtual void SetValue(double value) { 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}"); + 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.Element.Click(); + this.Click(); double currentValue = this.Value; while (Math.Abs(currentValue - value) > double.Epsilon) diff --git a/src/Legerity.Windows/Elements/Core/TextBlock.cs b/src/Legerity.Windows/Elements/Core/TextBlock.cs index 69402c85..b374348b 100644 --- a/src/Legerity.Windows/Elements/Core/TextBlock.cs +++ b/src/Legerity.Windows/Elements/Core/TextBlock.cs @@ -22,7 +22,7 @@ public TextBlock(WindowsElement element) /// /// Gets the text value of the text block. /// - public string Text => this.Element.Text; + public virtual string Text => this.Element.Text; /// /// Allows conversion of a to the without direct casting. diff --git a/src/Legerity.Windows/Elements/Core/TextBox.cs b/src/Legerity.Windows/Elements/Core/TextBox.cs index 051d9edb..7c08938c 100644 --- a/src/Legerity.Windows/Elements/Core/TextBox.cs +++ b/src/Legerity.Windows/Elements/Core/TextBox.cs @@ -1,6 +1,6 @@ namespace Legerity.Windows.Elements.Core { - using System; + using Legerity.Windows.Extensions; using OpenQA.Selenium.Appium; using OpenQA.Selenium.Appium.Windows; @@ -23,13 +23,12 @@ public TextBox(WindowsElement element) /// /// Gets the text value of the text box. /// - public string Text => this.Element.GetAttribute("Value.Value"); + public virtual string Text => this.GetValue(); /// /// Gets a value indicating whether the text box is in a readonly state. /// - public bool IsReadonly => - this.Element.GetAttribute("Value.IsReadonly").Equals("True", StringComparison.CurrentCultureIgnoreCase); + public virtual bool IsReadonly => this.IsReadonly(); /// /// Allows conversion of a to the without direct casting. @@ -63,7 +62,7 @@ public static implicit operator TextBox(AppiumWebElement element) /// Sets the text of the text box to the specified text. /// /// The text to display. - public void SetText(string text) + public virtual void SetText(string text) { this.ClearText(); this.AppendText(text); @@ -73,18 +72,18 @@ public void SetText(string text) /// Appends the specified text to the text box. /// /// The text to append. - public void AppendText(string text) + public virtual void AppendText(string text) { - this.Element.Click(); + this.Click(); this.Element.SendKeys(text); } /// /// Clears the text from the text box. /// - public void ClearText() + public virtual void ClearText() { - this.Element.Click(); + this.Click(); this.Element.Clear(); } } diff --git a/src/Legerity.Windows/Elements/Core/TimePicker.cs b/src/Legerity.Windows/Elements/Core/TimePicker.cs index b5f25987..c27d4618 100644 --- a/src/Legerity.Windows/Elements/Core/TimePicker.cs +++ b/src/Legerity.Windows/Elements/Core/TimePicker.cs @@ -54,10 +54,10 @@ public static implicit operator TimePicker(AppiumWebElement element) /// /// The time to set. /// - public void SetTime(TimeSpan time) + public virtual void SetTime(TimeSpan time) { // Taps the time picker to show the popup. - this.Element.Click(); + this.Click(); // Finds the popup and changes the time. WindowsElement popup = this.Driver.FindElement(WindowsByExtras.AutomationId("TimePickerFlyoutPresenter")); diff --git a/src/Legerity.Windows/Elements/Core/ToggleButton.cs b/src/Legerity.Windows/Elements/Core/ToggleButton.cs index 33d8ed6a..a9ca5f56 100644 --- a/src/Legerity.Windows/Elements/Core/ToggleButton.cs +++ b/src/Legerity.Windows/Elements/Core/ToggleButton.cs @@ -1,5 +1,6 @@ namespace Legerity.Windows.Elements.Core { + using Legerity.Windows.Extensions; using OpenQA.Selenium.Appium; using OpenQA.Selenium.Appium.Windows; @@ -8,8 +9,6 @@ namespace Legerity.Windows.Elements.Core /// public class ToggleButton : Button { - private const string ToggleOnValue = "1"; - /// /// Initializes a new instance of the class. /// @@ -24,7 +23,7 @@ public ToggleButton(WindowsElement element) /// /// Gets a value indicating whether the toggle button is in the on position. /// - public bool IsOn => this.Element.GetAttribute("Toggle.ToggleState") == ToggleOnValue; + public virtual bool IsOn => this.GetToggleState() == ToggleState.Checked; /// /// Allows conversion of a to the without direct casting. @@ -57,7 +56,7 @@ public static implicit operator ToggleButton(AppiumWebElement element) /// /// Toggles the button on. /// - public void ToggleOn() + public virtual void ToggleOn() { if (this.IsOn) { @@ -70,7 +69,7 @@ public void ToggleOn() /// /// Toggles the button off. /// - public void ToggleOff() + public virtual void ToggleOff() { if (!this.IsOn) { diff --git a/src/Legerity.Windows/Elements/Core/ToggleState.cs b/src/Legerity.Windows/Elements/Core/ToggleState.cs new file mode 100644 index 00000000..83685523 --- /dev/null +++ b/src/Legerity.Windows/Elements/Core/ToggleState.cs @@ -0,0 +1,23 @@ +namespace Legerity.Windows.Elements.Core +{ + /// + /// Defines the states of a toggle in a Windows element. + /// + public enum ToggleState + { + /// + /// The toggle is not checked. + /// + Unchecked = 0, + + /// + /// The toggle is checked. + /// + Checked = 1, + + /// + /// The toggle is indeterminate. + /// + Indeterminate = 2, + } +} \ No newline at end of file diff --git a/src/Legerity.Windows/Elements/Core/ToggleSwitch.cs b/src/Legerity.Windows/Elements/Core/ToggleSwitch.cs index dbe9e3c1..c69ac271 100644 --- a/src/Legerity.Windows/Elements/Core/ToggleSwitch.cs +++ b/src/Legerity.Windows/Elements/Core/ToggleSwitch.cs @@ -1,5 +1,6 @@ namespace Legerity.Windows.Elements.Core { + using Legerity.Windows.Extensions; using OpenQA.Selenium.Appium; using OpenQA.Selenium.Appium.Windows; @@ -8,8 +9,6 @@ namespace Legerity.Windows.Elements.Core /// public class ToggleSwitch : WindowsElementWrapper { - private const string ToggleOnValue = "1"; - /// /// Initializes a new instance of the class. /// @@ -24,7 +23,7 @@ public ToggleSwitch(WindowsElement element) /// /// Gets a value indicating whether the toggle switch is in the on position. /// - public bool IsOn => this.Element.GetAttribute("Toggle.ToggleState") == ToggleOnValue; + public virtual bool IsOn => this.GetToggleState() == ToggleState.Checked; /// /// Allows conversion of a to the without direct casting. @@ -57,27 +56,27 @@ public static implicit operator ToggleSwitch(AppiumWebElement element) /// /// Toggles the switch on. /// - public void ToggleOn() + public virtual void ToggleOn() { if (this.IsOn) { return; } - this.Element.Click(); + this.Click(); } /// /// Toggles the switch off. /// - public void ToggleOff() + public virtual void ToggleOff() { if (!this.IsOn) { return; } - this.Element.Click(); + this.Click(); } } } \ No newline at end of file diff --git a/src/Legerity.Windows/Extensions/AttributeExtensions.cs b/src/Legerity.Windows/Extensions/AttributeExtensions.cs index 45de19cc..fc6b29bd 100644 --- a/src/Legerity.Windows/Extensions/AttributeExtensions.cs +++ b/src/Legerity.Windows/Extensions/AttributeExtensions.cs @@ -1,5 +1,7 @@ namespace Legerity.Windows.Extensions { + using System; + using Legerity.Windows.Elements.Core; using OpenQA.Selenium; using OpenQA.Selenium.Remote; @@ -31,5 +33,227 @@ public static string GetAutomationId(this IElementWrapper el { return GetAutomationId(element.Element); } + + /// + /// Retrieves the Value.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.Value"); + } + + /// + /// Retrieves the Value.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.IsReadonly attribute from the specified element. + /// + /// The to retrieve the readonly state from. + /// A value indicating whether the item is readonly. + public static bool IsReadonly(this IWebElement element) + { + return element.GetAttribute("Value.IsReadonly").Equals("True", StringComparison.CurrentCultureIgnoreCase); + } + + /// + /// Retrieves the Value.IsReadonly attribute from the specified element. + /// + /// + /// The type of . + /// + /// The to retrieve the readonly state from. + /// A value indicating whether the item is readonly. + public static bool IsReadonly(this IElementWrapper element) + where TElement : IWebElement + { + return IsReadonly(element.Element); + } + + /// + /// Retrieves the Toggle.ToggleState attribute from the specified element. + /// + /// The to retrieve a toggle state from. + /// The of the element. + public static ToggleState GetToggleState(this IWebElement element) + { + return element.GetAttribute("Toggle.ToggleState") switch + { + "1" => ToggleState.Checked, + "2" => ToggleState.Indeterminate, + _ => ToggleState.Unchecked + }; + } + + /// + /// Retrieves the Toggle.ToggleState attribute from the specified element. + /// + /// + /// The type of . + /// + /// The to retrieve a toggle state from. + /// The of the element. + public static ToggleState GetToggleState(this IElementWrapper element) + where TElement : IWebElement + { + return GetToggleState(element.Element); + } + + /// + /// Retrieves the SelectionItem.IsSelected attribute from the specified element. + /// + /// The to retrieve the selected state from. + /// A value indicating whether the item is selected. + public static bool IsSelected(this IWebElement element) + { + return element.GetAttribute("SelectionItem.IsSelected") + .Equals("True", StringComparison.CurrentCultureIgnoreCase); + } + + /// + /// Retrieves the SelectionItem.IsSelected attribute from the specified element. + /// + /// + /// The type of . + /// + /// The to retrieve the selected state from. + /// A value indicating whether the item is selected. + public static bool IsSelected(this IElementWrapper element) + where TElement : IWebElement + { + return IsSelected(element.Element); + } + + /// + /// Retrieves the RangeValue.Value attribute from the specified element. + /// + /// The to retrieve the range value from. + /// The range value of the element. + public static double GetRangeValue(this IWebElement element) + { + return double.Parse(element.GetAttribute("RangeValue.Value")); + } + + /// + /// Retrieves the RangeValue.Value attribute from the specified element. + /// + /// + /// The type of . + /// + /// The to retrieve the range value from. + /// The range value of the element. + public static double GetRangeValue(this IElementWrapper element) + where TElement : IWebElement + { + return GetRangeValue(element.Element); + } + + /// + /// Retrieves the RangeValue.Maximum attribute from the specified element. + /// + /// The to retrieve the range max value from. + /// The range max value of the element. + public static double GetRangeMaximum(this IWebElement element) + { + return double.Parse(element.GetAttribute("RangeValue.Maximum")); + } + + /// + /// Retrieves the RangeValue.Maximum attribute from the specified element. + /// + /// + /// The type of . + /// + /// The to retrieve the range max value from. + /// The range max value of the element. + public static double GetRangeMaximum(this IElementWrapper element) + where TElement : IWebElement + { + return GetRangeMaximum(element.Element); + } + + /// + /// Retrieves the RangeValue.Minimum attribute from the specified element. + /// + /// The to retrieve the range min value from. + /// The range min value of the element. + public static double GetRangeMinimum(this IWebElement element) + { + return double.Parse(element.GetAttribute("RangeValue.Minimum")); + } + + /// + /// Retrieves the RangeValue.Minimum attribute from the specified element. + /// + /// + /// The type of . + /// + /// The to retrieve the range min value from. + /// The range min value of the element. + public static double GetRangeMinimum(this IElementWrapper element) + where TElement : IWebElement + { + return GetRangeMinimum(element.Element); + } + + /// + /// Retrieves the RangeValue.SmallChange attribute from the specified element. + /// + /// The to retrieve the range step value from. + /// The range step value of the element. + public static double GetRangeSmallChange(this IWebElement element) + { + return double.Parse(element.GetAttribute("RangeValue.SmallChange")); + } + + /// + /// Retrieves the RangeValue.SmallChange attribute from the specified element. + /// + /// + /// The type of . + /// + /// The to retrieve the range step value from. + /// The range step value of the element. + public static double GetRangeSmallChange(this IElementWrapper element) + where TElement : IWebElement + { + return GetRangeSmallChange(element.Element); + } + + /// + /// Retrieves the RangeValue.IsReadOnly attribute from the specified element. + /// + /// The to retrieve the readonly state from. + /// A value indicating whether the item is readonly. + public static bool IsRangeReadonly(this IWebElement element) + { + return bool.Parse(element.GetAttribute("RangeValue.IsReadOnly")); + } + + /// + /// Retrieves the RangeValue.IsReadOnly attribute from the specified element. + /// + /// + /// The type of . + /// + /// The to retrieve the readonly state from. + /// A value indicating whether the item is readonly. + public static bool IsRangeReadonly(this IElementWrapper element) + where TElement : IWebElement + { + return IsRangeReadonly(element.Element); + } } -} +} \ No newline at end of file diff --git a/src/Legerity.Windows/Extensions/WindowsElementExtensions.cs b/src/Legerity.Windows/Extensions/WindowsElementExtensions.cs index 78b9a469..20d0ff22 100644 --- a/src/Legerity.Windows/Extensions/WindowsElementExtensions.cs +++ b/src/Legerity.Windows/Extensions/WindowsElementExtensions.cs @@ -1,6 +1,7 @@ namespace Legerity.Windows.Extensions { using System; + using System.Globalization; using Legerity.Extensions; using OpenQA.Selenium; using OpenQA.Selenium.Appium; @@ -20,7 +21,9 @@ public static class WindowsElementExtensions /// The to search. /// The automation ID associated with the element to locate. /// The located . - public static TElement FindElementByAutomationId(this WindowsDriver driver, string automationId) + public static TElement FindElementByAutomationId( + this WindowsDriver driver, + string automationId) where TElement : IWebElement { return driver.FindElement(WindowsByExtras.AutomationId(automationId)); @@ -55,9 +58,9 @@ public static bool VerifyNameOrAutomationIdEquals(this AppiumWebElement element, string automationId = element.GetAutomationId(); return string.Equals(compare, name, StringComparison.CurrentCultureIgnoreCase) || string.Equals( - compare, - automationId, - StringComparison.CurrentCultureIgnoreCase); + compare, + automationId, + StringComparison.CurrentCultureIgnoreCase); } /// @@ -78,9 +81,43 @@ public static bool VerifyNameOrAutomationIdEquals(this WindowsElement element, s string automationId = element.GetAutomationId(); return string.Equals(compare, name, StringComparison.CurrentCultureIgnoreCase) || string.Equals( - compare, - automationId, - StringComparison.CurrentCultureIgnoreCase); + compare, + automationId, + StringComparison.CurrentCultureIgnoreCase); + } + + /// + /// Verifies the elements name or AutomationId based on the given partial compare. + /// + /// + /// The element to verify. + /// + /// The partial value to verify is the name or AutomationId. + /// + /// True if the element's name or AutomationId matches; otherwise, false. + /// + public static bool VerifyNameOrAutomationIdContains(this AppiumWebElement element, string partialCompare) + { + string name = element.GetName(); + string automationId = element.GetAutomationId(); + + return partialCompare.Contains(name, CultureInfo.CurrentCulture, CompareOptions.IgnoreCase) || + partialCompare.Contains(automationId, CultureInfo.CurrentCulture, CompareOptions.IgnoreCase); + } + + /// + /// Verifies the elements name or AutomationId based on the given partial compare. + /// + /// The element to verify. + /// The partial value to verify is the name or AutomationId. + /// True if the element's name or AutomationId partially matches; otherwise, false. + public static bool VerifyNameOrAutomationIdContains(this WindowsElement element, string partialCompare) + { + string name = element.GetName(); + string automationId = element.GetAutomationId(); + + return partialCompare.Contains(name, CultureInfo.CurrentCulture, CompareOptions.IgnoreCase) || + partialCompare.Contains(automationId, CultureInfo.CurrentCulture, CompareOptions.IgnoreCase); } } } \ No newline at end of file