Nelze vybrat více než 25 témat Téma musí začínat písmenem nebo číslem, může obsahovat pomlčky („-“) a může být dlouhé až 35 znaků.

ComboBoxElement.java 7.8KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276
  1. /*
  2. * Copyright 2000-2018 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.WebDriverException;
  22. import org.openqa.selenium.WebElement;
  23. import com.vaadin.testbench.By;
  24. import com.vaadin.testbench.TestBenchElement;
  25. import com.vaadin.testbench.elementsbase.ServerClass;
  26. @ServerClass("com.vaadin.ui.ComboBox")
  27. public class ComboBoxElement extends AbstractSingleSelectElement {
  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 (isReadOnly()) {
  42. throw new ReadOnlyException();
  43. }
  44. if (!isTextInputAllowed()) {
  45. selectByTextFromPopup(text);
  46. return;
  47. }
  48. clear();
  49. sendKeys(text);
  50. selectSuggestion(text);
  51. }
  52. /**
  53. * Selects, without filtering, the first option in the ComboBox which
  54. * matches the given text.
  55. *
  56. * @param text
  57. * the text of the option to select
  58. */
  59. private void selectByTextFromPopup(String text) {
  60. // This method assumes there is no need to touch the filter string
  61. // 1. Find first page
  62. // 2. Select first matching text if found
  63. // 3. Iterate towards end
  64. while (openPrevPage()) {
  65. // Scroll until beginning
  66. }
  67. do {
  68. if (selectSuggestion(text)) {
  69. return;
  70. }
  71. } while (openNextPage());
  72. }
  73. private boolean selectSuggestion(String text) {
  74. for (WebElement suggestion : getPopupSuggestionElements()) {
  75. if (text.equals(suggestion.getText())) {
  76. clickElement(suggestion);
  77. return true;
  78. }
  79. }
  80. return false;
  81. }
  82. private boolean isReadOnly(WebElement elem) {
  83. JavascriptExecutor js = (JavascriptExecutor) getDriver();
  84. return (Boolean) js.executeScript("return arguments[0].readOnly", elem);
  85. }
  86. /**
  87. * Checks if text input is allowed for the combo box.
  88. *
  89. * @return <code>true</code> if text input is allowed, <code>false</code>
  90. * otherwise
  91. */
  92. public boolean isTextInputAllowed() {
  93. return !isReadOnly(getInputField());
  94. }
  95. /**
  96. * Checks whether the suggestion popup is open or not.
  97. *
  98. * @return {@code true} if popup is open, {@code false if not}
  99. */
  100. public boolean isPopupOpen() {
  101. return isElementPresent(bySuggestionPopup);
  102. }
  103. /**
  104. * Open the suggestion popup.
  105. */
  106. public void openPopup() {
  107. findElement(By.vaadin("#button")).click();
  108. }
  109. /**
  110. * Gets the text representation of all suggestions on the current page.
  111. *
  112. * @return List of suggestion texts
  113. */
  114. public List<String> getPopupSuggestions() {
  115. List<String> suggestionsTexts = new ArrayList<>();
  116. List<WebElement> suggestions = getPopupSuggestionElements();
  117. for (WebElement suggestion : suggestions) {
  118. String text = suggestion.getText();
  119. if (!text.isEmpty()) {
  120. suggestionsTexts.add(text);
  121. }
  122. }
  123. return suggestionsTexts;
  124. }
  125. /**
  126. * Gets the elements of all suggestions on the current page.
  127. * <p>
  128. * Opens the popup if not already open.
  129. *
  130. * @return a list of elements for the suggestions on the current page
  131. */
  132. public List<WebElement> getPopupSuggestionElements() {
  133. List<WebElement> tables = getSuggestionPopup()
  134. .findElements(By.tagName("table"));
  135. if (tables == null || tables.isEmpty()) {
  136. return Collections.emptyList();
  137. }
  138. WebElement table = tables.get(0);
  139. return table.findElements(By.tagName("td"));
  140. }
  141. /**
  142. * Opens next popup page.
  143. *
  144. * @return True if next page opened. false if doesn't have next page
  145. */
  146. public boolean openNextPage() {
  147. try {
  148. clickElement(getSuggestionPopup().findElement(byNextPage));
  149. return true;
  150. } catch (WebDriverException e) {
  151. // PhantomJS driver can throw WDE instead of the more specific
  152. // NoSuchElementException
  153. return false;
  154. }
  155. }
  156. /**
  157. * Open previous popup page.
  158. *
  159. * @return True if previous page opened. False if doesn't have previous page
  160. */
  161. public boolean openPrevPage() {
  162. try {
  163. clickElement(getSuggestionPopup().findElement(byPrevPage));
  164. return true;
  165. } catch (WebDriverException e) {
  166. // PhantomJS driver can throw WDE instead of the more specific
  167. // NoSuchElementException
  168. return false;
  169. }
  170. }
  171. /**
  172. * Returns the suggestion popup element.
  173. */
  174. public WebElement getSuggestionPopup() {
  175. ensurePopupOpen();
  176. return findElement(bySuggestionPopup);
  177. }
  178. /**
  179. * Return value of the combo box element.
  180. *
  181. * @return value of the combo box element
  182. */
  183. public String getValue() {
  184. return getInputField().getAttribute("value");
  185. }
  186. /**
  187. * Returns the text input field element, used for entering text into the
  188. * combo box.
  189. *
  190. * @return the input field element
  191. */
  192. public WebElement getInputField() {
  193. return findElement(By.vaadin("#textbox"));
  194. }
  195. private void ensurePopupOpen() {
  196. if (!isElementPresent(bySuggestionPopup)) {
  197. openPopup();
  198. }
  199. }
  200. @Override
  201. public String getText() {
  202. return getInputField().getAttribute("value");
  203. }
  204. @Override
  205. public void clear() {
  206. getInputField().clear();
  207. String value = getText();
  208. if (value != null && !value.isEmpty()) {
  209. ((JavascriptExecutor) getDriver())
  210. .executeScript("arguments[0].value = ''", getInputField());
  211. }
  212. }
  213. @Override
  214. public void sendKeys(CharSequence... keysToSend) {
  215. sendKeys(50, keysToSend);
  216. }
  217. /**
  218. * Use this method to simulate typing into an element, which may set its
  219. * value.
  220. *
  221. * @param delay
  222. * delay after sending each individual key (mainly needed for
  223. * PhantomJS)
  224. * @param keysToSend
  225. * keys to type into the element
  226. */
  227. public void sendKeys(int delay, CharSequence... keysToSend) {
  228. WebElement input = getInputField();
  229. for (CharSequence key : keysToSend) {
  230. input.sendKeys(key);
  231. try {
  232. Thread.sleep(delay);
  233. } catch (InterruptedException e) {
  234. }
  235. }
  236. }
  237. private void clickElement(WebElement element) {
  238. if (isFirefox()) {
  239. // Workaround for Selenium/TB and Firefox 45 issue
  240. ((TestBenchElement) element).clickHiddenElement();
  241. } else {
  242. element.click();
  243. }
  244. }
  245. }