Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[Feature] Add multichoice combobox #105

Merged
merged 11 commits into from
Feb 15, 2024
6 changes: 3 additions & 3 deletions src/main/java/aquality/selenium/elements/ComboBox.java
Original file line number Diff line number Diff line change
Expand Up @@ -49,20 +49,20 @@ public void clickAndSelectByText(String value) {
@Override
public void selectByContainingText(String text) {
logElementAction("loc.combobox.select.by.text", text);
selectOptionThatContains(WebElement::getText,
applySelectFuncToOptionThatContains(WebElement::getText,
Select::selectByVisibleText,
text);
}

@Override
public void selectByContainingValue(String value) {
logElementAction(LOG_SELECTING_VALUE, value);
selectOptionThatContains(element -> element.getAttribute(Attributes.VALUE.toString()),
applySelectFuncToOptionThatContains(element -> element.getAttribute(Attributes.VALUE.toString()),
Select::selectByValue,
value);
}

private void selectOptionThatContains(Function<WebElement, String> getValueFunc, BiConsumer<Select, String> selectFunc, String value){
protected void applySelectFuncToOptionThatContains(Function<WebElement, String> getValueFunc, BiConsumer<Select, String> selectFunc, String value){
mialeska marked this conversation as resolved.
Show resolved Hide resolved
doWithRetry(() -> {
Select select = new Select(getElement());
List<WebElement> elements = select.getOptions();
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -39,6 +39,7 @@ protected Map<Class<? extends aquality.selenium.core.elements.interfaces.IElemen
typesMap.put(IButton.class, Button.class);
typesMap.put(ICheckBox.class, CheckBox.class);
typesMap.put(IComboBox.class, ComboBox.class);
typesMap.put(IMultiChoiceComboBox.class, MultiChoiceComboBox.class);
mialeska marked this conversation as resolved.
Show resolved Hide resolved
typesMap.put(ILabel.class, Label.class);
typesMap.put(ILink.class, Link.class);
typesMap.put(IRadioButton.class, RadioButton.class);
Expand Down
1 change: 1 addition & 0 deletions src/main/java/aquality/selenium/elements/ElementType.java
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ public enum ElementType {
BUTTON(IButton.class),
CHECKBOX(ICheckBox.class),
COMBOBOX(IComboBox.class),
MULTICHOICECOMBOBOX(IMultiChoiceComboBox.class),
LABEL(ILabel.class),
LINK(ILink.class),
RADIOBUTTON(IRadioButton.class),
Expand Down
63 changes: 63 additions & 0 deletions src/main/java/aquality/selenium/elements/MultiChoiceComboBox.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,63 @@
package aquality.selenium.elements;

import aquality.selenium.core.elements.ElementState;
import aquality.selenium.elements.interfaces.IMultiChoiceComboBox;
import org.openqa.selenium.By;
import org.openqa.selenium.WebElement;
import org.openqa.selenium.support.ui.Select;

/**
* Class describing the Multi-choice ComboBox (dropdown list), i.e. the one having attribute {@code multiple} set to {@code true}
*/
public class MultiChoiceComboBox extends ComboBox implements IMultiChoiceComboBox {

private static final String LOG_DESELECTING_VALUE = "loc.deselecting.value";

protected MultiChoiceComboBox(By locator, String name, ElementState state) {
super(locator, name, state);
}

protected String getElementType() {
return getLocalizationManager().getLocalizedMessage("loc.multichoicecombobox");
}

@Override
public void deselectAll() {
logElementAction("loc.multichoicecombobox.deselect.all");
doWithRetry(() -> new Select(getElement()).deselectAll());
}

@Override
public void deselectByIndex(int index) {
logElementAction(LOG_DESELECTING_VALUE, String.format("#%s", index));
doWithRetry(() -> new Select(getElement()).deselectByIndex(index));
}

@Override
public void deselectByValue(String value) {
logElementAction(LOG_DESELECTING_VALUE, value);
doWithRetry(() -> new Select(getElement()).deselectByValue(value));
}

@Override
public void deselectByContainingValue(String value) {
logElementAction(LOG_DESELECTING_VALUE, value);
applySelectFuncToOptionThatContains(element -> element.getAttribute(Attributes.VALUE.toString()),
Select::deselectByValue,
value);
}

@Override
public void deselectByText(String text) {
logElementAction("loc.multichoicecombobox.deselect.by.text", text);
doWithRetry(() -> new Select(getElement()).deselectByVisibleText(text));
}

@Override
public void deselectByContainingText(String text) {
logElementAction("loc.multichoicecombobox.deselect.by.text", text);
applySelectFuncToOptionThatContains(WebElement::getText,
Select::deselectByVisibleText,
text);
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -80,6 +80,14 @@ default IComboBox getComboBox(By locator, String name, ElementState state) {
return get(ElementType.COMBOBOX, locator, name, state);
}

default IMultiChoiceComboBox getMultiChoiceComboBox(By locator, String name) {
return getMultiChoiceComboBox(locator, name, ElementState.DISPLAYED);
}

default IMultiChoiceComboBox getMultiChoiceComboBox(By locator, String name, ElementState state) {
return get(ElementType.MULTICHOICECOMBOBOX, locator, name, state);
}

/**
* Creates element that implements ILabel interface.
*
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,46 @@
package aquality.selenium.elements.interfaces;

import java.util.List;

public interface IMultiChoiceComboBox extends IComboBox {

/**
* Deselect all selected options
*/
void deselectAll();
mialeska marked this conversation as resolved.
Show resolved Hide resolved

/**
* Deselect selected option by index
*
* @param index number of selected option
*/
void deselectByIndex(int index);

/**
* Deselect selected option by value
*
* @param value argument value
*/
void deselectByValue(String value);

/**
* Deselect selected option by containing value
*
* @param value partial option's value
*/
void deselectByContainingValue(String value);

/**
* Deselect selected option by visible text
*
* @param text text to be deselected
*/
void deselectByText(String text);

/**
* Deselect selected option by containing visible text
*
* @param text visible text
*/
void deselectByContainingText(String text);
}
4 changes: 4 additions & 0 deletions src/main/resources/localization/be.json
Original file line number Diff line number Diff line change
Expand Up @@ -43,6 +43,9 @@
"loc.combobox.texts": "Спіс тэкстаў опцыяў: [%s]",
"loc.combobox.values": "Спіс значэнняў: [%s]",
"loc.combobox.impossible.to.select.contain.value.or.text" : "Немагчыма выбраць опцыю, якая змяшчае значэнне/тэкст '%1$s' у камбабоксе '%2$s'",
"loc.multichoicecombobox": "Камбабокс з мульцівыбарам",
"loc.multichoicecombobox.deselect.all": "Адмяняем выбар усіх значэнняў",
"loc.multichoicecombobox.deselect.by.text": "Адмяняем выбар значэння з тэкстам '%s'",
"loc.el.getattr" : "Атрымліваем атрыбут '%1$s'",
"loc.el.attr.value": "Значэнне атрыбута '%1$s': [%2$s]",
"loc.el.cssvalue" : "Атрымліваем значэнне css '%1$s'",
Expand All @@ -64,6 +67,7 @@
"loc.scrolling.center.js" : "Пракручваем старонку да цэнтра элемента праз JavaScript",
"loc.scrolling.js" : "Пракручваем старонку праз JavaScript",
"loc.selecting.value" : "Выбіраем значэнне - '%s'",
"loc.deselecting.value": "Адмяняем выбар значэння - '%s'",
"loc.send.text" : "Задаем тэкст - '%s'",
"loc.setting.value" : "Задаем значэнне - '%s'",
"loc.text.clearing" : "Ачышчаем",
Expand Down
4 changes: 4 additions & 0 deletions src/main/resources/localization/en.json
Original file line number Diff line number Diff line change
Expand Up @@ -43,6 +43,9 @@
"loc.combobox.texts": "Option texts: [%s]",
"loc.combobox.values": "Option values: [%s]",
"loc.combobox.impossible.to.select.contain.value.or.text" : "It is impossible to select option that contains value/text '%1$s' from combobox '%2$s'",
"loc.multichoicecombobox": "Multi-choice ComboBox",
"loc.multichoicecombobox.deselect.all": "Deselect all",
"loc.multichoicecombobox.deselect.by.text": "Deselecting value by text '%s'",
"loc.el.getattr" : "Getting attribute '%1$s'",
"loc.el.attr.value": "Value of attribute '%1$s': [%2$s]",
"loc.el.cssvalue" : "Getting css value '%1$s'",
Expand All @@ -64,6 +67,7 @@
"loc.scrolling.center.js" : "Scrolling to the center via JavaScript",
"loc.scrolling.js" : "Scrolling via JavaScript",
"loc.selecting.value" : "Selecting value - '%s'",
"loc.deselecting.value": "Deselecting value - '%s'",
"loc.send.text" : "Setting text - '%s'",
"loc.setting.value" : "Setting value - '%s'",
"loc.text.clearing" : "Clearing",
Expand Down
4 changes: 4 additions & 0 deletions src/main/resources/localization/ru.json
Original file line number Diff line number Diff line change
Expand Up @@ -43,6 +43,9 @@
"loc.combobox.texts": "Список текстов опций: [%s]",
"loc.combobox.values": "Список значений: [%s]",
"loc.combobox.impossible.to.select.contain.value.or.text" : "Не удаётся выбрать значение которое содержит значение/текст '%1$s' в выпадающем списке '%2$s'",
"loc.multichoicecombobox": "Комбобокс с мультивыбором",
"loc.multichoicecombobox.deselect.all": "Отмена выбора всех значений",
"loc.multichoicecombobox.deselect.by.text": "Отмена выбора значения с текстом '%s'",
"loc.el.getattr" : "Получение аттрибута '%1$s'",
"loc.el.attr.value": "Значение аттрибута '%1$s'': [%2$s]",
"loc.el.cssvalue" : "Получение значения css '%1$s'",
Expand All @@ -64,6 +67,7 @@
"loc.scrolling.center.js" : "Скроллинг в центр (посредством JavaScript)",
"loc.scrolling.js" : "Скроллинг посредством JavaScript",
"loc.selecting.value" : "Выбор значения - '%s'",
"loc.deselecting.value": "Отмена выбора значения - '%s'",
"loc.send.text" : "Ввод текста - '%s'",
"loc.setting.value" : "Установка значения - '%s'",
"loc.text.clearing" : "Очистка",
Expand Down
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
package tests.integration;
package tests.integration.elements;

import aquality.selenium.browser.AqualityServices;
import aquality.selenium.core.elements.ElementState;
Expand Down
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
package tests.integration;
package tests.integration.elements;

import aquality.selenium.browser.AqualityServices;
import aquality.selenium.core.elements.ElementState;
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,97 @@
package tests.integration.elements;

import aquality.selenium.browser.AqualityServices;
import org.testng.Assert;
import org.testng.annotations.AfterClass;
import org.testng.annotations.AfterMethod;
import org.testng.annotations.BeforeMethod;
import org.testng.annotations.Test;
import tests.BaseTest;
import w3schools.W3SchoolsPage;
import w3schools.forms.SelectMultipleForm;

import java.util.List;
import java.util.stream.Collectors;
import java.util.stream.Stream;

public class MultiChoiceComboBoxTests extends BaseTest {

private final SelectMultipleForm selectMultipleForm = new SelectMultipleForm();

@BeforeMethod
@Override
public void beforeMethod() {
getBrowser().goTo(W3SchoolsPage.SELECT_MULTIPLE.getAddress());
getBrowser().setWindowSize(defaultSize.width, defaultSize.height);
}

@Test
public void testDeselectByValue() {
List<String> valuesToRemove = Stream.of("volvo", "saab").collect(Collectors.toList());

selectMultipleForm.switchToResultFrame();
selectMultipleForm.selectAll();
List<String> remaining = selectMultipleForm.deselectByValue(valuesToRemove);
selectMultipleForm.submit();

Assert.assertEquals(selectMultipleForm.getValuesFromResult(), remaining);
}

@Test
public void testDeselectByContainingValue() {
List<String> valuesToRemove = Stream.of("saa", "ope").collect(Collectors.toList());

selectMultipleForm.switchToResultFrame();
selectMultipleForm.selectAll();
List<String> remaining = selectMultipleForm.deselectByContainingValue(valuesToRemove);
selectMultipleForm.submit();

Assert.assertEquals(selectMultipleForm.getValuesFromResult(), remaining);
}

@Test
public void testDeselectByText() {
List<String> valuesToRemove = Stream.of("Opel").collect(Collectors.toList());

selectMultipleForm.switchToResultFrame();
selectMultipleForm.selectAll();
List<String> remaining = selectMultipleForm.deselectByText(valuesToRemove);
selectMultipleForm.submit();

Assert.assertEquals(selectMultipleForm.getValuesFromResult(), remaining);
}

@Test
public void testDeselectByContainingText() {
List<String> valuesToRemove = Stream.of("Au", "Vol").collect(Collectors.toList());

selectMultipleForm.switchToResultFrame();
selectMultipleForm.selectAll();
List<String> remaining = selectMultipleForm.deselectByContainingText(valuesToRemove);
selectMultipleForm.submit();

Assert.assertEquals(selectMultipleForm.getValuesFromResult(), remaining);
}

@Test
public void testDeselectByIndex() {
List<Integer> valuesToRemove = Stream.of(2, 3).collect(Collectors.toList());

selectMultipleForm.switchToResultFrame();
selectMultipleForm.selectAll();
List<String> remaining = selectMultipleForm.deselectByIndex(valuesToRemove);
selectMultipleForm.submit();

Assert.assertEquals(selectMultipleForm.getValuesFromResult(), remaining);
}

@Test
public void testDeselectAll() {
selectMultipleForm.switchToResultFrame();
selectMultipleForm.selectAll();
selectMultipleForm.deselectAll();
selectMultipleForm.submit();

Assert.assertTrue(selectMultipleForm.getValuesFromResult().isEmpty());
}
}
17 changes: 17 additions & 0 deletions src/test/java/w3schools/W3SchoolsPage.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
package w3schools;

public enum W3SchoolsPage {
SELECT_MULTIPLE("tryhtml_select_multiple");

private static final String BASE_URL = "https://www.w3schools.com/tags/tryit.asp";

private final String postfix;

W3SchoolsPage(String postfix) {
this.postfix = postfix;
}

public String getAddress() {
return BASE_URL.concat(String.format("?filename=%s", postfix));
}
}
Loading