Skip to content

Commit 45c2f40

Browse files
authored
[Feature] Add multichoice combobox +semver: feature (#233)
* [Feature] Add multichoice combobox +semver: feature * Implement MultiChoiceBox tests, fixed logic in ComboBox and documentation * Fix bug in ComboBox selectByContains method, and coding issues. Add localization values for logging * add cookies dialog waiting * Make multichoise box tests non-parallelizable to reduce web resource load * remove textbox highlighting from test * stabilize LocationForm
1 parent cd1abcc commit 45c2f40

File tree

15 files changed

+494
-21
lines changed

15 files changed

+494
-21
lines changed

Aquality.Selenium/src/Aquality.Selenium/Aquality.Selenium.xml

Lines changed: 71 additions & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

Aquality.Selenium/src/Aquality.Selenium/Elements/ComboBox.cs

Lines changed: 16 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@
33
using Aquality.Selenium.Elements.Interfaces;
44
using OpenQA.Selenium;
55
using OpenQA.Selenium.Support.UI;
6+
using System;
67
using System.Collections.Generic;
78
using System.Linq;
89

@@ -68,38 +69,35 @@ public IList<string> Values
6869
public void SelectByContainingText(string text)
6970
{
7071
LogElementAction("loc.combobox.select.by.text", text);
71-
DoWithRetry(() =>
72-
{
73-
var select = new SelectElement(GetElement());
74-
foreach (var element in select.Options)
75-
{
76-
var elementText = element.Text;
77-
if (elementText.ToLower().Contains(text.ToLower()))
78-
{
79-
select.SelectByText(elementText);
80-
return;
81-
}
82-
}
83-
throw new InvalidElementStateException($"Failed to select option that contains text {text}");
84-
});
72+
ApplyFunctionToOptionsThatContain(element => element.Text, (select, option) => select.SelectByText(option), text);
8573
}
8674

8775
public void SelectByContainingValue(string value)
8876
{
8977
LogElementAction("loc.selecting.value", value);
78+
ApplyFunctionToOptionsThatContain(
79+
element => element.GetAttribute(Attributes.Value), (select, option) => select.SelectByValue(option), value);
80+
}
81+
82+
protected void ApplyFunctionToOptionsThatContain(Func<IWebElement, string> getValueFunction, Action<SelectElement, string> selectFunction, string value)
83+
{
9084
DoWithRetry(() =>
9185
{
9286
var select = new SelectElement(GetElement());
87+
var isSelected = false;
9388
foreach (var element in select.Options)
9489
{
95-
var elementValue = element.GetAttribute(Attributes.Value);
90+
var elementValue = getValueFunction(element);
9691
if (elementValue.ToLower().Contains(value.ToLower()))
9792
{
98-
select.SelectByValue(elementValue);
99-
return;
93+
selectFunction(select, elementValue);
94+
isSelected = true;
10095
}
10196
}
102-
throw new InvalidElementStateException($"Failed to select option that contains value {value}");
97+
if (!isSelected)
98+
{
99+
throw new InvalidElementStateException($"Failed to find option that contains [{value}]");
100+
}
103101
});
104102
}
105103

Aquality.Selenium/src/Aquality.Selenium/Elements/ElementFactory.cs

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -47,6 +47,11 @@ public IComboBox GetComboBox(By locator, string name, ElementState state = Eleme
4747
return ResolveSupplier<IComboBox>()(locator, name, state);
4848
}
4949

50+
public IMultiChoiceBox GetMultiChoiceBox(By locator, string name, ElementState state = ElementState.Displayed)
51+
{
52+
return ResolveSupplier<IMultiChoiceBox>()(locator, name, state);
53+
}
54+
5055
public ILabel GetLabel(By locator, string name, ElementState state = ElementState.Displayed)
5156
{
5257
return ResolveSupplier<ILabel>()(locator, name, state);
@@ -105,6 +110,7 @@ protected override IDictionary<Type, Type> ElementTypesMap
105110
{ typeof(IButton), typeof(Button) },
106111
{ typeof(ICheckBox), typeof(CheckBox) },
107112
{ typeof(IComboBox), typeof(ComboBox) },
113+
{ typeof(IMultiChoiceBox), typeof(MultiChoiceBox) },
108114
{ typeof(ILabel), typeof(Label) },
109115
{ typeof(ILink), typeof(Link) },
110116
{ typeof(IRadioButton), typeof(RadioButton) },

Aquality.Selenium/src/Aquality.Selenium/Elements/Interfaces/IElementFactory.cs

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -36,6 +36,15 @@ public interface IElementFactory : ICoreElementFactory
3636
/// <returns>Instance of element that implements IComboBox interface</returns>
3737
IComboBox GetComboBox(By locator, string name, ElementState state = ElementState.Displayed);
3838

39+
/// <summary>
40+
/// Creates element that implements IMultiChoiceBox interface.
41+
/// </summary>
42+
/// <param name="locator">Element locator</param>
43+
/// <param name="name">Element name</param>
44+
/// <param name="state">Element state</param>
45+
/// <returns>Instance of element that implements IMultiChoiceBox interface</returns>
46+
IMultiChoiceBox GetMultiChoiceBox(By locator, string name, ElementState state = ElementState.Displayed);
47+
3948
/// <summary>
4049
/// Creates element that implements ILabel interface.
4150
/// </summary>
Lines changed: 62 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,62 @@
1+
using System.Collections.Generic;
2+
3+
namespace Aquality.Selenium.Elements.Interfaces
4+
{
5+
/// <summary>
6+
/// Describes behavior of MultiChoice ComboBox UI element.
7+
/// </summary>
8+
public interface IMultiChoiceBox : IComboBox
9+
{
10+
/// <summary>
11+
/// Gets value of all selected options.
12+
/// </summary>
13+
/// <value>Selected values.</value>
14+
IList<string> SelectedValues { get; }
15+
16+
/// <summary>
17+
/// Gets text of all selected options.
18+
/// </summary>
19+
/// <value>Selected texts.</value>
20+
IList<string> SelectedTexts { get; }
21+
22+
/// <summary>
23+
/// Select all options
24+
/// </summary>
25+
void SelectAll();
26+
27+
/// <summary>
28+
/// De-select all options
29+
/// </summary>
30+
void DeselectAll();
31+
32+
/// <summary>
33+
/// De-select selected option by index
34+
/// </summary>
35+
/// <param name="index">Number of selected option.</param>
36+
void DeselectByIndex(int index);
37+
38+
/// <summary>
39+
/// De-select selected option by value.
40+
/// </summary>
41+
/// <param name="value">Option value.</param>
42+
void DeselectByValue(string value);
43+
44+
/// <summary>
45+
/// De-select selected option by containing value.
46+
/// </summary>
47+
/// <param name="value">Partial option's value.</param>
48+
void DeselectByContainingValue(string value);
49+
50+
/// <summary>
51+
/// De-select selected option by visible text.
52+
/// </summary>
53+
/// <param name="text">Text to be deselected.</param>
54+
void DeselectByText(string text);
55+
56+
/// <summary>
57+
/// De-select selected option by containing visible text.
58+
/// </summary>
59+
/// <param name="text">Partial option's text.</param>
60+
void DeselectByContainingText(string text);
61+
}
62+
}
Lines changed: 93 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,93 @@
1+
using Aquality.Selenium.Core.Elements;
2+
using Aquality.Selenium.Elements.Interfaces;
3+
using OpenQA.Selenium;
4+
using OpenQA.Selenium.Support.UI;
5+
using System.Collections.Generic;
6+
using System.Linq;
7+
8+
namespace Aquality.Selenium.Elements
9+
{
10+
/// <summary>
11+
/// Defines MultiChoiceBox UI element.
12+
/// </summary>
13+
public class MultiChoiceBox : ComboBox, IMultiChoiceBox
14+
{
15+
private const string LocDeselectingValue = "loc.deselecting.value";
16+
17+
protected internal MultiChoiceBox(By locator, string name, ElementState state) : base(locator, name, state)
18+
{
19+
}
20+
21+
protected override string ElementType => LocalizationManager.GetLocalizedMessage("loc.multichoicebox");
22+
23+
public IList<string> SelectedValues
24+
{
25+
get
26+
{
27+
LogElementAction("loc.combobox.getting.selected.value");
28+
var values = DoWithRetry(() => new SelectElement(GetElement()).AllSelectedOptions.Select(option => option.GetAttribute(Attributes.Value)).ToList());
29+
LogElementAction("loc.combobox.selected.value", string.Join(", ", values.Select(value => $"'{value}'")));
30+
return values;
31+
}
32+
}
33+
34+
public IList<string> SelectedTexts
35+
{
36+
get
37+
{
38+
LogElementAction("loc.combobox.getting.selected.text");
39+
var texts = DoWithRetry(() => new SelectElement(GetElement()).AllSelectedOptions.Select(option => option.Text).ToList());
40+
LogElementAction("loc.combobox.selected.text", string.Join(", ", texts.Select(value => $"'{value}'")));
41+
return texts;
42+
}
43+
}
44+
45+
public void DeselectAll()
46+
{
47+
LogElementAction("loc.multichoicebox.deselect.all");
48+
DoWithRetry(() => new SelectElement(GetElement()).DeselectAll());
49+
}
50+
51+
public void DeselectByContainingText(string text)
52+
{
53+
LogElementAction("loc.multichoicebox.deselect.by.text", text);
54+
ApplyFunctionToOptionsThatContain(element => element.Text,
55+
(select, option) => select.DeselectByText(option),
56+
text);
57+
}
58+
59+
public void DeselectByContainingValue(string value)
60+
{
61+
LogElementAction(LocDeselectingValue, value);
62+
ApplyFunctionToOptionsThatContain(element => element.GetAttribute(Attributes.Value),
63+
(select, option) => select.DeselectByValue(option),
64+
value);
65+
}
66+
67+
public void DeselectByIndex(int index)
68+
{
69+
LogElementAction(LocDeselectingValue, $"#{index}");
70+
DoWithRetry(() => new SelectElement(GetElement()).DeselectByIndex(index));
71+
}
72+
73+
public void DeselectByText(string text)
74+
{
75+
LogElementAction("loc.multichoicebox.deselect.by.text", text);
76+
DoWithRetry(() => new SelectElement(GetElement()).DeselectByText(text));
77+
}
78+
79+
public void DeselectByValue(string value)
80+
{
81+
LogElementAction(LocDeselectingValue, value);
82+
DoWithRetry(() => new SelectElement(GetElement()).DeselectByValue(value));
83+
}
84+
85+
public void SelectAll()
86+
{
87+
LogElementAction("loc.multichoicebox.select.all");
88+
ApplyFunctionToOptionsThatContain(element => element.GetAttribute(Attributes.Value),
89+
(select, value) => select.SelectByValue(value),
90+
string.Empty);
91+
}
92+
}
93+
}

Aquality.Selenium/src/Aquality.Selenium/Resources/Localization/be.json

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -41,6 +41,10 @@
4141
"loc.combobox.get.text.js": "Атрымліваем выбраны тэкст праз JavaScript",
4242
"loc.combobox.texts": "Спіс тэкстаў опцыяў: [{0}]",
4343
"loc.combobox.values": "Спіс значэнняў: [{0}]",
44+
"loc.multichoicebox": "Камбабокс з мульцівыбарам",
45+
"loc.multichoicebox.select.all": "Выбіраем усе значэнні",
46+
"loc.multichoicebox.deselect.all": "Адмяняем выбар усіх значэнняў",
47+
"loc.multichoicebox.deselect.by.text": "Адмяняем выбар значэння з тэкстам '{0}'",
4448
"loc.el.getattr": "Атрымліваем атрыбут '{0}'",
4549
"loc.el.attr.value": "Значэнне атрыбута '{0}': [{1}]",
4650
"loc.el.attr.set": "Задаем значэнне атрыбута '{0}': [{1}]",
@@ -64,6 +68,7 @@
6468
"loc.scrolling.center.js": "Пракручваем старонку да цэнтра элемента праз JavaScript",
6569
"loc.scrolling.js": "Пракручваем старонку праз JavaScript",
6670
"loc.selecting.value": "Выбіраем значэнне - '{0}'",
71+
"loc.deselecting.value": "Адмяняем выбар значэння - '{0}'",
6772
"loc.send.text": "Задаем тэкст - '{0}'",
6873
"loc.setting.value": "Задаем значэнне - '{0}'",
6974
"loc.text.clearing": "Ачышчаем",

Aquality.Selenium/src/Aquality.Selenium/Resources/Localization/en.json

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -41,6 +41,10 @@
4141
"loc.combobox.get.text.js": "Getting selected text via JavaScript",
4242
"loc.combobox.texts": "Option texts: [{0}]",
4343
"loc.combobox.values": "Option values: [{0}]",
44+
"loc.multichoicebox": "Multi-choice ComboBox",
45+
"loc.multichoicebox.select.all": "Select all",
46+
"loc.multichoicebox.deselect.all": "Deselect all",
47+
"loc.multichoicebox.deselect.by.text": "Deselecting value by text '{0}'",
4448
"loc.el.getattr": "Getting attribute '{0}'",
4549
"loc.el.attr.value": "Value of attribute '{0}': [{1}]",
4650
"loc.el.attr.set": "Setting value of attribute '{0}': [{1}]",
@@ -64,6 +68,7 @@
6468
"loc.scrolling.center.js": "Scrolling to the center via JavaScript",
6569
"loc.scrolling.js": "Scrolling via JavaScript",
6670
"loc.selecting.value": "Selecting value - '{0}'",
71+
"loc.deselecting.value": "Deselecting value - '{0}'",
6772
"loc.send.text": "Setting text - '{0}'",
6873
"loc.setting.value": "Setting value - '{0}'",
6974
"loc.text.clearing": "Clearing",

0 commit comments

Comments
 (0)