123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276 |
- /*
- * Copyright 2000-2018 Vaadin Ltd.
- *
- * Licensed under the Apache License, Version 2.0 (the "License"); you may not
- * use this file except in compliance with the License. You may obtain a copy of
- * the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
- * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
- * License for the specific language governing permissions and limitations under
- * the License.
- */
- package com.vaadin.testbench.elements;
-
- import java.util.ArrayList;
- import java.util.Collections;
- import java.util.List;
-
- import org.openqa.selenium.JavascriptExecutor;
- import org.openqa.selenium.WebDriverException;
- import org.openqa.selenium.WebElement;
-
- import com.vaadin.testbench.By;
- import com.vaadin.testbench.TestBenchElement;
- import com.vaadin.testbench.elementsbase.ServerClass;
-
- @ServerClass("com.vaadin.ui.ComboBox")
- public class ComboBoxElement extends AbstractSingleSelectElement {
-
- private static org.openqa.selenium.By bySuggestionPopup = By
- .vaadin("#popup");
- private static org.openqa.selenium.By byNextPage = By
- .className("v-filterselect-nextpage");
- private static org.openqa.selenium.By byPrevPage = By
- .className("v-filterselect-prevpage");
-
- /**
- * Selects the first option in the ComboBox which matches the given text.
- *
- * @param text
- * the text of the option to select
- */
- public void selectByText(String text) {
- if (isReadOnly()) {
- throw new ReadOnlyException();
- }
-
- if (!isTextInputAllowed()) {
- selectByTextFromPopup(text);
- return;
- }
- clear();
- sendKeys(text);
-
- selectSuggestion(text);
- }
-
- /**
- * Selects, without filtering, the first option in the ComboBox which
- * matches the given text.
- *
- * @param text
- * the text of the option to select
- */
- private void selectByTextFromPopup(String text) {
- // This method assumes there is no need to touch the filter string
-
- // 1. Find first page
- // 2. Select first matching text if found
- // 3. Iterate towards end
-
- while (openPrevPage()) {
- // Scroll until beginning
- }
-
- do {
- if (selectSuggestion(text)) {
- return;
- }
- } while (openNextPage());
- }
-
- private boolean selectSuggestion(String text) {
- for (WebElement suggestion : getPopupSuggestionElements()) {
- if (text.equals(suggestion.getText())) {
- clickElement(suggestion);
- return true;
- }
- }
- return false;
- }
-
- private boolean isReadOnly(WebElement elem) {
- JavascriptExecutor js = (JavascriptExecutor) getDriver();
- return (Boolean) js.executeScript("return arguments[0].readOnly", elem);
- }
-
- /**
- * Checks if text input is allowed for the combo box.
- *
- * @return <code>true</code> if text input is allowed, <code>false</code>
- * otherwise
- */
- public boolean isTextInputAllowed() {
- return !isReadOnly(getInputField());
- }
-
- /**
- * Checks whether the suggestion popup is open or not.
- *
- * @return {@code true} if popup is open, {@code false if not}
- */
- public boolean isPopupOpen() {
- return isElementPresent(bySuggestionPopup);
- }
-
- /**
- * Open the suggestion popup.
- */
- public void openPopup() {
- findElement(By.vaadin("#button")).click();
- }
-
- /**
- * Gets the text representation of all suggestions on the current page.
- *
- * @return List of suggestion texts
- */
- public List<String> getPopupSuggestions() {
- List<String> suggestionsTexts = new ArrayList<>();
- List<WebElement> suggestions = getPopupSuggestionElements();
- for (WebElement suggestion : suggestions) {
- String text = suggestion.getText();
- if (!text.isEmpty()) {
- suggestionsTexts.add(text);
- }
- }
- return suggestionsTexts;
- }
-
- /**
- * Gets the elements of all suggestions on the current page.
- * <p>
- * Opens the popup if not already open.
- *
- * @return a list of elements for the suggestions on the current page
- */
- public List<WebElement> getPopupSuggestionElements() {
- List<WebElement> tables = getSuggestionPopup()
- .findElements(By.tagName("table"));
- if (tables == null || tables.isEmpty()) {
- return Collections.emptyList();
- }
- WebElement table = tables.get(0);
- return table.findElements(By.tagName("td"));
- }
-
- /**
- * Opens next popup page.
- *
- * @return True if next page opened. false if doesn't have next page
- */
- public boolean openNextPage() {
- try {
- clickElement(getSuggestionPopup().findElement(byNextPage));
- return true;
- } catch (WebDriverException e) {
- // PhantomJS driver can throw WDE instead of the more specific
- // NoSuchElementException
- return false;
- }
- }
-
- /**
- * Open previous popup page.
- *
- * @return True if previous page opened. False if doesn't have previous page
- */
- public boolean openPrevPage() {
- try {
- clickElement(getSuggestionPopup().findElement(byPrevPage));
- return true;
- } catch (WebDriverException e) {
- // PhantomJS driver can throw WDE instead of the more specific
- // NoSuchElementException
- return false;
- }
- }
-
- /**
- * Returns the suggestion popup element.
- */
- public WebElement getSuggestionPopup() {
- ensurePopupOpen();
- return findElement(bySuggestionPopup);
- }
-
- /**
- * Return value of the combo box element.
- *
- * @return value of the combo box element
- */
- public String getValue() {
- return getInputField().getAttribute("value");
- }
-
- /**
- * Returns the text input field element, used for entering text into the
- * combo box.
- *
- * @return the input field element
- */
- public WebElement getInputField() {
- return findElement(By.vaadin("#textbox"));
- }
-
- private void ensurePopupOpen() {
- if (!isElementPresent(bySuggestionPopup)) {
- openPopup();
- }
- }
-
- @Override
- public String getText() {
- return getInputField().getAttribute("value");
- }
-
- @Override
- public void clear() {
- getInputField().clear();
- String value = getText();
- if (value != null && !value.isEmpty()) {
- ((JavascriptExecutor) getDriver())
- .executeScript("arguments[0].value = ''", getInputField());
- }
- }
-
- @Override
- public void sendKeys(CharSequence... keysToSend) {
- sendKeys(50, keysToSend);
- }
-
- /**
- * Use this method to simulate typing into an element, which may set its
- * value.
- *
- * @param delay
- * delay after sending each individual key (mainly needed for
- * PhantomJS)
- * @param keysToSend
- * keys to type into the element
- */
- public void sendKeys(int delay, CharSequence... keysToSend) {
- WebElement input = getInputField();
-
- for (CharSequence key : keysToSend) {
- input.sendKeys(key);
- try {
- Thread.sleep(delay);
- } catch (InterruptedException e) {
- }
- }
- }
-
- private void clickElement(WebElement element) {
- if (isFirefox()) {
- // Workaround for Selenium/TB and Firefox 45 issue
- ((TestBenchElement) element).clickHiddenElement();
- } else {
- element.click();
- }
- }
- }
|