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.

ScrolledTabSheetResizeTest.java 9.8KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258
  1. package com.vaadin.tests.components.tabsheet;
  2. import static org.hamcrest.MatcherAssert.assertThat;
  3. import static org.hamcrest.Matchers.greaterThan;
  4. import static org.hamcrest.Matchers.greaterThanOrEqualTo;
  5. import static org.junit.Assert.assertEquals;
  6. import static org.junit.Assert.fail;
  7. import java.io.IOException;
  8. import java.util.HashMap;
  9. import java.util.List;
  10. import java.util.Map;
  11. import org.junit.Test;
  12. import org.openqa.selenium.By;
  13. import org.openqa.selenium.WebElement;
  14. import com.vaadin.testbench.TestBenchElement;
  15. import com.vaadin.testbench.elements.ButtonElement;
  16. import com.vaadin.testbench.elements.TabSheetElement;
  17. import com.vaadin.testbench.elements.UIElement;
  18. import com.vaadin.tests.tb3.MultiBrowserTest;
  19. public class ScrolledTabSheetResizeTest extends MultiBrowserTest {
  20. protected String lastVisibleTabCaption = "Tab 19";
  21. private WebElement pendingTab = null;
  22. @Override
  23. public void setup() throws Exception {
  24. super.setup();
  25. openTestURL();
  26. }
  27. @Test
  28. public void testReindeer() throws IOException, InterruptedException {
  29. $(ButtonElement.class).first().click();
  30. Map<String, Integer> sizes = saveWidths();
  31. StringBuilder exceptions = new StringBuilder();
  32. boolean failed = false;
  33. // upper limit is determined by the amount of tabs,
  34. // lower end by limits set by Selenium version
  35. for (int i = 1400; i >= 650; i = i - 50) {
  36. try {
  37. testResize(i, sizes);
  38. } catch (Exception e) {
  39. if (failed) {
  40. exceptions.append(" --- ");
  41. }
  42. failed = true;
  43. exceptions.append(i + ": " + e.getMessage());
  44. if (e.getCause() != null && e.getCause().getMessage() != null
  45. && !e.getCause().getMessage().trim().isEmpty()) {
  46. exceptions.append(" - " + e.getCause().getMessage());
  47. }
  48. } catch (AssertionError e) {
  49. if (failed) {
  50. exceptions.append(" --- ");
  51. }
  52. failed = true;
  53. exceptions.append(i + ": " + e.getMessage());
  54. }
  55. }
  56. if (failed) {
  57. fail("Combined error report: " + exceptions.toString());
  58. }
  59. }
  60. @Test
  61. public void testValo() throws IOException, InterruptedException {
  62. Map<String, Integer> sizes = saveWidths();
  63. StringBuilder exceptions = new StringBuilder();
  64. boolean failed = false;
  65. // 1550 would be better for the amount of tabs (wider than for
  66. // reindeer), but IE11 can't adjust that far
  67. for (int i = 1500; i >= 650; i = i - 50) {
  68. try {
  69. testResize(i, sizes);
  70. } catch (Exception e) {
  71. if (failed) {
  72. exceptions.append(" --- ");
  73. }
  74. failed = true;
  75. exceptions.append(i + ": " + e.getMessage());
  76. if (e.getCause() != null && e.getCause().getMessage() != null
  77. && !e.getCause().getMessage().trim().isEmpty()) {
  78. exceptions.append(" - " + e.getCause().getMessage());
  79. }
  80. } catch (AssertionError e) {
  81. if (failed) {
  82. exceptions.append(" --- ");
  83. }
  84. failed = true;
  85. exceptions.append(i + ": " + e.getMessage());
  86. }
  87. }
  88. if (failed) {
  89. fail("Combined error report: " + exceptions.toString());
  90. }
  91. }
  92. private Map<String, Integer> saveWidths() {
  93. // save the tab widths before any scrolling
  94. TabSheetElement ts = $(TabSheetElement.class).first();
  95. Map<String, Integer> sizes = new HashMap<>();
  96. for (WebElement tab : ts
  97. .findElements(By.className("v-tabsheet-tabitemcell"))) {
  98. if (hasCssClass(tab, "v-tabsheet-tabitemcell-first")) {
  99. // skip the first visible for now, it has different styling and
  100. // we are interested in the non-styled width
  101. pendingTab = tab;
  102. continue;
  103. }
  104. if (pendingTab != null && tab.isDisplayed()) {
  105. String currentLeft = tab.getCssValue("padding-left");
  106. String pendingLeft = pendingTab.getCssValue("padding-left");
  107. if (currentLeft == null || "0px".equals(currentLeft)) {
  108. currentLeft = tab.findElement(By.className("v-caption"))
  109. .getCssValue("margin-left");
  110. pendingLeft = pendingTab
  111. .findElement(By.className("v-caption"))
  112. .getCssValue("margin-left");
  113. }
  114. if (currentLeft != pendingLeft && currentLeft.endsWith("px")
  115. && pendingLeft.endsWith("px")) {
  116. WebElement caption = pendingTab
  117. .findElement(By.className("v-captiontext"));
  118. sizes.put(caption.getAttribute("innerText"),
  119. pendingTab.getSize().getWidth()
  120. - intValue(pendingLeft)
  121. + intValue(currentLeft));
  122. }
  123. pendingTab = null;
  124. }
  125. WebElement caption = tab.findElement(By.className("v-captiontext"));
  126. sizes.put(caption.getAttribute("innerText"),
  127. tab.getSize().getWidth());
  128. }
  129. return sizes;
  130. }
  131. private Integer intValue(String pixelString) {
  132. return Integer
  133. .valueOf(pixelString.substring(0, pixelString.indexOf("px")));
  134. }
  135. private void testResize(int start, Map<String, Integer> sizes)
  136. throws IOException, InterruptedException {
  137. resizeViewPortTo(start);
  138. waitUntilLoadingIndicatorNotVisible();
  139. sleep(100); // a bit more for layouting
  140. int iterations = 0;
  141. while (scrollRight() && iterations < 50) {
  142. waitUntilLoadingIndicatorNotVisible();
  143. ++iterations;
  144. }
  145. if (iterations >= 50) {
  146. fail("scrolling right never reaches the end");
  147. }
  148. assertNoExtraRoom(start, sizes);
  149. resizeViewPortTo(start + 150);
  150. waitUntilLoadingIndicatorNotVisible();
  151. sleep(100); // a bit more for layouting
  152. assertNoExtraRoom(start + 150, sizes);
  153. }
  154. private void resizeViewPortTo(int width) {
  155. try {
  156. testBench().resizeViewPortTo(width, 600);
  157. } catch (UnsupportedOperationException e) {
  158. // sometimes this exception is thrown even if resize succeeded, test
  159. // validity
  160. waitUntilLoadingIndicatorNotVisible();
  161. UIElement ui = $(UIElement.class).first();
  162. int currentWidth = ui.getSize().width;
  163. if (currentWidth != width) {
  164. // only throw the exception if the size didn't change
  165. throw e;
  166. }
  167. }
  168. }
  169. private void assertNoExtraRoom(int width, Map<String, Integer> sizes) {
  170. TabSheetElement ts = $(TabSheetElement.class).first();
  171. WebElement scroller = ts
  172. .findElement(By.className("v-tabsheet-scroller"));
  173. List<WebElement> tabs = ts
  174. .findElements(By.className("v-tabsheet-tabitemcell"));
  175. WebElement lastTab = tabs.get(tabs.size() - 1);
  176. assertEquals("Unexpected last visible tab,", lastVisibleTabCaption,
  177. lastTab.findElement(By.className("v-captiontext")).getText());
  178. WebElement firstHidden = getFirstHiddenViewable(tabs);
  179. if (firstHidden == null) {
  180. // nothing to scroll to
  181. return;
  182. }
  183. // the sizes change during a tab's life-cycle, use the recorded size
  184. // approximation for how much extra space adding this tab would need
  185. // (measuring a hidden tab would definitely give too small width)
  186. WebElement caption = firstHidden
  187. .findElement(By.className("v-captiontext"));
  188. String captionText = caption.getAttribute("innerText");
  189. Integer firstHiddenWidth = sizes.get(captionText);
  190. if (firstHiddenWidth == null) {
  191. firstHiddenWidth = sizes.get("Tab 3");
  192. }
  193. int tabWidth = lastTab.getSize().width;
  194. int tabRight = lastTab.getLocation().x + tabWidth;
  195. assertThat("Unexpected tab width", tabRight, greaterThan(20));
  196. int scrollerLeft = scroller.getLocation().x;
  197. // technically these should probably be just greaterThan,
  198. // but one pixel's difference is irrelevant for now
  199. assertThat("Not scrolled to the end (width: " + width + ")",
  200. scrollerLeft, greaterThanOrEqualTo(tabRight));
  201. assertThat("Too big gap (width: " + width + ")", firstHiddenWidth,
  202. greaterThanOrEqualTo(scrollerLeft - tabRight));
  203. }
  204. /*
  205. * Scroll the tabsheet bar to the right.
  206. */
  207. private boolean scrollRight() throws InterruptedException {
  208. List<WebElement> scrollElements = getDriver()
  209. .findElements(By.className("v-tabsheet-scrollerNext"));
  210. if (!scrollElements.isEmpty()) {
  211. TestBenchElement rightScrollElement = (TestBenchElement) scrollElements
  212. .get(0);
  213. rightScrollElement.click(5, 5);
  214. return true;
  215. } else {
  216. return false;
  217. }
  218. }
  219. /*
  220. * There is no way to differentiate between hidden-on-server and
  221. * hidden-on-client here, so this method has to be overridable.
  222. */
  223. protected WebElement getFirstHiddenViewable(List<WebElement> tabs) {
  224. WebElement previous = null;
  225. for (WebElement tab : tabs) {
  226. if (hasCssClass(tab, "v-tabsheet-tabitemcell-first")) {
  227. break;
  228. }
  229. previous = tab;
  230. }
  231. return previous;
  232. }
  233. }