Skip to content
Merged
Show file tree
Hide file tree
Changes from 3 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
99 changes: 99 additions & 0 deletions Aquality.Selenium/src/Aquality.Selenium/Elements/ElementFinder.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,99 @@
using System;
using System.Collections.Generic;
using System.Collections.ObjectModel;
using System.Linq;
using System.Threading;
using Aquality.Selenium.Browsers;
using Aquality.Selenium.Configurations;
using Aquality.Selenium.Elements.Interfaces;
using Aquality.Selenium.Waitings;
using OpenQA.Selenium;

namespace Aquality.Selenium.Elements
{
internal sealed class ElementFinder : IElementFinder
{
private static readonly ThreadLocal<ElementFinder> InstanceHolder = new ThreadLocal<ElementFinder>();

private ElementFinder()
{
}

public static ElementFinder Instance
{
get
{
if (!InstanceHolder.IsValueCreated)
{
InstanceHolder.Value = new ElementFinder();
}

return InstanceHolder.Value;
}
}

private ITimeoutConfiguration TimeoutConfiguration => Configuration.Instance.TimeoutConfiguration;

private TimeSpan DefaultTimeout => TimeoutConfiguration.Condition;

private Browser Browser => BrowserManager.Browser;

public IWebElement FindElement(By locator, TimeSpan? timeout = null, ElementState state = ElementState.ExistsInAnyState)
{
var clearTimeout = timeout ?? DefaultTimeout;
var elements = FindElements(locator, clearTimeout, state);
if (elements.Any())
{
return elements.First();
}

throw new NoSuchElementException($"Element was not found in {clearTimeout.Seconds} seconds in state {state} by locator {locator}");
}

public IWebElement FindElement(By by)
{
return FindElement(by, timeout: null);
}

public ReadOnlyCollection<IWebElement> FindElements(By locator, TimeSpan? timeout = null, ElementState state = ElementState.ExistsInAnyState)
{
var resultElements = new List<IWebElement>();
Browser.ImplicitWaitTimeout = TimeSpan.Zero;
ConditionalWait.WaitForTrue(driver =>
{
var foundElements = driver.FindElements(locator);
var filteredElements = FilterByState(foundElements, state);
resultElements.AddRange(filteredElements);
return filteredElements.Any();
}, timeout ?? DefaultTimeout);
Browser.ImplicitWaitTimeout = TimeoutConfiguration.Implicit;
return resultElements.ToList().AsReadOnly();
}

private IList<IWebElement> FilterByState(IList<IWebElement> foundElements, ElementState state)
{
var filteredElements = new List<IWebElement>();
if (foundElements.Any())
{
switch (state)
{
case ElementState.Displayed:
filteredElements.AddRange(foundElements.Where(element => element.Displayed));
break;
case ElementState.ExistsInAnyState:
filteredElements.AddRange(foundElements);
break;
default:
throw new InvalidOperationException($"{state} state is not recognized");
}
}

return filteredElements;
}

public ReadOnlyCollection<IWebElement> FindElements(By by)
{
return FindElements(by, timeout: null);
}
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
using OpenQA.Selenium;
using System;
using System.Collections.ObjectModel;

namespace Aquality.Selenium.Elements.Interfaces
{
/// <summary>
/// Provides ability to find elements in desired ElementState
/// </summary>
public interface IElementFinder : ISearchContext
{
/// <summary>
/// Finds elements in desired ElementState
/// </summary>
/// <param name="locator">elements locator</param>
/// <param name="timeout">timeout for search</param>
/// <param name="state">desired ElementState</param>
/// <returns>List of found elements</returns>
ReadOnlyCollection<IWebElement> FindElements(By locator, TimeSpan? timeout = null, ElementState state = ElementState.ExistsInAnyState);

/// <summary>
/// Finds element in desired ElementState
/// </summary>
/// <param name="locator">elements locator</param>
/// <param name="timeout">timeout for search</param>
/// <param name="state">desired ElementState</param>
/// <exception cref="OpenQA.Selenium.NoSuchElementException">Thrown if element was not found in time in desired state</exception>
/// <returns></returns>
IWebElement FindElement(By locator, TimeSpan? timeout = null, ElementState state = ElementState.ExistsInAnyState);
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ namespace Aquality.Selenium.Waitings
{
public static class ConditionalWait
{
public static bool WaitForTrue(Func<IWebDriver, bool> condition)
public static bool WaitForTrue(Func<IWebDriver, bool> condition, TimeSpan? timeout = null)
{
throw new NotImplementedException();
}
Expand Down