You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

ComboBoxElement.java 6.7KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233
  1. /*
  2. * Copyright 2000-2016 Vaadin Ltd.
  3. *
  4. * Licensed under the Apache License, Version 2.0 (the "License"); you may not
  5. * use this file except in compliance with the License. You may obtain a copy of
  6. * the License at
  7. *
  8. * http://www.apache.org/licenses/LICENSE-2.0
  9. *
  10. * Unless required by applicable law or agreed to in writing, software
  11. * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
  12. * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
  13. * License for the specific language governing permissions and limitations under
  14. * the License.
  15. */
  16. package com.vaadin.testbench.elements;
  17. import java.util.ArrayList;
  18. import java.util.Collections;
  19. import java.util.List;
  20. import org.openqa.selenium.JavascriptExecutor;
  21. import org.openqa.selenium.Keys;
  22. import org.openqa.selenium.NoSuchElementException;
  23. import org.openqa.selenium.WebElement;
  24. import com.vaadin.testbench.By;
  25. import com.vaadin.testbench.elementsbase.ServerClass;
  26. @ServerClass("com.vaadin.ui.ComboBox")
  27. public class ComboBoxElement extends AbstractSelectElement {
  28. private static org.openqa.selenium.By bySuggestionPopup = By
  29. .vaadin("#popup");
  30. private static org.openqa.selenium.By byNextPage = By
  31. .className("v-filterselect-nextpage");
  32. private static org.openqa.selenium.By byPrevPage = By
  33. .className("v-filterselect-prevpage");
  34. /**
  35. * Selects the first option in the ComboBox which matches the given text.
  36. *
  37. * @param text
  38. * the text of the option to select
  39. */
  40. public void selectByText(String text) {
  41. if (!isTextInputAllowed()) {
  42. selectByTextFromPopup(text);
  43. return;
  44. }
  45. getInputField().clear();
  46. sendInputFieldKeys(text);
  47. selectSuggestion(text);
  48. }
  49. /**
  50. * Selects, without filtering, the first option in the ComboBox which
  51. * matches the given text.
  52. *
  53. * @param text
  54. * the text of the option to select
  55. */
  56. private void selectByTextFromPopup(String text) {
  57. // This method assumes there is no need to touch the filter string
  58. // 1. Find first page
  59. // 2. Select first matching text if found
  60. // 3. Iterate towards end
  61. while (openPrevPage()) {
  62. // Scroll until beginning
  63. }
  64. do {
  65. if (selectSuggestion(text)) {
  66. return;
  67. }
  68. } while (openNextPage());
  69. }
  70. private boolean selectSuggestion(String text) {
  71. for (WebElement suggestion : getPopupSuggestionElements()) {
  72. if (text.equals(suggestion.getText())) {
  73. suggestion.click();
  74. return true;
  75. }
  76. }
  77. return false;
  78. }
  79. private boolean isReadOnly(WebElement elem) {
  80. JavascriptExecutor js = (JavascriptExecutor) getDriver();
  81. return (Boolean) js.executeScript("return arguments[0].readOnly", elem);
  82. }
  83. /**
  84. * Checks if text input is allowed for the combo box.
  85. *
  86. * @return <code>true</code> if text input is allowed, <code>false</code>
  87. * otherwise
  88. */
  89. public boolean isTextInputAllowed() {
  90. return !isReadOnly(getInputField());
  91. }
  92. /*
  93. * Workaround selenium's bug: sendKeys() will not send left parentheses
  94. * properly. See #14048.
  95. */
  96. private void sendInputFieldKeys(String text) {
  97. WebElement textBox = getInputField();
  98. if (!text.contains("(")) {
  99. textBox.sendKeys(text);
  100. return;
  101. }
  102. String OPEN_PARENTHESES = "_OPEN_PARENT#H#ESES_";
  103. String tamperedText = text.replaceAll("\\(", OPEN_PARENTHESES);
  104. textBox.sendKeys(tamperedText);
  105. JavascriptExecutor js = getCommandExecutor();
  106. String jsScript = String.format(
  107. "arguments[0].value = arguments[0].value.replace(/%s/g, '(')",
  108. OPEN_PARENTHESES);
  109. js.executeScript(jsScript, textBox);
  110. // refresh suggestions popupBox
  111. textBox.sendKeys("a" + Keys.BACK_SPACE);
  112. }
  113. /**
  114. * Open the suggestion popup
  115. */
  116. public void openPopup() {
  117. findElement(By.vaadin("#button")).click();
  118. }
  119. /**
  120. * Gets the text representation of all suggestions on the current page
  121. *
  122. * @return List of suggestion texts
  123. */
  124. public List<String> getPopupSuggestions() {
  125. List<String> suggestionsTexts = new ArrayList<String>();
  126. List<WebElement> suggestions = getPopupSuggestionElements();
  127. for (WebElement suggestion : suggestions) {
  128. String text = suggestion.getText();
  129. if (!text.isEmpty()) {
  130. suggestionsTexts.add(text);
  131. }
  132. }
  133. return suggestionsTexts;
  134. }
  135. /**
  136. * Gets the elements of all suggestions on the current page.
  137. * <p>
  138. * Opens the popup if not already open.
  139. *
  140. * @return a list of elements for the suggestions on the current page
  141. */
  142. public List<WebElement> getPopupSuggestionElements() {
  143. List<WebElement> tables = getSuggestionPopup()
  144. .findElements(By.tagName("table"));
  145. if (tables == null || tables.isEmpty()) {
  146. return Collections.emptyList();
  147. }
  148. WebElement table = tables.get(0);
  149. return table.findElements(By.tagName("td"));
  150. }
  151. /**
  152. * Opens next popup page.
  153. *
  154. * @return True if next page opened. false if doesn't have next page
  155. */
  156. public boolean openNextPage() {
  157. try {
  158. getSuggestionPopup().findElement(byNextPage).click();
  159. return true;
  160. } catch (NoSuchElementException e) {
  161. return false;
  162. }
  163. }
  164. /**
  165. * Open previous popup page.
  166. *
  167. * @return True if previous page opened. False if doesn't have previous page
  168. */
  169. public boolean openPrevPage() {
  170. try {
  171. getSuggestionPopup().findElement(byPrevPage).click();
  172. return true;
  173. } catch (NoSuchElementException e) {
  174. return false;
  175. }
  176. }
  177. /**
  178. * Returns the suggestion popup element
  179. */
  180. public WebElement getSuggestionPopup() {
  181. ensurePopupOpen();
  182. return findElement(bySuggestionPopup);
  183. }
  184. /**
  185. * Return value of the combo box element
  186. *
  187. * @return value of the combo box element
  188. */
  189. public String getValue() {
  190. return getInputField().getAttribute("value");
  191. }
  192. /**
  193. * Returns the text input field element, used for entering text into the
  194. * combo box.
  195. *
  196. * @return the input field element
  197. */
  198. public WebElement getInputField() {
  199. return findElement(By.xpath("input"));
  200. }
  201. private void ensurePopupOpen() {
  202. if (!isElementPresent(bySuggestionPopup)) {
  203. openPopup();
  204. }
  205. }
  206. }