Skip to content

Commit 3e5e72e

Browse files
PandaMagnusCurn, MikeKeboo
authored
Fix fetching many elemhandlers (#152)
* Work on being able to dynamically declare the index location in GetElementHandlers Co-authored-by: Kevin B <Keboo@users.noreply.github.com> * Update XML summary and make one additional change from PR feedback --------- Co-authored-by: Curn, Mike <Mike.Curn@avistacorp.com> Co-authored-by: Kevin B <Keboo@users.noreply.github.com>
1 parent 76411c4 commit 3e5e72e

2 files changed

Lines changed: 73 additions & 10 deletions

File tree

IntelliTect.TestTools.Selenate.Tests/GetElementHandlersTests.cs

Lines changed: 53 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -66,7 +66,7 @@ public void VerifyByXPathDoesNotChangeFormat()
6666
public void GetElementHandlersWorksWithAllSelectorTypes(string selectorType)
6767
{
6868
const string cssIndex = ":nth-of-type";
69-
List<By> convertedBys = new();
69+
List<By> convertedBys = new(2);
7070

7171
for (int i = 1; i < 3; i++)
7272
{
@@ -114,6 +114,58 @@ public void GetElementHandlersWorksWithAllSelectorTypes(string selectorType)
114114
Assert.Single(elementHandlers);
115115
}
116116

117+
[Theory]
118+
[InlineData("css", "div[id='test']>div", "div[id='test']>div:nth-of-type({index})")]
119+
[InlineData("css", "div[id='test']{index}>div", "div[id='test']:nth-of-type({index})>div")]
120+
[InlineData("xpath", "//div[@id='test']/div", "//div[@id='test']/div[{index}]")]
121+
[InlineData("xpath", "//div[@id='test']{index}/div", "//div[@id='test'][{index}]/div")]
122+
public void GetElementHandlersWorksWithAllSelectorTypesTest(string selectorType, string selectorCriteria, string expectedResult)
123+
{
124+
List<By> convertedBys = new(2);
125+
126+
for (int i = 1; i < 3; i++)
127+
{
128+
convertedBys.Add(selectorType switch
129+
{
130+
"css" => By.CssSelector(expectedResult.Replace("{index}", i.ToString())),
131+
"xpath" => By.XPath(expectedResult.Replace("{index}", i.ToString())),
132+
_ => throw new ArgumentException($"Please add support for this selector type: {selectorType}")
133+
});
134+
}
135+
136+
By by = selectorType switch
137+
{
138+
"css" => By.CssSelector(selectorCriteria),
139+
"xpath" => By.XPath(selectorCriteria),
140+
_ => throw new ArgumentException($"Please add support for this selector type: {selectorType}")
141+
};
142+
143+
var mockElement1 = new Mock<IWebElement>();
144+
mockElement1.SetupGet(e1 => e1.Text).Returns("Testing1");
145+
mockElement1.SetupGet(e1 => e1.Displayed).Returns(true);
146+
147+
var mockElement2 = new Mock<IWebElement>();
148+
mockElement2.SetupGet(e2 => e2.Text).Returns("Testing2");
149+
mockElement2.SetupGet(e2 => e2.Displayed).Returns(false);
150+
151+
var mockDriver = new Mock<IWebDriver>();
152+
mockDriver.Setup
153+
(f => f.FindElement(convertedBys[0]))
154+
.Returns(mockElement1.Object);
155+
156+
mockDriver.Setup
157+
(f => f.FindElement(convertedBys[1]))
158+
.Returns(mockElement2.Object);
159+
160+
ElementsHandler handler = new(mockDriver.Object, By.CssSelector("div#test"));
161+
IEnumerable<ElementHandler> elementHandlers = handler
162+
.SetTimeout(TimeSpan.FromMilliseconds(20))
163+
.GetElementHandlers(by);
164+
165+
var elementHandler = Assert.Single(elementHandlers);
166+
Assert.Equal(convertedBys[0].Criteria, elementHandler.Locator.Criteria);
167+
}
168+
117169
[Theory]
118170
[InlineData("tagname")]
119171
[InlineData("link")]

IntelliTect.TestTools.Selenate/ElementsHandler.cs

Lines changed: 20 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -104,32 +104,43 @@ public bool ContainsText(string text)
104104
}
105105

106106
/// <summary>
107-
/// Returns an ElementHandler as long as a matching DOM item is found, based on XPath or CSS index.
107+
/// Returns an ElementHandler as long as a matching DOM item is found, based on XPath or CSS index. <br />
108+
/// Note that if your locator does not have '{index}' in it, one will be appended to the end. <br />
109+
/// E.G. The locator By.CssSelector("div>div") will become By.CssSelector("div>div:nth-of-type(1)") <br />
110+
/// and By.CssSelector("div{index}>div") will become By.CssSelector("div:nth-of-type(1)>div") <br /> <br />
108111
/// Please ensure at least two elements can be found when attempting to use this method. <br />
109-
/// Respects any timeout set for this ElementsHandler. <br />
112+
/// Respects any timeout set for this ElementsHandler. <br /> <br />
110113
/// NOTE: By.Name locators have not yet been verified to work. Please file an issue if one is encountered: https://github.com/IntelliTect/TestTools.Selenate/issues
111114
/// </summary>
115+
/// <param name="byOverride">Used to override the locator only for this operation. This is primarily used when your regular locator <br />
116+
/// is needed for other operations, but you must specify where the indexing call needs to go for this specific operation.</param>
112117
/// <returns>The enumerable of ElementHandlers that exist at the time of invocation.</returns>
113-
public IEnumerable<ElementHandler> GetElementHandlers()
118+
public IEnumerable<ElementHandler> GetElementHandlers(By? byOverride = null)
114119
{
115120
// DOM elements are 1-based indexes
116121
int iteration = 1;
117-
122+
By locator = byOverride ?? Locator;
123+
string locatorCriteria = locator.Criteria;
124+
if (!locatorCriteria.Contains("{index}"))
125+
{
126+
locatorCriteria = $"{locatorCriteria}{{index}}";
127+
}
128+
118129
do
119130
{
120131
By by;
121-
if (Locator.Mechanism is "css selector")
132+
if (locator.Mechanism is "css selector")
122133
{
123-
by = By.CssSelector($"{Locator.Criteria}:nth-of-type({iteration})");
134+
by = By.CssSelector(locatorCriteria.Replace("{index}", $":nth-of-type({iteration})"));
124135
}
125-
else if (Locator.Mechanism is "xpath")
136+
else if (locator.Mechanism is "xpath")
126137
{
127-
by = By.XPath($"{Locator.Criteria}[{iteration}]");
138+
by = By.XPath(locatorCriteria.Replace("{index}", $"[{iteration}]"));
128139
}
129140
else
130141
{
131142
throw new ArgumentException(
132-
$"Invalid selector type, {Locator.Mechanism} for method {nameof(GetElementHandlers)}. Please convert to any selector type other than Partial Link Text, Link Text, or Tag Name.");
143+
$"Invalid selector type, {locator.Mechanism} for method {nameof(GetElementHandlers)}. Please convert to any selector type other than Partial Link Text, Link Text, or Tag Name.");
133144
}
134145

135146
ElementHandler foundHandler = new(WrappedDriver, by);

0 commit comments

Comments
 (0)