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.

AbstractTB3Test.java 17KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534
  1. /*
  2. * Copyright 2000-2013 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.tests.tb3;
  17. import java.net.URL;
  18. import org.junit.After;
  19. import org.junit.Before;
  20. import org.openqa.selenium.Platform;
  21. import org.openqa.selenium.WebDriver;
  22. import org.openqa.selenium.WebElement;
  23. import org.openqa.selenium.remote.BrowserType;
  24. import org.openqa.selenium.remote.DesiredCapabilities;
  25. import org.openqa.selenium.remote.RemoteWebDriver;
  26. import com.vaadin.server.LegacyApplication;
  27. import com.vaadin.testbench.By;
  28. import com.vaadin.testbench.TestBench;
  29. import com.vaadin.testbench.TestBenchTestCase;
  30. import com.vaadin.ui.UI;
  31. /**
  32. * Base class for TestBench 3+ tests. All TB3+ tests in the project should
  33. * extend this class.
  34. *
  35. * Provides:
  36. * <ul>
  37. * <li>Helpers for browser selection</li>
  38. * <li>Hub connection setup and teardown</li>
  39. * <li>Automatic opening of a given test on the development server using
  40. * {@link #getUIClass()} or by automatically finding an enclosing UI class</li>
  41. * <li>Generic helpers for creating TB3+ tests</li>
  42. * <li>Automatic URL generation based on needed features, e.g.
  43. * {@link #isDebug()}, {@link #isPushEnabled()}</li>
  44. * </ul>
  45. *
  46. * @author Vaadin Ltd
  47. */
  48. public abstract class AbstractTB3Test extends TestBenchTestCase {
  49. /**
  50. * Height of the screenshots we want to capture
  51. */
  52. private static final int SCREENSHOT_HEIGHT = 850;
  53. /**
  54. * Width of the screenshots we want to capture
  55. */
  56. private static final int SCREENSHOT_WIDTH = 1500;
  57. private DesiredCapabilities desiredCapabilities;
  58. {
  59. // Default browser to run on unless setDesiredCapabilities is called
  60. desiredCapabilities = BrowserUtil.firefox(24);
  61. }
  62. /**
  63. * Connect to the hub using a remote web driver, set the canvas size and
  64. * opens the initial URL as specified by {@link #getTestUrl()}
  65. *
  66. * @throws Exception
  67. */
  68. @Before
  69. public void setup() throws Exception {
  70. setupDriver();
  71. String testUrl = getTestUrl();
  72. if (testUrl != null) {
  73. driver.get(testUrl);
  74. }
  75. }
  76. /**
  77. * Creates and configure the web driver to be used for the test. By default
  78. * creates a remote web driver which connects to {@link #getHubURL()} and
  79. * selects a browser based on {@link #getDesiredCapabilities()}.
  80. *
  81. * This method MUST call {@link #setDriver(WebDriver)} with the newly
  82. * generated driver.
  83. *
  84. * @throws Exception
  85. * If something goes wrong
  86. */
  87. protected void setupDriver() throws Exception {
  88. DesiredCapabilities capabilities = getDesiredCapabilities();
  89. WebDriver dr = TestBench.createDriver(new RemoteWebDriver(new URL(
  90. getHubURL()), capabilities));
  91. setDriver(dr);
  92. int w = SCREENSHOT_WIDTH;
  93. int h = SCREENSHOT_HEIGHT;
  94. if (BrowserUtil.isIE8(capabilities)) {
  95. // IE8 gets size wrong, who would have guessed...
  96. w += 4;
  97. h += 4;
  98. }
  99. try {
  100. testBench().resizeViewPortTo(w, h);
  101. } catch (UnsupportedOperationException e) {
  102. // Opera does not support this...
  103. }
  104. }
  105. /**
  106. * Returns the full URL to be opened when the test starts.
  107. *
  108. * @return the full URL to open or null to not open any URL automatically
  109. */
  110. protected String getTestUrl() {
  111. String baseUrl = getBaseURL();
  112. if (baseUrl.endsWith("/")) {
  113. baseUrl = baseUrl.substring(0, baseUrl.length() - 1);
  114. }
  115. return baseUrl + getDeploymentPath();
  116. }
  117. /**
  118. *
  119. * @return the location (URL) of the TB hub
  120. */
  121. protected String getHubURL() {
  122. return "http://" + getHubHostname() + ":4444/wd/hub";
  123. }
  124. /**
  125. * Used for building the hub URL to use for the test
  126. *
  127. * @return the host name of the TestBench hub
  128. */
  129. protected abstract String getHubHostname();
  130. /**
  131. * Used to determine what URL to initially open for the test
  132. *
  133. * @return the host name of development server
  134. */
  135. protected abstract String getDeploymentHostname();
  136. /**
  137. * Used to determine which capabilities should be used when setting up a
  138. * {@link WebDriver} for this test. Typically set by a test runner or left
  139. * at its default (Firefox 24). If you want to run a test on a single
  140. * browser other than Firefox 24 you can override this method.
  141. *
  142. * @return the requested browser capabilities
  143. */
  144. protected DesiredCapabilities getDesiredCapabilities() {
  145. return desiredCapabilities;
  146. }
  147. /**
  148. * Sets the requested browser capabilities (typically browser name and
  149. * version)
  150. *
  151. * @param desiredCapabilities
  152. */
  153. public void setDesiredCapabilities(DesiredCapabilities desiredCapabilities) {
  154. this.desiredCapabilities = desiredCapabilities;
  155. }
  156. /**
  157. * Shuts down the driver after the test has been completed
  158. *
  159. * @throws Exception
  160. */
  161. @After
  162. public void tearDown() throws Exception {
  163. if (driver != null) {
  164. driver.quit();
  165. }
  166. driver = null;
  167. }
  168. /**
  169. * Finds a Vaadin element based on the part of a TB3 style locator following
  170. * the :: (e.g.
  171. * vaadin=runLabelModes::PID_Scheckboxaction-Enabled/domChild[0] ->
  172. * PID_Scheckboxaction-Enabled/domChild[0]).
  173. *
  174. * @param vaadinLocator
  175. * The part following :: of the vaadin locator string
  176. * @return
  177. */
  178. protected WebElement vaadinElement(String vaadinLocator) {
  179. String base = getApplicationId(getDeploymentPath());
  180. base += "::";
  181. return driver.findElement(By.vaadin(base + vaadinLocator));
  182. }
  183. /**
  184. * Find a Vaadin element based on its id given using Component.setId
  185. *
  186. * @param id
  187. * The id to locate
  188. * @return
  189. */
  190. public WebElement vaadinElementById(String id) {
  191. return vaadinElement("PID_S" + id);
  192. }
  193. /**
  194. * Returns the path that should be used for the test. The path contains the
  195. * full path (appended to hostname+port) and must start with a slash.
  196. *
  197. * @return The path to open automatically when the test starts
  198. */
  199. protected String getDeploymentPath() {
  200. Class<?> uiClass = getUIClass();
  201. if (uiClass != null) {
  202. return getDeploymentPath(uiClass);
  203. }
  204. throw new IllegalArgumentException("Unable to determine path for "
  205. + getClass().getCanonicalName());
  206. }
  207. /**
  208. * Returns the UI class the current test is connected to. Uses the enclosing
  209. * class if the test class is a static inner class to a UI class.
  210. *
  211. * Test which are not enclosed by a UI class must implement this method and
  212. * return the UI class they want to test.
  213. *
  214. * Note that this method will update the test name to the enclosing class to
  215. * be compatible with TB2 screenshot naming
  216. *
  217. * @return the UI class the current test is connected to
  218. */
  219. protected Class<?> getUIClass() {
  220. Class<?> enclosingClass = getClass().getEnclosingClass();
  221. if (enclosingClass != null) {
  222. return enclosingClass;
  223. }
  224. return null;
  225. }
  226. /**
  227. * Determines whether to run the test in debug mode (with the debug console
  228. * open) or not
  229. *
  230. * @return true to run with the debug window open, false by default
  231. */
  232. protected boolean isDebug() {
  233. return false;
  234. }
  235. /**
  236. * Determines whether to run the test with push enabled (using /run-push) or
  237. * not. Note that push tests can and should typically be created using @Push
  238. * on the UI instead of overriding this method
  239. *
  240. * @return true to use push in the test, false to use whatever UI specifies
  241. */
  242. protected boolean isPushEnabled() {
  243. return false;
  244. }
  245. /**
  246. * Returns the path for the given UI class when deployed on the test server.
  247. * The path contains the full path (appended to hostname+port) and must
  248. * start with a slash.
  249. *
  250. * This method takes into account {@link #isPushEnabled()} and
  251. * {@link #isDebug()} when the path is generated.
  252. *
  253. * @param uiClass
  254. * @return The path to the given UI class
  255. */
  256. private String getDeploymentPath(Class<?> uiClass) {
  257. String runPath = "/run";
  258. if (isPushEnabled()) {
  259. runPath = "/run-push";
  260. }
  261. if (UI.class.isAssignableFrom(uiClass)) {
  262. return runPath + "/" + uiClass.getCanonicalName()
  263. + (isDebug() ? "?debug" : "");
  264. } else if (LegacyApplication.class.isAssignableFrom(uiClass)) {
  265. return runPath + "/" + uiClass.getCanonicalName()
  266. + "?restartApplication" + (isDebug() ? "&debug" : "");
  267. } else {
  268. throw new IllegalArgumentException(
  269. "Unable to determine path for enclosing class "
  270. + uiClass.getCanonicalName());
  271. }
  272. }
  273. /**
  274. * Used to determine what URL to initially open for the test
  275. *
  276. * @return The base URL for the test. Does not include a trailing slash.
  277. */
  278. protected String getBaseURL() {
  279. return "http://" + getDeploymentHostname() + ":8888";
  280. }
  281. /**
  282. * Generates the application id based on the URL in a way compatible with
  283. * VaadinServletService.
  284. *
  285. * @param pathWithQueryParameters
  286. * The path part of the URL, possibly still containing query
  287. * parameters
  288. * @return The application ID string used in Vaadin locators
  289. */
  290. private String getApplicationId(String pathWithQueryParameters) {
  291. // Remove any possible URL parameters
  292. String pathWithoutQueryParameters = pathWithQueryParameters.replaceAll(
  293. "\\?.*", "");
  294. if ("".equals(pathWithoutQueryParameters)) {
  295. return "ROOT";
  296. }
  297. // Retain only a-z and numbers
  298. return pathWithoutQueryParameters.replaceAll("[^a-zA-Z0-9]", "");
  299. }
  300. /**
  301. * Helper method for sleeping X ms in a test. Catches and ignores
  302. * InterruptedExceptions
  303. *
  304. * @param timeoutMillis
  305. * Number of ms to wait
  306. */
  307. protected void sleep(int timeoutMillis) {
  308. try {
  309. Thread.sleep(timeoutMillis);
  310. } catch (InterruptedException e) {
  311. throw new RuntimeException(e);
  312. }
  313. }
  314. /**
  315. * Provides helper method for selecting the browser to run on
  316. *
  317. * @author Vaadin Ltd
  318. */
  319. public static class BrowserUtil {
  320. /**
  321. * Gets the capabilities for Safari of the given version
  322. *
  323. * @param version
  324. * the major version
  325. * @return an object describing the capabilities required for running a
  326. * test on the given Safari version
  327. */
  328. public static DesiredCapabilities safari(int version) {
  329. DesiredCapabilities c = DesiredCapabilities.safari();
  330. c.setVersion("" + version);
  331. return c;
  332. }
  333. /**
  334. * Gets the capabilities for Chrome of the given version
  335. *
  336. * @param version
  337. * the major version
  338. * @return an object describing the capabilities required for running a
  339. * test on the given Chrome version
  340. */
  341. public static DesiredCapabilities chrome(int version) {
  342. DesiredCapabilities c = DesiredCapabilities.chrome();
  343. c.setVersion("" + version);
  344. c.setPlatform(Platform.XP);
  345. return c;
  346. }
  347. /**
  348. * Gets the capabilities for Opera of the given version
  349. *
  350. * @param version
  351. * the major version
  352. * @return an object describing the capabilities required for running a
  353. * test on the given Opera version
  354. */
  355. public static DesiredCapabilities opera(int version) {
  356. DesiredCapabilities c = DesiredCapabilities.opera();
  357. c.setVersion("" + version);
  358. c.setPlatform(Platform.XP);
  359. return c;
  360. }
  361. /**
  362. * Gets the capabilities for Firefox of the given version
  363. *
  364. * @param version
  365. * the major version
  366. * @return an object describing the capabilities required for running a
  367. * test on the given Firefox version
  368. */
  369. public static DesiredCapabilities firefox(int version) {
  370. DesiredCapabilities c = DesiredCapabilities.firefox();
  371. c.setVersion("" + version);
  372. c.setPlatform(Platform.XP);
  373. return c;
  374. }
  375. /**
  376. * Gets the capabilities for Internet Explorer of the given version
  377. *
  378. * @param version
  379. * the major version
  380. * @return an object describing the capabilities required for running a
  381. * test on the given Internet Explorer version
  382. */
  383. public static DesiredCapabilities ie(int version) {
  384. DesiredCapabilities c = DesiredCapabilities.internetExplorer();
  385. c.setVersion("" + version);
  386. return c;
  387. }
  388. /**
  389. * Checks if the given capabilities refer to Internet Explorer 8
  390. *
  391. * @param capabilities
  392. * @return true if the capabilities refer to IE8, false otherwise
  393. */
  394. public static boolean isIE8(DesiredCapabilities capabilities) {
  395. return BrowserType.IE.equals(capabilities.getBrowserName())
  396. && "8".equals(capabilities.getVersion());
  397. }
  398. /**
  399. * Returns a human readable identifier of the given browser. Used for
  400. * test naming and screenshots
  401. *
  402. * @param capabilities
  403. * @return a human readable string describing the capabilities
  404. */
  405. public static String getBrowserIdentifier(
  406. DesiredCapabilities capabilities) {
  407. String browserName = capabilities.getBrowserName();
  408. if (BrowserType.IE.equals(browserName)) {
  409. return "InternetExplorer";
  410. } else if (BrowserType.FIREFOX.equals(browserName)) {
  411. return "Firefox";
  412. } else if (BrowserType.CHROME.equals(browserName)) {
  413. return "Chrome";
  414. } else if (BrowserType.SAFARI.equals(browserName)) {
  415. return "Safari";
  416. } else if (BrowserType.OPERA.equals(browserName)) {
  417. return "Opera";
  418. }
  419. return browserName;
  420. }
  421. /**
  422. * Returns a human readable identifier of the platform described by the
  423. * given capabilities. Used mainly for screenshots
  424. *
  425. * @param capabilities
  426. * @return a human readable string describing the platform
  427. */
  428. public static String getPlatform(DesiredCapabilities capabilities) {
  429. if (capabilities.getPlatform() == Platform.WIN8
  430. || capabilities.getPlatform() == Platform.WINDOWS
  431. || capabilities.getPlatform() == Platform.VISTA
  432. || capabilities.getPlatform() == Platform.XP) {
  433. return "Windows";
  434. } else if (capabilities.getPlatform() == Platform.MAC) {
  435. return "Mac";
  436. }
  437. return capabilities.getPlatform().toString();
  438. }
  439. /**
  440. * Returns a string which uniquely (enough) identifies this browser.
  441. * Used mainly in screenshot names.
  442. *
  443. * @param capabilities
  444. *
  445. * @return a unique string for each browser
  446. */
  447. public static String getUniqueIdentifier(
  448. DesiredCapabilities capabilities) {
  449. return getUniqueIdentifier(getPlatform(capabilities),
  450. getBrowserIdentifier(capabilities),
  451. capabilities.getVersion());
  452. }
  453. /**
  454. * Returns a string which uniquely (enough) identifies this browser.
  455. * Used mainly in screenshot names.
  456. *
  457. * @param capabilities
  458. *
  459. * @return a unique string for each browser
  460. */
  461. public static String getUniqueIdentifier(
  462. DesiredCapabilities capabilities, String versionOverride) {
  463. return getUniqueIdentifier(getPlatform(capabilities),
  464. getBrowserIdentifier(capabilities), versionOverride);
  465. }
  466. private static String getUniqueIdentifier(String platform,
  467. String browser, String version) {
  468. return platform + "_" + browser + "_" + version;
  469. }
  470. }
  471. /**
  472. * Called by the test runner whenever there is an exception in the test that
  473. * will cause termination of the test
  474. *
  475. * @param t
  476. * the throwable which caused the termination
  477. */
  478. public void onUncaughtException(Throwable t) {
  479. // Do nothing by default
  480. }
  481. }