Skip to content

Commit 37157a5

Browse files
authored
Add IElementFinder implementation (#27)
* Add IElementFinder to resolve #23
1 parent 0daefee commit 37157a5

File tree

2 files changed

+130
-0
lines changed

2 files changed

+130
-0
lines changed
Lines changed: 99 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,99 @@
1+
using System;
2+
using System.Collections.Generic;
3+
using System.Collections.ObjectModel;
4+
using System.Linq;
5+
using System.Threading;
6+
using Aquality.Selenium.Browsers;
7+
using Aquality.Selenium.Configurations;
8+
using Aquality.Selenium.Elements.Interfaces;
9+
using Aquality.Selenium.Waitings;
10+
using OpenQA.Selenium;
11+
12+
namespace Aquality.Selenium.Elements
13+
{
14+
internal sealed class ElementFinder : IElementFinder
15+
{
16+
private static readonly ThreadLocal<ElementFinder> InstanceHolder = new ThreadLocal<ElementFinder>();
17+
18+
private ElementFinder()
19+
{
20+
}
21+
22+
public static ElementFinder Instance
23+
{
24+
get
25+
{
26+
if (!InstanceHolder.IsValueCreated)
27+
{
28+
InstanceHolder.Value = new ElementFinder();
29+
}
30+
31+
return InstanceHolder.Value;
32+
}
33+
}
34+
35+
private ITimeoutConfiguration TimeoutConfiguration => Configuration.Instance.TimeoutConfiguration;
36+
37+
private TimeSpan DefaultTimeout => TimeoutConfiguration.Condition;
38+
39+
private Browser Browser => BrowserManager.Browser;
40+
41+
public IWebElement FindElement(By locator, TimeSpan? timeout = null, ElementState state = ElementState.ExistsInAnyState)
42+
{
43+
var clearTimeout = timeout ?? DefaultTimeout;
44+
var elements = FindElements(locator, clearTimeout, state);
45+
if (elements.Any())
46+
{
47+
return elements.First();
48+
}
49+
50+
throw new NoSuchElementException($"Element was not found in {clearTimeout.Seconds} seconds in state {state} by locator {locator}");
51+
}
52+
53+
public IWebElement FindElement(By by)
54+
{
55+
return FindElement(by, timeout: null);
56+
}
57+
58+
public ReadOnlyCollection<IWebElement> FindElements(By locator, TimeSpan? timeout = null, ElementState state = ElementState.ExistsInAnyState)
59+
{
60+
var resultElements = new List<IWebElement>();
61+
Browser.ImplicitWaitTimeout = TimeSpan.Zero;
62+
ConditionalWait.WaitForTrue(driver =>
63+
{
64+
var foundElements = driver.FindElements(locator);
65+
var filteredElements = FilterByState(foundElements, state);
66+
resultElements.AddRange(filteredElements);
67+
return filteredElements.Any();
68+
}, timeout ?? DefaultTimeout);
69+
Browser.ImplicitWaitTimeout = TimeoutConfiguration.Implicit;
70+
return resultElements.ToList().AsReadOnly();
71+
}
72+
73+
private IList<IWebElement> FilterByState(IList<IWebElement> foundElements, ElementState state)
74+
{
75+
var filteredElements = new List<IWebElement>();
76+
if (foundElements.Any())
77+
{
78+
switch (state)
79+
{
80+
case ElementState.Displayed:
81+
filteredElements.AddRange(foundElements.Where(element => element.Displayed));
82+
break;
83+
case ElementState.ExistsInAnyState:
84+
filteredElements.AddRange(foundElements);
85+
break;
86+
default:
87+
throw new InvalidOperationException($"{state} state is not recognized");
88+
}
89+
}
90+
91+
return filteredElements;
92+
}
93+
94+
public ReadOnlyCollection<IWebElement> FindElements(By by)
95+
{
96+
return FindElements(by, timeout: null);
97+
}
98+
}
99+
}
Lines changed: 31 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,31 @@
1+
using OpenQA.Selenium;
2+
using System;
3+
using System.Collections.ObjectModel;
4+
5+
namespace Aquality.Selenium.Elements.Interfaces
6+
{
7+
/// <summary>
8+
/// Provides ability to find elements in desired ElementState
9+
/// </summary>
10+
public interface IElementFinder : ISearchContext
11+
{
12+
/// <summary>
13+
/// Finds elements in desired ElementState
14+
/// </summary>
15+
/// <param name="locator">elements locator</param>
16+
/// <param name="timeout">timeout for search</param>
17+
/// <param name="state">desired ElementState</param>
18+
/// <returns>List of found elements</returns>
19+
ReadOnlyCollection<IWebElement> FindElements(By locator, TimeSpan? timeout = null, ElementState state = ElementState.ExistsInAnyState);
20+
21+
/// <summary>
22+
/// Finds element in desired ElementState
23+
/// </summary>
24+
/// <param name="locator">elements locator</param>
25+
/// <param name="timeout">timeout for search</param>
26+
/// <param name="state">desired ElementState</param>
27+
/// <exception cref="OpenQA.Selenium.NoSuchElementException">Thrown if element was not found in time in desired state</exception>
28+
/// <returns>Found element</returns>
29+
IWebElement FindElement(By locator, TimeSpan? timeout = null, ElementState state = ElementState.ExistsInAnyState);
30+
}
31+
}

0 commit comments

Comments
 (0)