mirror of
https://github.com/scm-manager/scm-manager.git
synced 2025-11-13 17:05:43 +01:00
fix selenium integration tests and introduce page object pattern
This commit is contained in:
@@ -326,13 +326,20 @@
|
|||||||
<version>${selenium.version}</version>
|
<version>${selenium.version}</version>
|
||||||
<scope>test</scope>
|
<scope>test</scope>
|
||||||
</dependency>
|
</dependency>
|
||||||
|
|
||||||
<dependency>
|
<dependency>
|
||||||
<groupId>org.seleniumhq.selenium</groupId>
|
<groupId>org.seleniumhq.selenium</groupId>
|
||||||
<artifactId>selenium-firefox-driver</artifactId>
|
<artifactId>selenium-firefox-driver</artifactId>
|
||||||
<version>${selenium.version}</version>
|
<version>${selenium.version}</version>
|
||||||
<scope>test</scope>
|
<scope>test</scope>
|
||||||
</dependency>
|
</dependency>
|
||||||
|
|
||||||
|
<dependency>
|
||||||
|
<groupId>org.seleniumhq.selenium</groupId>
|
||||||
|
<artifactId>htmlunit-driver</artifactId>
|
||||||
|
<version>2.21</version>
|
||||||
|
<scope>test</scope>
|
||||||
|
</dependency>
|
||||||
|
|
||||||
<dependency>
|
<dependency>
|
||||||
<groupId>com.sun.jersey</groupId>
|
<groupId>com.sun.jersey</groupId>
|
||||||
@@ -528,7 +535,7 @@
|
|||||||
<scm.stage>DEVELOPMENT</scm.stage>
|
<scm.stage>DEVELOPMENT</scm.stage>
|
||||||
<scm.home>target/scm-it</scm.home>
|
<scm.home>target/scm-it</scm.home>
|
||||||
<environment.profile>default</environment.profile>
|
<environment.profile>default</environment.profile>
|
||||||
<selenium.version>2.28.0</selenium.version>
|
<selenium.version>2.53.1</selenium.version>
|
||||||
<enunciate.version>1.31</enunciate.version>
|
<enunciate.version>1.31</enunciate.version>
|
||||||
<aether.version>1.13.1</aether.version>
|
<aether.version>1.13.1</aether.version>
|
||||||
<wagon.version>1.0</wagon.version>
|
<wagon.version>1.0</wagon.version>
|
||||||
@@ -688,6 +695,24 @@
|
|||||||
<profile>
|
<profile>
|
||||||
<id>selenium</id>
|
<id>selenium</id>
|
||||||
|
|
||||||
|
<dependencies>
|
||||||
|
|
||||||
|
<dependency>
|
||||||
|
<groupId>org.apache.httpcomponents</groupId>
|
||||||
|
<artifactId>httpclient</artifactId>
|
||||||
|
<version>4.3.2</version>
|
||||||
|
<scope>test</scope>
|
||||||
|
</dependency>
|
||||||
|
|
||||||
|
<dependency>
|
||||||
|
<groupId>xml-apis</groupId>
|
||||||
|
<artifactId>xml-apis</artifactId>
|
||||||
|
<version>1.4.01</version>
|
||||||
|
<scope>test</scope>
|
||||||
|
</dependency>
|
||||||
|
|
||||||
|
</dependencies>
|
||||||
|
|
||||||
<build>
|
<build>
|
||||||
<plugins>
|
<plugins>
|
||||||
|
|
||||||
|
|||||||
@@ -34,25 +34,27 @@ package sonia.scm.selenium;
|
|||||||
|
|
||||||
//~--- non-JDK imports --------------------------------------------------------
|
//~--- non-JDK imports --------------------------------------------------------
|
||||||
|
|
||||||
|
import sonia.scm.selenium.page.Pages;
|
||||||
|
import sonia.scm.selenium.page.MainPage;
|
||||||
|
import sonia.scm.selenium.page.LoginPage;
|
||||||
|
import static org.junit.Assert.*;
|
||||||
import org.junit.Test;
|
import org.junit.Test;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
*
|
* Authentication related selenium integration tests.
|
||||||
|
*
|
||||||
* @author Sebastian Sdorra
|
* @author Sebastian Sdorra
|
||||||
*/
|
*/
|
||||||
public class AuthenticationITCase extends SeleniumTestBase
|
public class AuthenticationITCase extends SeleniumITCaseBase {
|
||||||
{
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Method description
|
* Authenticates an user and call logout function.
|
||||||
*
|
|
||||||
*
|
|
||||||
* @throws Exception
|
|
||||||
*/
|
*/
|
||||||
@Test
|
@Test
|
||||||
public void testAuthentication() throws Exception
|
public void testAuthentication() {
|
||||||
{
|
MainPage main = Pages.get(driver, LoginPage.class).login("scmadmin", "scmadmin");
|
||||||
login("scmadmin", "scmadmin");
|
assertEquals("scmadmin", main.getUserInfo());
|
||||||
logout();
|
main.logout();
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -34,61 +34,55 @@ package sonia.scm.selenium;
|
|||||||
|
|
||||||
//~--- non-JDK imports --------------------------------------------------------
|
//~--- non-JDK imports --------------------------------------------------------
|
||||||
|
|
||||||
|
import sonia.scm.selenium.page.Pages;
|
||||||
|
import sonia.scm.selenium.page.MainPage;
|
||||||
|
import sonia.scm.selenium.page.LoginPage;
|
||||||
import org.junit.After;
|
import org.junit.After;
|
||||||
import org.junit.Before;
|
import org.junit.Before;
|
||||||
import org.junit.Test;
|
import org.junit.Test;
|
||||||
|
|
||||||
import static org.junit.Assert.*;
|
import sonia.scm.repository.Repository;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
*
|
* Repository related selenium integration tests.
|
||||||
|
*
|
||||||
* @author Sebastian Sdorra
|
* @author Sebastian Sdorra
|
||||||
*/
|
*/
|
||||||
public class RepositoryCRUDITCase extends SeleniumTestBase
|
public class RepositoriesITCase extends SeleniumITCaseBase {
|
||||||
{
|
|
||||||
|
|
||||||
|
private MainPage main;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Method description
|
* Authenticates admin user, before each test.
|
||||||
*
|
|
||||||
*/
|
|
||||||
@After
|
|
||||||
public void after()
|
|
||||||
{
|
|
||||||
logout();
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Method description
|
|
||||||
*
|
|
||||||
*/
|
|
||||||
@Test
|
|
||||||
public void createRepository() throws InterruptedException
|
|
||||||
{
|
|
||||||
waitAndClick("#repositoryAddButton");
|
|
||||||
waitForPresence("input[name=name]").sendKeys("scm");
|
|
||||||
select("#x-form-el-repositoryType img").click();
|
|
||||||
waitAndClick("div.x-combo-list-item:nth-of-type(2)");
|
|
||||||
type("input[name=contact]", "scmadmin@scm-manager.org");
|
|
||||||
type("textarea[name=description]", "SCM-Manager");
|
|
||||||
waitAndClick("div.x-panel-btns button:nth-of-type(1)");
|
|
||||||
|
|
||||||
String name =
|
|
||||||
waitForPresence(
|
|
||||||
"div.x-grid3-row-selected div.x-grid3-col-name").getText();
|
|
||||||
|
|
||||||
assertEquals("scm", name);
|
|
||||||
|
|
||||||
waitAndClick("#repoRmButton button");
|
|
||||||
waitAndClick("div.x-window button:nth-of-type(1)");
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Method description
|
|
||||||
*
|
|
||||||
*/
|
*/
|
||||||
@Before
|
@Before
|
||||||
public void login()
|
public void login() {
|
||||||
{
|
main = Pages.get(driver, LoginPage.class)
|
||||||
login("scmadmin", "scmadmin");
|
.login("scmadmin", "scmadmin");
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Creates, select and removes a repository.
|
||||||
|
*/
|
||||||
|
@Test
|
||||||
|
public void createRepository() {
|
||||||
|
Repository repository = new Repository();
|
||||||
|
repository.setName("scm");
|
||||||
|
repository.setType("git");
|
||||||
|
repository.setContact("scmadmin@scm-manager.org");
|
||||||
|
repository.setDescription("SCM-Manager");
|
||||||
|
|
||||||
|
main.repositories()
|
||||||
|
.add(repository)
|
||||||
|
.select(repository.getName())
|
||||||
|
.remove();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Logs the user out, after each test.
|
||||||
|
*/
|
||||||
|
@After
|
||||||
|
public void logout() {
|
||||||
|
main.logout();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -0,0 +1,71 @@
|
|||||||
|
/**
|
||||||
|
* Copyright (c) 2014, Sebastian Sdorra
|
||||||
|
* All rights reserved.
|
||||||
|
*
|
||||||
|
* Redistribution and use in source and binary forms, with or without
|
||||||
|
* modification, are permitted provided that the following conditions are met:
|
||||||
|
*
|
||||||
|
* 1. Redistributions of source code must retain the above copyright notice,
|
||||||
|
* this list of conditions and the following disclaimer.
|
||||||
|
* 2. Redistributions in binary form must reproduce the above copyright notice,
|
||||||
|
* this list of conditions and the following disclaimer in the documentation
|
||||||
|
* and/or other materials provided with the distribution.
|
||||||
|
* 3. Neither the name of SCM-Manager; nor the names of its
|
||||||
|
* contributors may be used to endorse or promote products derived from this
|
||||||
|
* software without specific prior written permission.
|
||||||
|
*
|
||||||
|
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
||||||
|
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||||
|
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
||||||
|
* DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY
|
||||||
|
* DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
|
||||||
|
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
|
||||||
|
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
|
||||||
|
* ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||||
|
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
||||||
|
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||||
|
*
|
||||||
|
* http://bitbucket.org/sdorra/scm-manager
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
package sonia.scm.selenium;
|
||||||
|
|
||||||
|
import org.junit.AfterClass;
|
||||||
|
import org.junit.BeforeClass;
|
||||||
|
import org.openqa.selenium.WebDriver;
|
||||||
|
import org.openqa.selenium.firefox.FirefoxDriver;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Base class for selenium integration tests.
|
||||||
|
*
|
||||||
|
* @author Sebastian Sdorra
|
||||||
|
*/
|
||||||
|
public class SeleniumITCaseBase {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Selenium test driver.
|
||||||
|
*/
|
||||||
|
protected static WebDriver driver;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Setup selenium test driver.
|
||||||
|
*/
|
||||||
|
@BeforeClass
|
||||||
|
public static void setUpDriver() {
|
||||||
|
// DesiredCapabilities capa = DesiredCapabilities.chrome();
|
||||||
|
// capa.setBrowserName("firefox");
|
||||||
|
// capa.setPlatform(Platform.ANY);
|
||||||
|
// RemoteWebDriver driver = new RemoteWebDriver(new URL("http://localhost:4444/wd/hub"), capa);
|
||||||
|
|
||||||
|
driver = new FirefoxDriver();
|
||||||
|
driver.get("http://localhost:8082/scm/index.html");
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Closes the selenium test driver.
|
||||||
|
*/
|
||||||
|
@AfterClass
|
||||||
|
public static void tearDownDriver() {
|
||||||
|
driver.close();
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -1,271 +0,0 @@
|
|||||||
/**
|
|
||||||
* Copyright (c) 2010, Sebastian Sdorra
|
|
||||||
* All rights reserved.
|
|
||||||
*
|
|
||||||
* Redistribution and use in source and binary forms, with or without
|
|
||||||
* modification, are permitted provided that the following conditions are met:
|
|
||||||
*
|
|
||||||
* 1. Redistributions of source code must retain the above copyright notice,
|
|
||||||
* this list of conditions and the following disclaimer.
|
|
||||||
* 2. Redistributions in binary form must reproduce the above copyright notice,
|
|
||||||
* this list of conditions and the following disclaimer in the documentation
|
|
||||||
* and/or other materials provided with the distribution.
|
|
||||||
* 3. Neither the name of SCM-Manager; nor the names of its
|
|
||||||
* contributors may be used to endorse or promote products derived from this
|
|
||||||
* software without specific prior written permission.
|
|
||||||
*
|
|
||||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
|
||||||
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
|
||||||
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
|
||||||
* DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY
|
|
||||||
* DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
|
|
||||||
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
|
|
||||||
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
|
|
||||||
* ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
|
||||||
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
|
||||||
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
|
||||||
*
|
|
||||||
* http://bitbucket.org/sdorra/scm-manager
|
|
||||||
*
|
|
||||||
*/
|
|
||||||
|
|
||||||
|
|
||||||
package sonia.scm.selenium;
|
|
||||||
|
|
||||||
//~--- non-JDK imports --------------------------------------------------------
|
|
||||||
|
|
||||||
import com.google.common.io.Files;
|
|
||||||
|
|
||||||
import org.junit.After;
|
|
||||||
import org.junit.Before;
|
|
||||||
|
|
||||||
import org.openqa.selenium.By;
|
|
||||||
import org.openqa.selenium.OutputType;
|
|
||||||
import org.openqa.selenium.TakesScreenshot;
|
|
||||||
import org.openqa.selenium.WebDriver;
|
|
||||||
import org.openqa.selenium.WebElement;
|
|
||||||
import org.openqa.selenium.firefox.FirefoxDriver;
|
|
||||||
import org.openqa.selenium.support.ui.ExpectedConditions;
|
|
||||||
import org.openqa.selenium.support.ui.WebDriverWait;
|
|
||||||
|
|
||||||
import org.slf4j.Logger;
|
|
||||||
import org.slf4j.LoggerFactory;
|
|
||||||
|
|
||||||
import static org.junit.Assert.*;
|
|
||||||
|
|
||||||
//~--- JDK imports ------------------------------------------------------------
|
|
||||||
|
|
||||||
import java.io.File;
|
|
||||||
import java.io.IOException;
|
|
||||||
|
|
||||||
import java.util.concurrent.TimeUnit;
|
|
||||||
|
|
||||||
/**
|
|
||||||
*
|
|
||||||
* @author Sebastian Sdorra
|
|
||||||
*/
|
|
||||||
public class SeleniumTestBase
|
|
||||||
{
|
|
||||||
|
|
||||||
/**
|
|
||||||
* the logger for SeleniumTestBase
|
|
||||||
*/
|
|
||||||
private static final Logger logger =
|
|
||||||
LoggerFactory.getLogger(SeleniumTestBase.class);
|
|
||||||
|
|
||||||
//~--- methods --------------------------------------------------------------
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Method description
|
|
||||||
*
|
|
||||||
*
|
|
||||||
* @throws Exception
|
|
||||||
*/
|
|
||||||
@After
|
|
||||||
public void tearDown() throws Exception
|
|
||||||
{
|
|
||||||
driver.quit();
|
|
||||||
}
|
|
||||||
|
|
||||||
//~--- set methods ----------------------------------------------------------
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Method description
|
|
||||||
*
|
|
||||||
*
|
|
||||||
* @throws Exception
|
|
||||||
*/
|
|
||||||
@Before
|
|
||||||
public void setUp() throws Exception
|
|
||||||
{
|
|
||||||
driver = new FirefoxDriver();
|
|
||||||
baseUrl = "http://localhost:8082/scm/";
|
|
||||||
open("index.html");
|
|
||||||
}
|
|
||||||
|
|
||||||
//~--- methods --------------------------------------------------------------
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Method description
|
|
||||||
*
|
|
||||||
*
|
|
||||||
* @param username
|
|
||||||
* @param password
|
|
||||||
*/
|
|
||||||
protected void login(String username, String password)
|
|
||||||
{
|
|
||||||
type("input[name=username]", username);
|
|
||||||
type("input[name=password]", password);
|
|
||||||
waitAndClick("#loginButton button");
|
|
||||||
|
|
||||||
String ue = waitForPresence("#scm-userinfo-tip").getText();
|
|
||||||
|
|
||||||
assertEquals(username, ue);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Method description
|
|
||||||
*
|
|
||||||
*/
|
|
||||||
protected void logout()
|
|
||||||
{
|
|
||||||
waitAndClick("#navLogout a");
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Method description
|
|
||||||
*
|
|
||||||
*
|
|
||||||
* @param url
|
|
||||||
*/
|
|
||||||
protected void open(String url)
|
|
||||||
{
|
|
||||||
driver.get(baseUrl + url);
|
|
||||||
pause(500, TimeUnit.MILLISECONDS);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Method description
|
|
||||||
*
|
|
||||||
*
|
|
||||||
* @param value
|
|
||||||
* @param unit
|
|
||||||
*/
|
|
||||||
protected void pause(int value, TimeUnit unit)
|
|
||||||
{
|
|
||||||
driver.manage().timeouts().implicitlyWait(value, unit);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Method description
|
|
||||||
*
|
|
||||||
*
|
|
||||||
* @param target
|
|
||||||
*/
|
|
||||||
protected void screenshot(String target)
|
|
||||||
{
|
|
||||||
screenshot(new File(target));
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Method description
|
|
||||||
*
|
|
||||||
*
|
|
||||||
* @param target
|
|
||||||
*/
|
|
||||||
protected void screenshot(File target)
|
|
||||||
{
|
|
||||||
try
|
|
||||||
{
|
|
||||||
File scrFile =
|
|
||||||
((TakesScreenshot) driver).getScreenshotAs(OutputType.FILE);
|
|
||||||
|
|
||||||
Files.copy(scrFile, target);
|
|
||||||
}
|
|
||||||
catch (IOException ex)
|
|
||||||
{
|
|
||||||
logger.error("could not create screenshot", ex);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Method description
|
|
||||||
*
|
|
||||||
*
|
|
||||||
* @param cssSelector
|
|
||||||
*
|
|
||||||
* @return
|
|
||||||
*/
|
|
||||||
protected WebElement select(String cssSelector)
|
|
||||||
{
|
|
||||||
WebElement element = driver.findElement(By.cssSelector(cssSelector));
|
|
||||||
|
|
||||||
assertNotNull(element);
|
|
||||||
|
|
||||||
return element;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Method description
|
|
||||||
*
|
|
||||||
*
|
|
||||||
* @param cssLocator
|
|
||||||
* @param value
|
|
||||||
*/
|
|
||||||
protected void type(String cssLocator, String value)
|
|
||||||
{
|
|
||||||
select(cssLocator).clear();
|
|
||||||
select(cssLocator).sendKeys(value);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Method description
|
|
||||||
*
|
|
||||||
*
|
|
||||||
* @param query
|
|
||||||
*/
|
|
||||||
protected void waitAndClick(String query)
|
|
||||||
{
|
|
||||||
waitToBeClickable(query).click();
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Method description
|
|
||||||
*
|
|
||||||
*
|
|
||||||
* @param query
|
|
||||||
*
|
|
||||||
* @return
|
|
||||||
*/
|
|
||||||
protected WebElement waitForPresence(String query)
|
|
||||||
{
|
|
||||||
WebDriverWait wait = new WebDriverWait(driver, 5);
|
|
||||||
|
|
||||||
return wait.until(
|
|
||||||
ExpectedConditions.presenceOfElementLocated(By.cssSelector(query)));
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Method description
|
|
||||||
*
|
|
||||||
*
|
|
||||||
* @param query
|
|
||||||
*
|
|
||||||
* @return
|
|
||||||
*/
|
|
||||||
protected WebElement waitToBeClickable(String query)
|
|
||||||
{
|
|
||||||
WebDriverWait wait = new WebDriverWait(driver, 5);
|
|
||||||
|
|
||||||
return wait.until(
|
|
||||||
ExpectedConditions.elementToBeClickable(By.cssSelector(query)));
|
|
||||||
}
|
|
||||||
|
|
||||||
//~--- fields ---------------------------------------------------------------
|
|
||||||
|
|
||||||
/** Field description */
|
|
||||||
protected WebDriver driver;
|
|
||||||
|
|
||||||
/** Field description */
|
|
||||||
private String baseUrl;
|
|
||||||
}
|
|
||||||
168
scm-webapp/src/test/java/sonia/scm/selenium/page/BasePage.java
Normal file
168
scm-webapp/src/test/java/sonia/scm/selenium/page/BasePage.java
Normal file
@@ -0,0 +1,168 @@
|
|||||||
|
/**
|
||||||
|
* Copyright (c) 2014, Sebastian Sdorra
|
||||||
|
* All rights reserved.
|
||||||
|
*
|
||||||
|
* Redistribution and use in source and binary forms, with or without
|
||||||
|
* modification, are permitted provided that the following conditions are met:
|
||||||
|
*
|
||||||
|
* 1. Redistributions of source code must retain the above copyright notice,
|
||||||
|
* this list of conditions and the following disclaimer.
|
||||||
|
* 2. Redistributions in binary form must reproduce the above copyright notice,
|
||||||
|
* this list of conditions and the following disclaimer in the documentation
|
||||||
|
* and/or other materials provided with the distribution.
|
||||||
|
* 3. Neither the name of SCM-Manager; nor the names of its
|
||||||
|
* contributors may be used to endorse or promote products derived from this
|
||||||
|
* software without specific prior written permission.
|
||||||
|
*
|
||||||
|
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
||||||
|
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||||
|
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
||||||
|
* DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY
|
||||||
|
* DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
|
||||||
|
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
|
||||||
|
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
|
||||||
|
* ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||||
|
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
||||||
|
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||||
|
*
|
||||||
|
* http://bitbucket.org/sdorra/scm-manager
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
package sonia.scm.selenium.page;
|
||||||
|
|
||||||
|
import com.google.common.base.Throwables;
|
||||||
|
import com.google.common.io.Files;
|
||||||
|
import java.io.File;
|
||||||
|
import java.io.IOException;
|
||||||
|
import java.util.List;
|
||||||
|
import java.util.concurrent.TimeUnit;
|
||||||
|
import org.openqa.selenium.By;
|
||||||
|
import org.openqa.selenium.OutputType;
|
||||||
|
import org.openqa.selenium.TakesScreenshot;
|
||||||
|
import org.openqa.selenium.WebDriver;
|
||||||
|
import org.openqa.selenium.WebElement;
|
||||||
|
import org.openqa.selenium.support.ui.ExpectedConditions;
|
||||||
|
import org.openqa.selenium.support.ui.WebDriverWait;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Abstract selenium base page.
|
||||||
|
*
|
||||||
|
* @author Sebastian Sdorra
|
||||||
|
*
|
||||||
|
* @param <P> concrete page implementation
|
||||||
|
*/
|
||||||
|
public abstract class BasePage<P extends BasePage> {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Selenium test driver.
|
||||||
|
*/
|
||||||
|
protected final WebDriver driver;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Constructs a new base page.
|
||||||
|
*
|
||||||
|
* @param driver selenium test driver
|
||||||
|
*/
|
||||||
|
protected BasePage(WebDriver driver) {
|
||||||
|
this.driver = driver;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Performs a {@link Thread#sleep(long)} for the given timeout.
|
||||||
|
*
|
||||||
|
* @param time timeout
|
||||||
|
* @param unit time unit of timeout
|
||||||
|
*/
|
||||||
|
protected void sleep(long time, TimeUnit unit) {
|
||||||
|
try {
|
||||||
|
unit.sleep(time);
|
||||||
|
} catch (InterruptedException ex) {
|
||||||
|
throw Throwables.propagate(ex);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Wait for the element until it is clickable.
|
||||||
|
*
|
||||||
|
* @param by element selector
|
||||||
|
*
|
||||||
|
* @return web element
|
||||||
|
*/
|
||||||
|
protected WebElement waitToBeClickable(By by){
|
||||||
|
return waitToBeClickable(driver.findElement(by));
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Waits for the element until it is clickable.
|
||||||
|
*
|
||||||
|
* @param element web element
|
||||||
|
*
|
||||||
|
* @return web element
|
||||||
|
*/
|
||||||
|
protected WebElement waitToBeClickable(WebElement element) {
|
||||||
|
WebDriverWait wait = new WebDriverWait(driver, 5);
|
||||||
|
|
||||||
|
return wait.until(ExpectedConditions.elementToBeClickable(element));
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Waits until the element is present.
|
||||||
|
*
|
||||||
|
* @param by element locator
|
||||||
|
*
|
||||||
|
* @return web element
|
||||||
|
*/
|
||||||
|
protected WebElement waitFor(By by){
|
||||||
|
WebDriverWait wait = new WebDriverWait(driver, 1);
|
||||||
|
return wait.until(ExpectedConditions.presenceOfElementLocated(by));
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Waits until the elements are present.
|
||||||
|
*
|
||||||
|
* @param by element selector
|
||||||
|
*
|
||||||
|
* @return list of web elements
|
||||||
|
*/
|
||||||
|
protected List<WebElement> waitForAll(By by){
|
||||||
|
WebDriverWait wait = new WebDriverWait(driver, 1);
|
||||||
|
return wait.until(ExpectedConditions.presenceOfAllElementsLocatedBy(by));
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Creates a screenshot of the current browser content and stores it at the given path.
|
||||||
|
*
|
||||||
|
* @param target target file path
|
||||||
|
*
|
||||||
|
* @return {@code this}
|
||||||
|
*/
|
||||||
|
public P screenshot(String target) {
|
||||||
|
return screenshot(new File(target));
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Creates a screenshot of the current browser content and stores it at the file.
|
||||||
|
*
|
||||||
|
* @param target target file
|
||||||
|
*
|
||||||
|
* @return {@code this}
|
||||||
|
*/
|
||||||
|
public P screenshot(File target) {
|
||||||
|
try {
|
||||||
|
File scrFile = ((TakesScreenshot) driver).getScreenshotAs(OutputType.FILE);
|
||||||
|
|
||||||
|
Files.copy(scrFile, target);
|
||||||
|
} catch (IOException ex) {
|
||||||
|
throw Throwables.propagate(ex);
|
||||||
|
}
|
||||||
|
return self();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns {@code this}.
|
||||||
|
*
|
||||||
|
* @return {@code this}
|
||||||
|
*/
|
||||||
|
protected abstract P self();
|
||||||
|
|
||||||
|
}
|
||||||
@@ -0,0 +1,89 @@
|
|||||||
|
/**
|
||||||
|
* Copyright (c) 2014, Sebastian Sdorra
|
||||||
|
* All rights reserved.
|
||||||
|
*
|
||||||
|
* Redistribution and use in source and binary forms, with or without
|
||||||
|
* modification, are permitted provided that the following conditions are met:
|
||||||
|
*
|
||||||
|
* 1. Redistributions of source code must retain the above copyright notice,
|
||||||
|
* this list of conditions and the following disclaimer.
|
||||||
|
* 2. Redistributions in binary form must reproduce the above copyright notice,
|
||||||
|
* this list of conditions and the following disclaimer in the documentation
|
||||||
|
* and/or other materials provided with the distribution.
|
||||||
|
* 3. Neither the name of SCM-Manager; nor the names of its
|
||||||
|
* contributors may be used to endorse or promote products derived from this
|
||||||
|
* software without specific prior written permission.
|
||||||
|
*
|
||||||
|
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
||||||
|
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||||
|
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
||||||
|
* DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY
|
||||||
|
* DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
|
||||||
|
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
|
||||||
|
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
|
||||||
|
* ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||||
|
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
||||||
|
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||||
|
*
|
||||||
|
* http://bitbucket.org/sdorra/scm-manager
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
package sonia.scm.selenium.page;
|
||||||
|
|
||||||
|
import java.util.concurrent.TimeUnit;
|
||||||
|
import org.openqa.selenium.WebDriver;
|
||||||
|
import org.openqa.selenium.WebElement;
|
||||||
|
import org.openqa.selenium.support.FindBy;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Page object for the scm-manager login page.
|
||||||
|
*
|
||||||
|
* @author Sebastian Sdorra
|
||||||
|
*/
|
||||||
|
public class LoginPage extends BasePage<LoginPage> {
|
||||||
|
|
||||||
|
@FindBy(css = "input[name=username]")
|
||||||
|
private WebElement usernameInput;
|
||||||
|
|
||||||
|
@FindBy(css = "input[name=password]")
|
||||||
|
private WebElement passwordInput;
|
||||||
|
|
||||||
|
@FindBy(css = "#loginButton button")
|
||||||
|
private WebElement loginButton;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Constructs a new page. This constructor should only be called from {@link Pages}.
|
||||||
|
*
|
||||||
|
* @param driver selenium test driver
|
||||||
|
*/
|
||||||
|
LoginPage(WebDriver driver) {
|
||||||
|
super(driver);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected LoginPage self() {
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Authenticates the user and returns the {@link MainPage}.
|
||||||
|
*
|
||||||
|
* @param username username
|
||||||
|
* @param password password
|
||||||
|
*
|
||||||
|
* @return {@link MainPage} after successful authentication
|
||||||
|
*/
|
||||||
|
public MainPage login(String username, String password) {
|
||||||
|
usernameInput.clear();
|
||||||
|
usernameInput.sendKeys(username);
|
||||||
|
|
||||||
|
passwordInput.clear();
|
||||||
|
passwordInput.sendKeys(password);
|
||||||
|
|
||||||
|
sleep(250, TimeUnit.MILLISECONDS);
|
||||||
|
|
||||||
|
waitToBeClickable(loginButton).click();
|
||||||
|
|
||||||
|
return Pages.get(driver, MainPage.class);
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,95 @@
|
|||||||
|
/**
|
||||||
|
* Copyright (c) 2014, Sebastian Sdorra
|
||||||
|
* All rights reserved.
|
||||||
|
*
|
||||||
|
* Redistribution and use in source and binary forms, with or without
|
||||||
|
* modification, are permitted provided that the following conditions are met:
|
||||||
|
*
|
||||||
|
* 1. Redistributions of source code must retain the above copyright notice,
|
||||||
|
* this list of conditions and the following disclaimer.
|
||||||
|
* 2. Redistributions in binary form must reproduce the above copyright notice,
|
||||||
|
* this list of conditions and the following disclaimer in the documentation
|
||||||
|
* and/or other materials provided with the distribution.
|
||||||
|
* 3. Neither the name of SCM-Manager; nor the names of its
|
||||||
|
* contributors may be used to endorse or promote products derived from this
|
||||||
|
* software without specific prior written permission.
|
||||||
|
*
|
||||||
|
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
||||||
|
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||||
|
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
||||||
|
* DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY
|
||||||
|
* DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
|
||||||
|
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
|
||||||
|
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
|
||||||
|
* ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||||
|
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
||||||
|
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||||
|
*
|
||||||
|
* http://bitbucket.org/sdorra/scm-manager
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
package sonia.scm.selenium.page;
|
||||||
|
|
||||||
|
import org.openqa.selenium.WebDriver;
|
||||||
|
import org.openqa.selenium.WebElement;
|
||||||
|
import org.openqa.selenium.support.FindBy;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Page object for scm-manager's main page.
|
||||||
|
*
|
||||||
|
* @author Sebastian Sdorra
|
||||||
|
*/
|
||||||
|
public class MainPage extends BasePage<MainPage> {
|
||||||
|
|
||||||
|
@FindBy(css = "#navLogout a")
|
||||||
|
private WebElement logoutLink;
|
||||||
|
|
||||||
|
@FindBy(linkText = "Repositories")
|
||||||
|
private WebElement repositoriesLink;
|
||||||
|
|
||||||
|
@FindBy(css = "#scm-userinfo-tip")
|
||||||
|
private WebElement userInfoTip;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Constructs a new page. This constructor should only be called from {@link Pages}.
|
||||||
|
*
|
||||||
|
* @param driver selenium test driver
|
||||||
|
*/
|
||||||
|
MainPage(WebDriver driver) {
|
||||||
|
super(driver);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected MainPage self() {
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns the name of the current authenticated user from the user info tip.
|
||||||
|
*
|
||||||
|
* @return name of the current authenticated user
|
||||||
|
*/
|
||||||
|
public String getUserInfo(){
|
||||||
|
return userInfoTip.getText();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Navigates to the repositories page and returns the page object for this page.
|
||||||
|
*
|
||||||
|
* @return page object for repositories page
|
||||||
|
*/
|
||||||
|
public RepositoriesPage repositories(){
|
||||||
|
repositoriesLink.click();
|
||||||
|
return Pages.get(driver, RepositoriesPage.class);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Logs the current user out.
|
||||||
|
*
|
||||||
|
* @return page object for the login
|
||||||
|
*/
|
||||||
|
public LoginPage logout(){
|
||||||
|
waitToBeClickable(logoutLink).click();
|
||||||
|
return Pages.get(driver, LoginPage.class);
|
||||||
|
}
|
||||||
|
}
|
||||||
113
scm-webapp/src/test/java/sonia/scm/selenium/page/Pages.java
Normal file
113
scm-webapp/src/test/java/sonia/scm/selenium/page/Pages.java
Normal file
@@ -0,0 +1,113 @@
|
|||||||
|
/**
|
||||||
|
* Copyright (c) 2014, Sebastian Sdorra
|
||||||
|
* All rights reserved.
|
||||||
|
*
|
||||||
|
* Redistribution and use in source and binary forms, with or without
|
||||||
|
* modification, are permitted provided that the following conditions are met:
|
||||||
|
*
|
||||||
|
* 1. Redistributions of source code must retain the above copyright notice,
|
||||||
|
* this list of conditions and the following disclaimer.
|
||||||
|
* 2. Redistributions in binary form must reproduce the above copyright notice,
|
||||||
|
* this list of conditions and the following disclaimer in the documentation
|
||||||
|
* and/or other materials provided with the distribution.
|
||||||
|
* 3. Neither the name of SCM-Manager; nor the names of its
|
||||||
|
* contributors may be used to endorse or promote products derived from this
|
||||||
|
* software without specific prior written permission.
|
||||||
|
*
|
||||||
|
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
||||||
|
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||||
|
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
||||||
|
* DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY
|
||||||
|
* DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
|
||||||
|
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
|
||||||
|
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
|
||||||
|
* ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||||
|
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
||||||
|
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||||
|
*
|
||||||
|
* http://bitbucket.org/sdorra/scm-manager
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
package sonia.scm.selenium.page;
|
||||||
|
|
||||||
|
import com.google.common.base.Throwables;
|
||||||
|
import com.google.common.collect.Lists;
|
||||||
|
import java.lang.reflect.Constructor;
|
||||||
|
import java.util.Arrays;
|
||||||
|
import java.util.List;
|
||||||
|
import org.openqa.selenium.By;
|
||||||
|
import org.openqa.selenium.SearchContext;
|
||||||
|
import org.openqa.selenium.WebDriver;
|
||||||
|
import org.openqa.selenium.WebElement;
|
||||||
|
import org.openqa.selenium.support.PageFactory;
|
||||||
|
import org.openqa.selenium.support.pagefactory.DefaultElementLocatorFactory;
|
||||||
|
import org.openqa.selenium.support.ui.ExpectedConditions;
|
||||||
|
import org.openqa.selenium.support.ui.WebDriverWait;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Helper class for selenium page objects.
|
||||||
|
*
|
||||||
|
* @author Sebastian Sdorra
|
||||||
|
*/
|
||||||
|
public final class Pages {
|
||||||
|
|
||||||
|
private Pages() {
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Creates an instance of the given page object.
|
||||||
|
*
|
||||||
|
* @param <T> page object type
|
||||||
|
* @param driver selenium driver
|
||||||
|
* @param clazz page object type
|
||||||
|
* @param otherArguments other constructor arguments
|
||||||
|
*
|
||||||
|
* @return instance of page object
|
||||||
|
*/
|
||||||
|
public static <T extends BasePage> T get(WebDriver driver, Class<T> clazz, Object... otherArguments)
|
||||||
|
{
|
||||||
|
T page = null;
|
||||||
|
try {
|
||||||
|
List<Class<?>> argumentTypes = Lists.newArrayList();
|
||||||
|
argumentTypes.add(WebDriver.class);
|
||||||
|
for (Object argument : otherArguments) {
|
||||||
|
argumentTypes.add(argument.getClass());
|
||||||
|
}
|
||||||
|
|
||||||
|
List<Object> arguments = Lists.newArrayList();
|
||||||
|
arguments.add(driver);
|
||||||
|
arguments.addAll(Arrays.asList(otherArguments));
|
||||||
|
|
||||||
|
Constructor<T> constructor = clazz.getDeclaredConstructor(
|
||||||
|
argumentTypes.toArray(new Class<?>[argumentTypes.size()])
|
||||||
|
);
|
||||||
|
page = constructor.newInstance(arguments.toArray(new Object[arguments.size()]));
|
||||||
|
|
||||||
|
PageFactory.initElements(new DefaultElementLocatorFactory(new WaitingSearchContext(driver)), page);
|
||||||
|
} catch (Exception ex) {
|
||||||
|
throw Throwables.propagate(ex);
|
||||||
|
}
|
||||||
|
return page;
|
||||||
|
}
|
||||||
|
|
||||||
|
private static class WaitingSearchContext implements SearchContext {
|
||||||
|
|
||||||
|
private final WebDriver driver;
|
||||||
|
private final WebDriverWait wait;
|
||||||
|
|
||||||
|
private WaitingSearchContext(WebDriver driver) {
|
||||||
|
this.driver = driver;
|
||||||
|
this.wait = new WebDriverWait(driver, 1);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public List<WebElement> findElements(By by) {
|
||||||
|
return wait.until(ExpectedConditions.presenceOfAllElementsLocatedBy(by));
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public WebElement findElement(By by) {
|
||||||
|
return wait.until(ExpectedConditions.presenceOfElementLocated(by));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,136 @@
|
|||||||
|
/**
|
||||||
|
* Copyright (c) 2014, Sebastian Sdorra
|
||||||
|
* All rights reserved.
|
||||||
|
*
|
||||||
|
* Redistribution and use in source and binary forms, with or without
|
||||||
|
* modification, are permitted provided that the following conditions are met:
|
||||||
|
*
|
||||||
|
* 1. Redistributions of source code must retain the above copyright notice,
|
||||||
|
* this list of conditions and the following disclaimer.
|
||||||
|
* 2. Redistributions in binary form must reproduce the above copyright notice,
|
||||||
|
* this list of conditions and the following disclaimer in the documentation
|
||||||
|
* and/or other materials provided with the distribution.
|
||||||
|
* 3. Neither the name of SCM-Manager; nor the names of its
|
||||||
|
* contributors may be used to endorse or promote products derived from this
|
||||||
|
* software without specific prior written permission.
|
||||||
|
*
|
||||||
|
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
||||||
|
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||||
|
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
||||||
|
* DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY
|
||||||
|
* DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
|
||||||
|
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
|
||||||
|
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
|
||||||
|
* ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||||
|
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
||||||
|
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||||
|
*
|
||||||
|
* http://bitbucket.org/sdorra/scm-manager
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
package sonia.scm.selenium.page;
|
||||||
|
|
||||||
|
import com.google.common.base.Objects;
|
||||||
|
import java.util.List;
|
||||||
|
import org.openqa.selenium.By;
|
||||||
|
import org.openqa.selenium.JavascriptExecutor;
|
||||||
|
import org.openqa.selenium.NotFoundException;
|
||||||
|
import org.openqa.selenium.WebDriver;
|
||||||
|
import org.openqa.selenium.WebElement;
|
||||||
|
import org.openqa.selenium.support.FindBy;
|
||||||
|
import org.openqa.selenium.support.ui.WebDriverWait;
|
||||||
|
import sonia.scm.repository.Repository;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Page object for scm-manager's repository creation page.
|
||||||
|
*
|
||||||
|
* @author Sebastian Sdorra
|
||||||
|
*/
|
||||||
|
public class RepositoriesAddPage extends BasePage<RepositoriesAddPage> {
|
||||||
|
|
||||||
|
@FindBy(css = "input[name=name]")
|
||||||
|
private WebElement nameInput;
|
||||||
|
|
||||||
|
@FindBy(css = "input[name=contact]")
|
||||||
|
private WebElement contactInput;
|
||||||
|
|
||||||
|
@FindBy(css = "#x-form-el-repositoryType img")
|
||||||
|
private WebElement typeInput;
|
||||||
|
|
||||||
|
@FindBy(css = "textarea[name=description]")
|
||||||
|
private WebElement descriptionInput;
|
||||||
|
|
||||||
|
@FindBy(css = "div.x-panel-btns button:nth-of-type(1)")
|
||||||
|
private WebElement okButton;
|
||||||
|
|
||||||
|
private final RepositoriesPage repositoriesPage;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Constructs a new page. This constructor should only be called from {@link Pages}.
|
||||||
|
*
|
||||||
|
* @param driver selenium test driver
|
||||||
|
* @param repositoriesPage repositories page object
|
||||||
|
*/
|
||||||
|
RepositoriesAddPage(WebDriver driver, RepositoriesPage repositoriesPage) {
|
||||||
|
super(driver);
|
||||||
|
this.repositoriesPage = repositoriesPage;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected RepositoriesAddPage self() {
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Creates a new {@link Repository}.
|
||||||
|
*
|
||||||
|
* @param repository repository for creation
|
||||||
|
*
|
||||||
|
* @return repositories overview page
|
||||||
|
*/
|
||||||
|
public RepositoriesPage add(Repository repository) {
|
||||||
|
nameInput.sendKeys(repository.getName());
|
||||||
|
|
||||||
|
selectType(repository.getType());
|
||||||
|
|
||||||
|
contactInput.sendKeys(repository.getContact());
|
||||||
|
descriptionInput.sendKeys(repository.getDescription());
|
||||||
|
|
||||||
|
waitToBeClickable(okButton).click();
|
||||||
|
|
||||||
|
return repositoriesPage;
|
||||||
|
}
|
||||||
|
|
||||||
|
private void selectType(String type) {
|
||||||
|
typeInput.click();
|
||||||
|
|
||||||
|
String displayName = findDisplayName(type);
|
||||||
|
|
||||||
|
WebDriverWait wait = new WebDriverWait(driver, 1);
|
||||||
|
List<WebElement> elements = waitForAll(By.className("x-combo-list-item"));
|
||||||
|
WebElement typeElement = null;
|
||||||
|
for (WebElement te : elements){
|
||||||
|
if (te.getText().trim().equalsIgnoreCase(displayName)){
|
||||||
|
typeElement = te;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (typeElement == null){
|
||||||
|
throw new NotFoundException("could not find type element with type " + displayName);
|
||||||
|
}
|
||||||
|
|
||||||
|
typeElement.click();
|
||||||
|
}
|
||||||
|
|
||||||
|
private String findDisplayName(String type) {
|
||||||
|
String displayName = null;
|
||||||
|
if (driver instanceof JavascriptExecutor) {
|
||||||
|
// TODO seams not to work
|
||||||
|
String script = "Sonia.repository.getTypeByName('" + type + "').displayName;";
|
||||||
|
displayName = (String) ((JavascriptExecutor)driver).executeScript(script);
|
||||||
|
}
|
||||||
|
return Objects.firstNonNull(displayName, type);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
@@ -0,0 +1,103 @@
|
|||||||
|
/**
|
||||||
|
* Copyright (c) 2014, Sebastian Sdorra
|
||||||
|
* All rights reserved.
|
||||||
|
*
|
||||||
|
* Redistribution and use in source and binary forms, with or without
|
||||||
|
* modification, are permitted provided that the following conditions are met:
|
||||||
|
*
|
||||||
|
* 1. Redistributions of source code must retain the above copyright notice,
|
||||||
|
* this list of conditions and the following disclaimer.
|
||||||
|
* 2. Redistributions in binary form must reproduce the above copyright notice,
|
||||||
|
* this list of conditions and the following disclaimer in the documentation
|
||||||
|
* and/or other materials provided with the distribution.
|
||||||
|
* 3. Neither the name of SCM-Manager; nor the names of its
|
||||||
|
* contributors may be used to endorse or promote products derived from this
|
||||||
|
* software without specific prior written permission.
|
||||||
|
*
|
||||||
|
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
||||||
|
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||||
|
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
||||||
|
* DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY
|
||||||
|
* DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
|
||||||
|
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
|
||||||
|
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
|
||||||
|
* ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||||
|
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
||||||
|
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||||
|
*
|
||||||
|
* http://bitbucket.org/sdorra/scm-manager
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
package sonia.scm.selenium.page;
|
||||||
|
|
||||||
|
import java.util.List;
|
||||||
|
import java.util.Locale;
|
||||||
|
import org.openqa.selenium.By;
|
||||||
|
import org.openqa.selenium.NotFoundException;
|
||||||
|
import org.openqa.selenium.WebDriver;
|
||||||
|
import org.openqa.selenium.WebElement;
|
||||||
|
import org.openqa.selenium.support.FindBy;
|
||||||
|
import sonia.scm.repository.Repository;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Page object for scm-manager's repositories overview page.
|
||||||
|
*
|
||||||
|
* @author Sebastian Sdorra
|
||||||
|
*/
|
||||||
|
public class RepositoriesPage extends BasePage<RepositoriesPage> {
|
||||||
|
|
||||||
|
@FindBy(id = "repositoryAddButton")
|
||||||
|
private WebElement addButton;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Constructs a new page. This constructor should only be called from {@link Pages}.
|
||||||
|
*
|
||||||
|
* @param driver selenium test driver
|
||||||
|
*/
|
||||||
|
RepositoriesPage(WebDriver driver) {
|
||||||
|
super(driver);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected RepositoriesPage self() {
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Creates a new {@link Repository}.
|
||||||
|
*
|
||||||
|
* @param repository repository for creation
|
||||||
|
*
|
||||||
|
* @return {@link this}
|
||||||
|
*/
|
||||||
|
public RepositoriesPage add(Repository repository){
|
||||||
|
addButton.click();
|
||||||
|
RepositoriesAddPage addPage = Pages.get(driver, RepositoriesAddPage.class, this);
|
||||||
|
return addPage.add(repository);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Selects the repository with the given name and returns the detail page object for the selected repository.
|
||||||
|
*
|
||||||
|
* @param repositoryName name of the repository
|
||||||
|
*
|
||||||
|
* @return page object for selected repository
|
||||||
|
*/
|
||||||
|
public RepositoryPage select(String repositoryName){
|
||||||
|
WebElement repositoryNameColumn = null;
|
||||||
|
|
||||||
|
List<WebElement> elements = waitForAll(By.className("x-grid3-col-name"));
|
||||||
|
for (WebElement element : elements){
|
||||||
|
if (element.getText().trim().toLowerCase(Locale.ENGLISH).equals(repositoryName)){
|
||||||
|
repositoryNameColumn = element;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if ( repositoryNameColumn == null ) {
|
||||||
|
throw new NotFoundException("could not find repository " + repositoryName);
|
||||||
|
}
|
||||||
|
|
||||||
|
return Pages.get(driver, RepositoryPage.class, this);
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,77 @@
|
|||||||
|
/**
|
||||||
|
* Copyright (c) 2014, Sebastian Sdorra
|
||||||
|
* All rights reserved.
|
||||||
|
*
|
||||||
|
* Redistribution and use in source and binary forms, with or without
|
||||||
|
* modification, are permitted provided that the following conditions are met:
|
||||||
|
*
|
||||||
|
* 1. Redistributions of source code must retain the above copyright notice,
|
||||||
|
* this list of conditions and the following disclaimer.
|
||||||
|
* 2. Redistributions in binary form must reproduce the above copyright notice,
|
||||||
|
* this list of conditions and the following disclaimer in the documentation
|
||||||
|
* and/or other materials provided with the distribution.
|
||||||
|
* 3. Neither the name of SCM-Manager; nor the names of its
|
||||||
|
* contributors may be used to endorse or promote products derived from this
|
||||||
|
* software without specific prior written permission.
|
||||||
|
*
|
||||||
|
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
||||||
|
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||||
|
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
||||||
|
* DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY
|
||||||
|
* DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
|
||||||
|
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
|
||||||
|
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
|
||||||
|
* ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||||
|
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
||||||
|
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||||
|
*
|
||||||
|
* http://bitbucket.org/sdorra/scm-manager
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
package sonia.scm.selenium.page;
|
||||||
|
|
||||||
|
import org.openqa.selenium.By;
|
||||||
|
import org.openqa.selenium.WebDriver;
|
||||||
|
import org.openqa.selenium.WebElement;
|
||||||
|
import org.openqa.selenium.support.FindBy;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Page object for scm-manager's repository detail page.
|
||||||
|
*
|
||||||
|
* @author Sebastian Sdorra
|
||||||
|
*/
|
||||||
|
public class RepositoryPage extends BasePage<RepositoryPage> {
|
||||||
|
|
||||||
|
@FindBy(css = "#repoRmButton button")
|
||||||
|
private WebElement removeButton;
|
||||||
|
|
||||||
|
private final RepositoriesPage repositoriesPage;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Constructs a new page. This constructor should only be called from {@link Pages}.
|
||||||
|
*
|
||||||
|
* @param driver selenium test driver
|
||||||
|
* @param repositoriesPage repositories page object
|
||||||
|
*/
|
||||||
|
RepositoryPage(WebDriver driver, RepositoriesPage repositoriesPage) {
|
||||||
|
super(driver);
|
||||||
|
this.repositoriesPage = repositoriesPage;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected RepositoryPage self() {
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Removes the selected repository.
|
||||||
|
*
|
||||||
|
* @return repositories overview page object
|
||||||
|
*/
|
||||||
|
public RepositoriesPage remove(){
|
||||||
|
removeButton.click();
|
||||||
|
waitToBeClickable(By.cssSelector("div.x-window button:nth-of-type(1)")).click();
|
||||||
|
return repositoriesPage;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
Reference in New Issue
Block a user