diff --git a/Behavioral.Automation.Template/Behavioral.Automation.Template.Bindings/ElementWrappers/TextElementWrapper.cs b/Behavioral.Automation.Template/Behavioral.Automation.Template.Bindings/ElementWrappers/TextElementWrapper.cs index bcdc8a9d..6d7e7699 100644 --- a/Behavioral.Automation.Template/Behavioral.Automation.Template.Bindings/ElementWrappers/TextElementWrapper.cs +++ b/Behavioral.Automation.Template/Behavioral.Automation.Template.Bindings/ElementWrappers/TextElementWrapper.cs @@ -27,6 +27,7 @@ public void ClearInput() new AssertionBehavior(AssertionType.Continuous, false), $"{Caption} is not enabled"); + Element.Clear(); while (Element.GetAttribute("value").Length > 0) { Element.SendKeys(Keys.Backspace); diff --git a/Behavioral.Automation.Template/Behavioral.Automation.Template.Bindings/ElementWrappers/WebElementWrapper.cs b/Behavioral.Automation.Template/Behavioral.Automation.Template.Bindings/ElementWrappers/WebElementWrapper.cs index 27e19e7b..3e549e52 100644 --- a/Behavioral.Automation.Template/Behavioral.Automation.Template.Bindings/ElementWrappers/WebElementWrapper.cs +++ b/Behavioral.Automation.Template/Behavioral.Automation.Template.Bindings/ElementWrappers/WebElementWrapper.cs @@ -5,18 +5,20 @@ using System; using System.Collections.Generic; using System.Diagnostics.CodeAnalysis; +using System.Linq; +using System.Text.RegularExpressions; namespace Behavioral.Automation.Template.Bindings.ElementWrappers { public class WebElementWrapper : IWebElementWrapper { private readonly Func _elementSelector; - private readonly IDriverService _driverService; - public WebElementWrapper([NotNull] Func elementSelector, [NotNull] string caption, [NotNull] IDriverService driverService) + public WebElementWrapper([NotNull] Func elementSelector, [NotNull] string caption, + [NotNull] IDriverService driverService) { _elementSelector = elementSelector; - _driverService = driverService; + Driver = driverService; Caption = caption; } @@ -24,21 +26,51 @@ public WebElementWrapper([NotNull] Func elementSelector, [NotNull] public IWebElement Element => _elementSelector(); - public string Text => Element.Text; + public string Text + { + get + { + try + { + return Regex.Replace(Element.Text, @"\t|\n|\r", " ").Replace(" ", " "); + } + catch (Exception e) when (e is NullReferenceException or StaleElementReferenceException) + { + return string.Empty; + } + } + } - public string GetAttribute(string attribute) => Element.GetAttribute(attribute); + public string GetAttribute(string attribute) + { + try + { + return Element.GetAttribute(attribute); + } + catch (Exception e) when (e is NullReferenceException or StaleElementReferenceException) + { + return null; + } + } public void Click() { - MouseHover(); - Assert.ShouldGet(() => Enabled); - _driverService.MouseClick(); + Assert.ShouldBecome(() => Enabled, true, $"Unable to click on {Caption}. The element was disabled"); + try + { + Element.Click(); + } + catch (ElementClickInterceptedException) + { + MouseHover(); + Driver.MouseClick(); + } } public void MouseHover() { - Assert.ShouldBecome(() => Enabled, true, $"{Caption} is disabled"); - _driverService.ScrollTo(Element); + Assert.ShouldBecome(() => Displayed, true, $"{Caption} is not visible"); + Driver.ScrollTo(Element); } public void SendKeys(string text) @@ -47,29 +79,25 @@ public void SendKeys(string text) Element.SendKeys(text); } - public bool Displayed => Element != null && Element.Displayed; - - public bool Enabled => Displayed && Element.Enabled && AriaEnabled; - - public string Tooltip + public bool Displayed { get { - var matTooltip = GetAttribute("matTooltip"); - if (matTooltip != null) + try { - return matTooltip; + return Element is not null && Element.Displayed; } - var ngReflectTip = GetAttribute("ng-reflect-message"); //some elements have their tooltips' texts stored inside 'ng-reflect-message' attribute - if (ngReflectTip != null) + catch (Exception e) when (e is NullReferenceException or StaleElementReferenceException) { - return ngReflectTip; + return false; } - - return GetAttribute("aria-label"); //some elements have their tooltips' texts stored inside 'aria-label' attribute } } + public bool Enabled => Displayed && Element.Enabled; + + public string Tooltip => GetAttribute("data-test-tooltip-text"); + public bool Stale { get @@ -80,7 +108,7 @@ public bool Stale var elementEnabled = Element.Enabled; return false; } - catch (StaleElementReferenceException) + catch (Exception e) when (e is NullReferenceException or StaleElementReferenceException) { return true; } @@ -89,34 +117,22 @@ public bool Stale public IEnumerable FindSubElements(By locator, string caption) { - var elements = Assert.ShouldGet(() => Element.FindElements(locator)); - return ElementsToWrappers(elements, caption); - } - - private IEnumerable ElementsToWrappers(IEnumerable elements, string caption) - { - foreach (var element in elements) + try { - var wrapper = new WebElementWrapper(() => element, caption, _driverService); - yield return wrapper; + return ElementsToWrappers(Assert.ShouldGet(() => Element.FindElements(locator)), caption); + } + catch (Exception e) when (e is NullReferenceException or InvalidOperationException) + { + NUnit.Framework.Assert.Fail($"Couldn't find elements with {caption}"); + return null; } } - protected IDriverService Driver => _driverService; - - private bool AriaEnabled + private IEnumerable ElementsToWrappers(IEnumerable elements, string caption) { - get - { - switch (Element.GetAttribute("aria-disabled")) - { - case null: - case "false": - return true; - } - - return false; - } + return elements.Select(element => new WebElementWrapper(() => element, caption, Driver)); } + + protected IDriverService Driver { get; } } } diff --git a/CHANGELOG.md b/CHANGELOG.md index 5f8bfbac..88c6910d 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -4,11 +4,5 @@ All notable changes to this project will be documented in this file. The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/), and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html). -[1.8.6] - 2022-01-25 -### Fixed -- Error when calling Aggregate() to generate message for DropdownWrapper - -[1.8.5] - 2022-01-27 -### Changed -- Bindings code refactoring -- Updated Specflow package version \ No newline at end of file +[1.8.7] - 2022-02-25 +- Moved tooltip attribute to separate interface \ No newline at end of file diff --git a/src/Behavioral.Automation/Behavioral.Automation.csproj b/src/Behavioral.Automation/Behavioral.Automation.csproj index fec60278..df83f038 100644 --- a/src/Behavioral.Automation/Behavioral.Automation.csproj +++ b/src/Behavioral.Automation/Behavioral.Automation.csproj @@ -16,7 +16,7 @@ The whole automation code is divided into the following parts: - UI structure descriptive code - Supportive code Quantori Inc. - 1.8.6 + 1.8.7 https://github.com/quantori/Behavioral.Automation true true diff --git a/src/Behavioral.Automation/Bindings/LabelBinding.cs b/src/Behavioral.Automation/Bindings/LabelBinding.cs index 5546c7c5..77b9589b 100644 --- a/src/Behavioral.Automation/Bindings/LabelBinding.cs +++ b/src/Behavioral.Automation/Bindings/LabelBinding.cs @@ -8,8 +8,8 @@ namespace Behavioral.Automation.Bindings { - /// - /// Bindings for labels or other text elements testing + /// + /// Bindings for labels or other text elements testing /// [Binding] public sealed class LabelBinding @@ -23,18 +23,18 @@ public LabelBinding([NotNull] RunnerService runnerService, [NotNull] ScenarioCon _scenarioContext = scenarioContext; } - /// - /// Check that element's text is equal to the expected one - /// - /// Tested web element wrapper - /// Assertion behavior (instant or continuous) + /// + /// Check that element's text is equal to the expected one + /// + /// Tested web element wrapper + /// Assertion behavior (instant or continuous) /// Expected value /// Then "Test" element text should be "expected text" [Given("the (.*?) text (is|is not|become|become not) \"(.*)\"")] [Then("the (.*?) text should (be|be not|become|become not) \"(.*)\"")] public void CheckSelectedText( - [NotNull] IWebElementWrapper element, - [NotNull] AssertionBehavior behavior, + [NotNull] IWebElementWrapper element, + [NotNull] AssertionBehavior behavior, [NotNull] string value) { Assert.ShouldBecome(() => StringExtensions.GetElementTextOrValue(element), value, behavior, @@ -68,7 +68,7 @@ public void CheckSelectedTextContain( /// Then the "Test" element should have tooltip with text "expected string" [Then("the (.*?) should (have|not have) tooltip with text \"(.*)\"")] public void CheckElementTooltip( - [NotNull] IWebElementWrapper element, + [NotNull] ITooltipElementWrapper element, [NotNull] AssertionBehavior behavior, [NotNull] string value) { @@ -88,8 +88,8 @@ public void CheckElementIsEmpty([NotNull] IWebElementWrapper element, AssertionB { Assert.ShouldBecome(() => StringExtensions.GetElementTextOrValue(element), string.Empty, behavior, $"{element.Caption} text is \"{StringExtensions.GetElementTextOrValue(element)}\""); - } - + } + /// /// Check that multiple elements' texts are empty /// diff --git a/src/Behavioral.Automation/Elements/ITooltipElementWrapper.cs b/src/Behavioral.Automation/Elements/ITooltipElementWrapper.cs new file mode 100644 index 00000000..0e816d84 --- /dev/null +++ b/src/Behavioral.Automation/Elements/ITooltipElementWrapper.cs @@ -0,0 +1,10 @@ +namespace Behavioral.Automation.Elements +{ + public interface ITooltipElementWrapper : IWebElementWrapper + { + /// + /// Message that appears when mouse is hovered over element + /// + public string Tooltip { get; } + } +} \ No newline at end of file diff --git a/src/Behavioral.Automation/Elements/IWebElementWrapper.cs b/src/Behavioral.Automation/Elements/IWebElementWrapper.cs index 86a7b61d..a16234e5 100644 --- a/src/Behavioral.Automation/Elements/IWebElementWrapper.cs +++ b/src/Behavioral.Automation/Elements/IWebElementWrapper.cs @@ -65,11 +65,6 @@ public interface IWebElementWrapper /// public bool Enabled { get; } - /// - /// Message that appears when mouse is hovered over element - /// - public string Tooltip { get; } - /// /// Element staleness. See ///