com.vaadin.testbench.elements.ComboBoxElement.java Source code

Java tutorial

Introduction

Here is the source code for com.vaadin.testbench.elements.ComboBoxElement.java

Source

/*
 * 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();
        }
    }
}