ソースを参照

Merged selenium tests from akquinet (pull request #65)

tags/v1.3.0
James Moger 11年前
コミット
795b227ed3

+ 12
- 0
.classpath ファイルの表示

@@ -38,6 +38,18 @@
<classpathentry kind="lib" path="ext/xz-1.0.jar" sourcepath="ext/src/xz-1.0-sources.jar" />
<classpathentry kind="lib" path="ext/junit-4.10.jar" sourcepath="ext/src/junit-4.10-sources.jar" />
<classpathentry kind="lib" path="ext/hamcrest-core-1.1.jar" />
<classpathentry kind="lib" path="ext/seleniumhq/selenium-java-2.28.0.jar"/>
<classpathentry kind="lib" path="ext/seleniumhq/selenium-api-2.28.0.jar"/>
<classpathentry kind="lib" path="ext/seleniumhq/selenium-remote-driver-2.28.0.jar"/>
<classpathentry kind="lib" path="ext/seleniumhq/selenium-support-2.28.0.jar"/>
<classpathentry kind="lib" path="ext/seleniumhq/guava-12.0.jar"/>
<classpathentry kind="lib" path="ext/seleniumhq/json-20080701.jar"/>
<classpathentry kind="lib" path="ext/seleniumhq/commons-exec-1.1.jar"/>
<classpathentry kind="lib" path="ext/seleniumhq/httpcore-4.2.1.jar"/>
<classpathentry kind="lib" path="ext/seleniumhq/httpmime-4.2.1.jar"/>
<classpathentry kind="lib" path="ext/seleniumhq/httpclient-4.2.1.jar"/>
<classpathentry kind="lib" path="ext/seleniumhq/commons-logging-1.1.1.jar"/>
<classpathentry kind="lib" path="ext/seleniumhq/selenium-firefox-driver-2.28.0.jar"/>
<classpathentry kind="output" path="bin/classes" />
<classpathentry kind="con" path="org.eclipse.jdt.launching.JRE_CONTAINER" />
</classpath>

+ 110
- 4
src/com/gitblit/build/Build.java ファイルの表示

@@ -109,6 +109,20 @@ public class Build {
downloadFromApache(MavenObject.COMMONS_COMPRESS, BuildType.RUNTIME);
downloadFromApache(MavenObject.XZ, BuildType.RUNTIME);
//needed for selenium ui tests
downloadFromApacheToExtSelenium(MavenObject.SEL_API, BuildType.RUNTIME);
downloadFromApacheToExtSelenium(MavenObject.SEL_FF, BuildType.RUNTIME);
downloadFromApacheToExtSelenium(MavenObject.SEL_JAVA, BuildType.RUNTIME);
downloadFromApacheToExtSelenium(MavenObject.SEL_REMOTE, BuildType.RUNTIME);
downloadFromApacheToExtSelenium(MavenObject.SEL_SUPPORT, BuildType.RUNTIME);
downloadFromApacheToExtSelenium(MavenObject.GUAVA, BuildType.RUNTIME);
downloadFromApacheToExtSelenium(MavenObject.JSON, BuildType.RUNTIME);
downloadFromApacheToExtSelenium(MavenObject.COMMONS_EXEC, BuildType.RUNTIME);
downloadFromApacheToExtSelenium(MavenObject.HTTPCLIENT, BuildType.RUNTIME);
downloadFromApacheToExtSelenium(MavenObject.HTTPCORE, BuildType.RUNTIME);
downloadFromApacheToExtSelenium(MavenObject.HTTPMIME, BuildType.RUNTIME);
downloadFromApacheToExtSelenium(MavenObject.COMMONS_LOGGING, BuildType.RUNTIME);
downloadFromEclipse(MavenObject.JGIT, BuildType.RUNTIME);
downloadFromEclipse(MavenObject.JGIT_HTTP, BuildType.RUNTIME);
}
@@ -148,6 +162,20 @@ public class Build {
downloadFromApache(MavenObject.COMMONS_COMPRESS, BuildType.COMPILETIME);
downloadFromApache(MavenObject.XZ, BuildType.COMPILETIME);
//needed for selenium ui tests
downloadFromApacheToExtSelenium(MavenObject.SEL_API, BuildType.COMPILETIME);
downloadFromApacheToExtSelenium(MavenObject.SEL_FF, BuildType.COMPILETIME);
downloadFromApacheToExtSelenium(MavenObject.SEL_JAVA, BuildType.COMPILETIME);
downloadFromApacheToExtSelenium(MavenObject.SEL_REMOTE, BuildType.COMPILETIME);
downloadFromApacheToExtSelenium(MavenObject.SEL_SUPPORT, BuildType.COMPILETIME);
downloadFromApacheToExtSelenium(MavenObject.GUAVA, BuildType.COMPILETIME);
downloadFromApacheToExtSelenium(MavenObject.JSON, BuildType.COMPILETIME);
downloadFromApacheToExtSelenium(MavenObject.COMMONS_EXEC, BuildType.COMPILETIME);
downloadFromApacheToExtSelenium(MavenObject.HTTPCLIENT, BuildType.COMPILETIME);
downloadFromApacheToExtSelenium(MavenObject.HTTPCORE, BuildType.COMPILETIME);
downloadFromApacheToExtSelenium(MavenObject.HTTPMIME, BuildType.COMPILETIME);
downloadFromApacheToExtSelenium(MavenObject.COMMONS_LOGGING, BuildType.COMPILETIME);
downloadFromEclipse(MavenObject.JGIT, BuildType.COMPILETIME);
downloadFromEclipse(MavenObject.JGIT_HTTP, BuildType.COMPILETIME);
@@ -217,7 +245,7 @@ public class Build {
Properties properties = new Properties();
FileInputStream is = null;
try {
is = new FileInputStream(new File("distrib", Constants.PROPERTIES_FILE));
is = new FileInputStream(Constants.PROPERTIES_FILE);
properties.load(is);
} catch (Throwable t) {
t.printStackTrace();
@@ -398,7 +426,7 @@ public class Build {
* the maven object to download.
* @return
*/
private static List<File> downloadFromMaven(String mavenRoot, MavenObject mo, BuildType type) {
private static List<File> downloadFromMaven(String mavenRoot, MavenObject mo, BuildType type, String targetFolder) {
List<File> downloads = new ArrayList<File>();
String[] jars = { "" };
if (BuildType.RUNTIME.equals(type)) {
@@ -407,9 +435,9 @@ public class Build {
jars = new String[] { "-sources" };
}
for (String jar : jars) {
File targetFile = mo.getLocalFile("ext", jar);
File targetFile = mo.getLocalFile(targetFolder, jar);
if ("-sources".equals(jar)) {
File relocated = new File("ext/src", targetFile.getName());
File relocated = new File(targetFolder+"/src", targetFile.getName());
if (targetFile.exists()) {
// move -sources jar to ext/src folder
targetFile.renameTo(relocated);
@@ -502,6 +530,31 @@ public class Build {
return downloads;
}
/**
* Download a file from the official Apache Maven repository.
*
* @param mo
* the maven object to download.
* @return
*/
private static List<File> downloadFromApacheToExtSelenium(MavenObject mo,
BuildType type) {
return downloadFromMaven("http://repo1.maven.org/maven2/", mo, type,
"ext/seleniumhq");
}
/**
* Download a file from the official Apache Maven repository.
*
* @param mo
* the maven object to download.
* @return
*/
private static List<File> downloadFromMaven(String mavenRoot,
MavenObject mo, BuildType type) {
return downloadFromMaven(mavenRoot, mo, type, "ext");
}
private static void removeObsoleteArtifacts(final MavenObject mo, final BuildType type, File folder) {
File [] removals = folder.listFiles(new FilenameFilter() {
@Override
@@ -796,6 +849,59 @@ public class Build {
"ecff5cb8b1189514c9d1d8d68eb77ac372e000c9",
"f95e32a5d2dd8da643c4419814415b9704312993", "");
public static final MavenObject SEL_JAVA = new MavenObject(
"selenium-java", "org/seleniumhq/selenium", "selenium-java",
"2.28.0", 984098, 0, 0,
"7606286989ac9cb942cc206d975ffe187c18d605", "4ede08d293dc153989a337cd0d31d26421433af5", "");
public static final MavenObject SEL_API = new MavenObject(
"selenium-api", "org/seleniumhq/selenium", "selenium-api",
"2.28.0", 984098, 0, 0,
"c4044c40fff65cd25135a5f443638a2b1ccaeac5", "35fc6ec0804ae32b16a56627e69bdcb69995c515", "");
public static final MavenObject SEL_REMOTE = new MavenObject(
"selenium-remote-driver", "org/seleniumhq/selenium",
"selenium-remote-driver", "2.28.0", 984098, 0, 0,
"c67f97cd94e02afec92b0ac881844febb4fc90be", "51a9c30de3c8c203cb7a474a10842443005a5fb4", "");
public static final MavenObject SEL_SUPPORT = new MavenObject(
"selenium-support", "org/seleniumhq/selenium",
"selenium-support", "2.28.0", 984098, 0, 0,
"caf68d6310425f583bc592c08e43066b35eb94f6", "ce3831a601f5f50fda2f4604decde409b6c735a7", "");
public static final MavenObject SEL_FF = new MavenObject(
"selenium-firefox-driver", "org/seleniumhq/selenium",
"selenium-firefox-driver", "2.28.0", 984098, 0, 0,
"a7c34e45dba39e65467b900aa67611aaa039692d", "aa8cd5fb49ca75a53d5b143406ea3d81ab3eddfd", "");
public static final MavenObject GUAVA = new MavenObject("guava",
"com/google/guava", "guava", "12.0", 984098, 0, 0,
"5bc66dd95b79db1e437eb08adba124a3e4088dc0", "f8b98e61865bed3c39b978ee3bf5c7fb990c4032", "");
public static final MavenObject JSON = new MavenObject("json",
"org/json", "json", "20080701", 984098, 0, 0,
"d652f102185530c93b66158b1859f35d45687258", "71bd54221e701df9d112bf9ba2918e13b0671f3a", "");
public static final MavenObject COMMONS_EXEC = new MavenObject(
"commons-exec", "org/apache/commons", "commons-exec", "1.1",
984098, 0, 0, "07dfdf16fade726000564386825ed6d911a44ba1", "f60bea898e18b308099862e8634d589b06a8b0be",
"");
public static final MavenObject HTTPCORE = new MavenObject("httpcore",
"org/apache/httpcomponents", "httpcore", "4.2.1", 984098, 0, 0,
"2d503272bf0a8b5f92d64db78b4ba9abbaccc6fd", "3f6caf5334fa83607b82e2f32dd128a9d8a0ea5e", "");
public static final MavenObject HTTPMIME = new MavenObject("httpmime",
"org/apache/httpcomponents", "httpmime", "4.2.1", 984098, 0, 0,
"7c772bace9aa31a728c39a88c6ff66a7cd177e89", "", "4e453843ae47f1c2d70e2eb2c13c037de4b614c4");
public static final MavenObject HTTPCLIENT = new MavenObject(
"httpclient", "org/apache/httpcomponents", "httpclient",
"4.2.1", 984098, 0, 0,
"b69bd03af60bf487b3ae1209a644ecac587bf6fc", "6b27312b9c28b59aaeb6c21f3490045690c703d3", "");
public static final MavenObject COMMONS_LOGGING = new MavenObject(
"commons-logging", "commons-logging", "commons-logging",
"1.1.1", 984098, 0, 0,
"5043bfebc3db072ed80fbd362e7caf00e885d8ae", "f3f156cbff0e0fb0d64bfce31a352cce4a33bc19", "");
public final String name;
public final String group;
public final String artifact;

+ 1203
- 0
test-ui-gitblit.properties
ファイル差分が大きすぎるため省略します
ファイルの表示


+ 44
- 0
test-ui-users.conf ファイルの表示

@@ -0,0 +1,44 @@
[user "admin"]
password = admin
cookie = dd94709528bb1c83d08f3088d4043f4742891f4f
role = "#admin"
role = "#notfederated"
[user "userthree"]
password = StoredInLDAP
cookie = d7d3894fc517612aa6c595555b6e1ab8e147e597
displayName = User Three
emailAddress = userthree@gitblit.com
role = "#admin"
[user "userone"]
password = StoredInLDAP
cookie = c97cd38e50858cd0b389ec61b18fb9a89b4da54c
displayName = User One
emailAddress = User.One@gitblit.com
role = "#admin"
[user "usertwo"]
password = StoredInLDAP
cookie = 498ca9bd2841d39050fa45d1d737b9f9f767858d
displayName = User Two
emailAddress = usertwo@gitblit.com
role = "#admin"
[user "basic"]
password = MD5:f17aaabc20bfe045075927934fed52d2
cookie = dd94709528bb1c83d08f3088d4043f4742891f4f
role = "#fork"
repository = RW:~repocreator/shb.git
repository = V:test/gitective.git
[user "repocreator"]
password = MD5:b77e53bb561c47368d133b22e285f60b
cookie = dd94709528bb1c83d08f3088d4043f4742891f4f
role = "#create"
[team "Git_Admins"]
role = "#none"
user = userone
[team "Git_Users"]
role = "#none"
user = userone
user = usertwo
user = userthree
[team "Git Admins"]
role = "#none"
user = usertwo

+ 134
- 0
tests/de/akquinet/devops/GitblitRunnable.java ファイルの表示

@@ -0,0 +1,134 @@
/*
* Copyright 2013 akquinet tech@spree GmbH
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package de.akquinet.devops;

import java.net.InetAddress;
import java.net.ServerSocket;

import com.gitblit.GitBlitServer;
import com.gitblit.tests.GitBlitSuite;

/**
* This is a runnable implementation, that is used to run a gitblit server in a
* separate thread (e.g. alongside test cases)
*
* @author saheba
*
*/
public class GitblitRunnable implements Runnable {

private int httpPort, httpsPort, shutdownPort;
private String userPropertiesPath, gitblitPropertiesPath;
private boolean startFailed = false;

/**
* constructor with reduced set of start params
*
* @param httpPort
* @param httpsPort
* @param shutdownPort
* @param gitblitPropertiesPath
* @param userPropertiesPath
*/
public GitblitRunnable(int httpPort, int httpsPort, int shutdownPort,
String gitblitPropertiesPath, String userPropertiesPath) {
this.httpPort = httpPort;
this.httpsPort = httpsPort;
this.shutdownPort = shutdownPort;
this.userPropertiesPath = userPropertiesPath;
this.gitblitPropertiesPath = gitblitPropertiesPath;
}

/*
* (non-Javadoc)
*
* @see java.lang.Runnable#run()
*/
public void run() {
boolean portsFree = false;
long lastRun = -1;
while (!portsFree) {
long current = System.currentTimeMillis();
if (lastRun == -1 || lastRun + 100 < current) {
portsFree = areAllPortsFree(new int[] { httpPort, httpsPort,
shutdownPort }, "127.0.0.1");
}
lastRun = current;

}
try {
GitBlitServer.main("--httpPort", "" + httpPort, "--httpsPort", ""
+ httpsPort, "--shutdownPort", "" + shutdownPort,
"--repositoriesFolder",
"\"" + GitBlitSuite.REPOSITORIES.getAbsolutePath() + "\"",
"--userService", userPropertiesPath, "--settings",
gitblitPropertiesPath);
setStartFailed(false);
} catch (Exception iex) {
System.out.println("Gitblit server start failed");
setStartFailed(true);
}
}

/**
* Method used to ensure that all ports are free, if the runnable is used
* JUnit test classes. Be aware that JUnit's setUpClass and tearDownClass
* methods, which are executed before and after a test class (consisting of
* several test cases), may be executed parallely if they are part of a test
* suite consisting of several test classes. Therefore the run method of
* this class calls areAllPortsFree to check port availability before
* starting another gitblit instance.
*
* @param ports
* @param inetAddress
* @return
*/
public static boolean areAllPortsFree(int[] ports, String inetAddress) {
System.out
.println("\n"
+ System.currentTimeMillis()
+ " ----------------------------------- testing if all ports are free ...");
String blockedPorts = "";
for (int i = 0; i < ports.length; i++) {
ServerSocket s;
try {
s = new ServerSocket(ports[i], 1,
InetAddress.getByName(inetAddress));
s.close();
} catch (Exception e) {
if (!blockedPorts.equals("")) {
blockedPorts += ", ";
}
}
}
if (blockedPorts.equals("")) {
System.out
.println(" ----------------------------------- ... verified");
return true;
}
System.out.println(" ----------------------------------- ... "
+ blockedPorts + " are still blocked");
return false;
}

private void setStartFailed(boolean startFailed) {
this.startFailed = startFailed;
}

public boolean isStartFailed() {
return startFailed;
}
}

+ 126
- 0
tests/de/akquinet/devops/LaunchWithUITestConfig.java ファイルの表示

@@ -0,0 +1,126 @@
/*
* Copyright 2013 akquinet tech@spree GmbH
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package de.akquinet.devops;

import java.io.IOException;
import java.io.OutputStream;
import java.net.InetAddress;
import java.net.Socket;
import java.net.UnknownHostException;

import junit.framework.Assert;

import org.junit.Test;

import com.gitblit.Constants;
import com.gitblit.GitBlitServer;
import com.gitblit.tests.GitBlitSuite;

/**
* This test checks if it is possible to run two server instances in the same
* JVM sequentially
*
* @author saheba
*
*/
public class LaunchWithUITestConfig {

@Test
public void testSequentialLaunchOfSeveralInstances()
throws InterruptedException {
// different ports than in testParallelLaunchOfSeveralInstances to
// ensure that both test cases do not affect each others test results
int httpPort = 9191, httpsPort = 9292, shutdownPort = 9393;
String gitblitPropertiesPath = "test-ui-gitblit.properties", usersPropertiesPath = "test-ui-users.conf";

GitblitRunnable gitblitRunnable = new GitblitRunnable(httpPort,
httpsPort, shutdownPort, gitblitPropertiesPath,
usersPropertiesPath);
Thread serverThread = new Thread(gitblitRunnable);
serverThread.start();
Thread.sleep(2000);
Assert.assertFalse(gitblitRunnable.isStartFailed());
LaunchWithUITestConfig.shutdownGitBlitServer(shutdownPort);

Thread.sleep(5000);

GitblitRunnable gitblitRunnable2 = new GitblitRunnable(httpPort,
httpsPort, shutdownPort, gitblitPropertiesPath,
usersPropertiesPath);
Thread serverThread2 = new Thread(gitblitRunnable2);
serverThread2.start();
Thread.sleep(2000);
Assert.assertFalse(gitblitRunnable2.isStartFailed());
LaunchWithUITestConfig.shutdownGitBlitServer(shutdownPort);
}

@Test
public void testParallelLaunchOfSeveralInstances()
throws InterruptedException {
// different ports than in testSequentialLaunchOfSeveralInstances to
// ensure that both test cases do not affect each others test results
int httpPort = 9797, httpsPort = 9898, shutdownPort = 9999;
int httpPort2 = 9494, httpsPort2 = 9595, shutdownPort2 = 9696;
String gitblitPropertiesPath = "test-ui-gitblit.properties", usersPropertiesPath = "test-ui-users.conf";

GitblitRunnable gitblitRunnable = new GitblitRunnable(httpPort,
httpsPort, shutdownPort, gitblitPropertiesPath,
usersPropertiesPath);
Thread serverThread = new Thread(gitblitRunnable);
serverThread.start();
Thread.sleep(2000);
Assert.assertFalse(gitblitRunnable.isStartFailed());

GitblitRunnable gitblitRunnable2 = new GitblitRunnable(httpPort2,
httpsPort2, shutdownPort2, gitblitPropertiesPath,
usersPropertiesPath);
Thread serverThread2 = new Thread(gitblitRunnable2);
serverThread2.start();
Thread.sleep(2000);
Assert.assertFalse(gitblitRunnable2.isStartFailed());

LaunchWithUITestConfig.shutdownGitBlitServer(shutdownPort);
LaunchWithUITestConfig.shutdownGitBlitServer(shutdownPort2);
}

/**
* main runs the tests without assert checks. You have to check the console
* output manually.
*
* @param args
* @throws InterruptedException
*/
public static void main(String[] args) throws InterruptedException {
new LaunchWithUITestConfig().testSequentialLaunchOfSeveralInstances();
new LaunchWithUITestConfig().testParallelLaunchOfSeveralInstances();
}

private static void shutdownGitBlitServer(int shutdownPort) {
try {
Socket s = new Socket(InetAddress.getByName("127.0.0.1"),
shutdownPort);
OutputStream out = s.getOutputStream();
System.out.println("Sending Shutdown Request to " + Constants.NAME);
out.write("\r\n".getBytes());
out.flush();
s.close();
} catch (UnknownHostException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
}
}

+ 14
- 0
tests/de/akquinet/devops/ManualUITestLaunch.java ファイルの表示

@@ -0,0 +1,14 @@
package de.akquinet.devops;

public class ManualUITestLaunch {
public static void main(String[] args) {
int httpPort = 8080, httpsPort = 8443, shutdownPort = 8081;
String gitblitPropertiesPath = "test-ui-gitblit.properties", usersPropertiesPath = "test-ui-users.conf";

GitblitRunnable gitblitRunnable = new GitblitRunnable(httpPort,
httpsPort, shutdownPort, gitblitPropertiesPath,
usersPropertiesPath);
Thread serverThread = new Thread(gitblitRunnable);
serverThread.start();
}
}

+ 33
- 0
tests/de/akquinet/devops/test/ui/TestUISuite.java ファイルの表示

@@ -0,0 +1,33 @@
/*
* Copyright 2013 akquinet tech@spree GmbH
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package de.akquinet.devops.test.ui;

import org.junit.runner.RunWith;
import org.junit.runners.Suite;

import de.akquinet.devops.test.ui.cases.UI_MultiAdminSupportTest;

/**
* the test suite including all selenium-based ui-tests.
*
* @author saheba
*
*/
@RunWith(Suite.class)
@Suite.SuiteClasses({ UI_MultiAdminSupportTest.class })
public class TestUISuite {

}

+ 93
- 0
tests/de/akquinet/devops/test/ui/cases/UI_MultiAdminSupportTest.java ファイルの表示

@@ -0,0 +1,93 @@
/*
* Copyright 2013 akquinet tech@spree GmbH
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package de.akquinet.devops.test.ui.cases;

import org.junit.Assert;
import org.junit.Before;
import org.junit.Test;

import de.akquinet.devops.test.ui.generic.AbstractUITest;
import de.akquinet.devops.test.ui.view.RepoEditView;
import de.akquinet.devops.test.ui.view.RepoListView;

/**
* tests the multi admin per repo feature.
*
* @author saheba
*
*/
public class UI_MultiAdminSupportTest extends AbstractUITest {

String baseUrl = "https://localhost:8443";
RepoListView view;
RepoEditView editView;
private static final String TEST_MULTI_ADMIN_SUPPORT_REPO_NAME = "testmultiadminsupport";
private static final String TEST_MULTI_ADMIN_SUPPORT_REPO_PATH = "~repocreator/"
+ TEST_MULTI_ADMIN_SUPPORT_REPO_NAME + ".git";
private static final String TEST_MULTI_ADMIN_SUPPORT_REPO_PATH_WITHOUT_SUFFIX = "~repocreator/"
+ TEST_MULTI_ADMIN_SUPPORT_REPO_NAME;

@Before
public void before() {
System.out.println("IN BEFORE");
this.view = new RepoListView(AbstractUITest.getDriver(), baseUrl);
this.editView = new RepoEditView(AbstractUITest.getDriver());
AbstractUITest.getDriver().navigate().to(baseUrl);
}

@Test
public void test_MultiAdminSelectionInStandardRepo() {
// login
view.login("repocreator", "repocreator");

// create new repo
view.navigateToNewRepo(1);
editView.changeName(TEST_MULTI_ADMIN_SUPPORT_REPO_PATH);
Assert.assertTrue(editView.navigateToPermissionsTab());

Assert.assertTrue(editView
.changeAccessRestriction(RepoEditView.RESTRICTION_AUTHENTICATED_VCP));
Assert.assertTrue(editView
.changeAuthorizationControl(RepoEditView.AUTHCONTROL_RWALL));

// with a second admin
editView.addRepoAdministrator("admin");
Assert.assertTrue(editView.save());
// user is automatically forwarded to repo list view
Assert.assertTrue(view.isEmptyRepo(TEST_MULTI_ADMIN_SUPPORT_REPO_PATH));
Assert.assertTrue(view
.isEditableRepo(TEST_MULTI_ADMIN_SUPPORT_REPO_PATH));
Assert.assertTrue(view
.isDeletableRepo(TEST_MULTI_ADMIN_SUPPORT_REPO_PATH_WITHOUT_SUFFIX));
// logout repocreator
view.logout();

// check with admin account if second admin has the same rights
view.login("admin", "admin");
Assert.assertTrue(view.isEmptyRepo(TEST_MULTI_ADMIN_SUPPORT_REPO_PATH));
Assert.assertTrue(view
.isEditableRepo(TEST_MULTI_ADMIN_SUPPORT_REPO_PATH));
Assert.assertTrue(view
.isDeletableRepo(TEST_MULTI_ADMIN_SUPPORT_REPO_PATH_WITHOUT_SUFFIX));
// delete repo to reach state as before test execution
view.navigateToDeleteRepo(TEST_MULTI_ADMIN_SUPPORT_REPO_PATH_WITHOUT_SUFFIX);
view.acceptAlertDialog();
view.logout();

Assert.assertTrue(view.isLoginPartVisible());
}

}

+ 96
- 0
tests/de/akquinet/devops/test/ui/generic/AbstractUITest.java ファイルの表示

@@ -0,0 +1,96 @@
/*
* Copyright 2013 akquinet tech@spree GmbH
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package de.akquinet.devops.test.ui.generic;

import org.junit.AfterClass;
import org.junit.BeforeClass;
import org.openqa.selenium.WebDriver;
import org.openqa.selenium.firefox.FirefoxDriver;
import org.openqa.selenium.firefox.FirefoxProfile;

import com.gitblit.GitBlitServer;

import de.akquinet.devops.GitblitRunnable;

/**
* This abstract class implements the setUpClass and tearDownClass for
* selenium-based UITests. They require a running gitblit server instance and a
* webdriver instance, which are managed by the setUpClass and tearDownClass
* method. Write a separate test class derived from this abstract class for each
* scenario consisting of one or more test cases, which can share the same
* server instance.
*
* @author saheba
*
*/
public abstract class AbstractUITest {

private static Thread serverThread;
private static WebDriver driver;

private static final int HTTP_PORT = 8080, HTTPS_PORT = 8443,
SHUTDOWN_PORT = 8081;
private static final String GITBLIT_PROPERTIES_PATH = "test-ui-gitblit.properties",
USERS_PROPERTIES_PATH = "test-ui-users.conf";

/**
* starts a gitblit server instance in a separate thread before test cases
* of concrete, non-abstract child-classes are executed
*/
@BeforeClass
public static void setUpClass() {
Runnable gitblitRunnable = new GitblitRunnable(HTTP_PORT, HTTPS_PORT,
SHUTDOWN_PORT, GITBLIT_PROPERTIES_PATH, USERS_PROPERTIES_PATH);

serverThread = new Thread(gitblitRunnable);
serverThread.start();
FirefoxProfile firefoxProfile = new FirefoxProfile();
firefoxProfile.setPreference("startup.homepage_welcome_url",
"https://www.google.de");

firefoxProfile.setPreference("browser.download.folderList", 2);
firefoxProfile.setPreference(
"browser.download.manager.showWhenStarting", false);
String downloadDir = System.getProperty("java.io.tmpdir");
firefoxProfile.setPreference("browser.download.dir", downloadDir);
firefoxProfile.setPreference("browser.helperApps.neverAsk.saveToDisk",
"text/csv,text/plain,application/zip,application/pdf");
firefoxProfile.setPreference("browser.helperApps.alwaysAsk.force",
false);
System.out.println("Saving all attachments to: " + downloadDir);

driver = new FirefoxDriver(firefoxProfile);
}

/**
* stops the gitblit server instance running in a separate thread after test
* cases of concrete, non-abstract child-classes have been executed
*/
@AfterClass
public static void tearDownClass() throws InterruptedException {
driver.close();
// Stop Gitblit
GitBlitServer.main("--stop", "--shutdownPort", "" + SHUTDOWN_PORT);

// Wait a few seconds for it to be running completely including thread
// destruction
Thread.sleep(1000);
}

public static WebDriver getDriver() {
return AbstractUITest.driver;
}
}

+ 45
- 0
tests/de/akquinet/devops/test/ui/view/Exp.java ファイルの表示

@@ -0,0 +1,45 @@
/*
* Copyright 2013 akquinet tech@spree GmbH
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package de.akquinet.devops.test.ui.view;

import java.util.List;

import org.openqa.selenium.By;
import org.openqa.selenium.WebDriver;
import org.openqa.selenium.WebElement;
import org.openqa.selenium.support.ui.ExpectedCondition;

/**
* container class for selenium conditions
*
* @author saheba
*
*/
public class Exp {
public static class EditRepoViewLoaded implements ExpectedCondition<Boolean> {
public Boolean apply(WebDriver d) {
List<WebElement> findElements = d.findElements(By.partialLinkText("general"));
return findElements.size() == 1;
}
}
public static class RepoListViewLoaded implements ExpectedCondition<Boolean> {
public Boolean apply(WebDriver d) {
String xpath = "//img[@src=\"git-black-16x16.png\"]";
List<WebElement> findElements = d.findElements(By.xpath(xpath ));
return findElements.size() == 1;
}
}
}

+ 100
- 0
tests/de/akquinet/devops/test/ui/view/GitblitDashboardView.java ファイルの表示

@@ -0,0 +1,100 @@
/*
* Copyright 2013 akquinet tech@spree GmbH
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package de.akquinet.devops.test.ui.view;

import java.util.List;

import org.openqa.selenium.By;
import org.openqa.selenium.WebDriver;
import org.openqa.selenium.WebElement;
import org.openqa.selenium.support.ui.ExpectedCondition;
import org.openqa.selenium.support.ui.WebDriverWait;

/**
* class representing the view componenents and possible user interactions, you
* can see and do on most screens when you are logged in.
*
* @author saheba
*
*/
public class GitblitDashboardView extends GitblitPageView {

public static final String TITLE_STARTS_WITH = "localhost";

public GitblitDashboardView(WebDriver driver, String baseUrl) {
super(driver, baseUrl);
}

public boolean isLoginPartVisible() {
List<WebElement> found = getDriver().findElements(
By.partialLinkText("logout"));
return found == null || found.size() == 0;
}

public void logout() {
// String pathLogout = "//a[@href =\"?" + WICKET_HREF_PAGE_PATH
// + ".LogoutPage\"]";
// List<WebElement> logout =
// getDriver().findElements(By.xpath(pathLogout));
// logout.get(0).click();
// replaced by url call because click hangs sometimes if the clicked
// object is not a button or selenium ff driver does not notice the
// change for any other reason
getDriver().navigate().to(
getBaseUrl() + "?" + WICKET_HREF_PAGE_PATH + ".LogoutPage");
}

public static final String LOGIN_AREA_SELECTOR = "//span[@class = \"form-search\" ]";
public static final String WICKET_PAGES_PACKAGE_NAME = "com.gitblit.wicket.pages";
public static final String WICKET_HREF_PAGE_PATH = "wicket:bookmarkablePage=:"
+ WICKET_PAGES_PACKAGE_NAME;

synchronized public void waitToLoadFor(int sec) {
WebDriverWait webDriverWait = new WebDriverWait(getDriver(), sec);
webDriverWait.until(new ExpectedCondition<Boolean>() {
public Boolean apply(WebDriver d) {
return d.getTitle().toLowerCase()
.startsWith(GitblitDashboardView.TITLE_STARTS_WITH);
}
});
}

public void login(String id, String pw) {
String pathID = LOGIN_AREA_SELECTOR + "/input[@name = \"username\" ]";
String pathPW = LOGIN_AREA_SELECTOR + "/input[@name = \"password\" ]";
String pathSubmit = LOGIN_AREA_SELECTOR
+ "/button[@type = \"submit\" ]";
// System.out.println("DRIVER:"+getDriver());
// List<WebElement> findElement =
// getDriver().findElements(By.xpath("//span[@class = \"form-search\" ]"));
//
// System.out.println("ELEM: "+findElement);
// System.out.println("SIZE: "+findElement.size());
// System.out.println("XPath: "+pathID);
WebElement idField = getDriver().findElement(By.xpath(pathID));
// System.out.println("IDFIELD:"+idField);
idField.sendKeys(id);
WebElement pwField = getDriver().findElement(By.xpath(pathPW));
// System.out.println(pwField);
pwField.sendKeys(pw);
WebElement submit = getDriver().findElement(By.xpath(pathSubmit));
submit.click();
}

public void acceptAlertDialog() {
getDriver().switchTo().alert().accept();
}
}

+ 73
- 0
tests/de/akquinet/devops/test/ui/view/GitblitPageView.java ファイルの表示

@@ -0,0 +1,73 @@
/*
* Copyright 2013 akquinet tech@spree GmbH
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package de.akquinet.devops.test.ui.view;

import org.openqa.selenium.JavascriptExecutor;
import org.openqa.selenium.WebDriver;
import org.openqa.selenium.WebElement;

/**
* general basic class representing a gitblit webpage and offering basic methods
* used in selenium tests.
*
* @author saheba
*
*/
public class GitblitPageView {
private WebDriver driver;
private String baseUrl;

public GitblitPageView(WebDriver driver, String baseUrl) {
this.driver = driver;
this.baseUrl = baseUrl;
}

public void sleep(int miliseconds) {
try {
Thread.sleep(miliseconds);
} catch (InterruptedException e) {
e.printStackTrace();
}
}

public WebElement getElementWithFocus() {
String elScript = "return document.activeElement;";

WebElement focuseedEl = (WebElement) ((JavascriptExecutor) getDriver())
.executeScript(elScript);
return focuseedEl;
}

public void navigateToPreviousPageOfBrowserHistory() {
driver.navigate().back();
}

public void setDriver(WebDriver driver) {
this.driver = driver;
}

public WebDriver getDriver() {
return driver;
}

public void setBaseUrl(String baseUrl) {
this.baseUrl = baseUrl;
}

public String getBaseUrl() {
return baseUrl;
}
}

+ 158
- 0
tests/de/akquinet/devops/test/ui/view/RepoEditView.java ファイルの表示

@@ -0,0 +1,158 @@
/*
* Copyright 2013 akquinet tech@spree GmbH
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package de.akquinet.devops.test.ui.view;

import java.util.List;

import org.openqa.selenium.By;
import org.openqa.selenium.WebDriver;
import org.openqa.selenium.WebElement;
import org.openqa.selenium.support.ui.WebDriverWait;

/**
* class representing the tabs you can access when you edit a repo.
*
* @author saheba
*
*/
public class RepoEditView extends GitblitDashboardView {

public static final String PERMISSION_VIEW_USERS_NAME_PREFIX = "users:";
public static final String PERMISSION_VIEW_TEAMS_NAME_PREFIX = "teams:";

public static final String PERMISSION_VIEW_MUTABLE = "permissionToggleForm:showMutable";
public static final String PERMISSION_VIEW_SPECIFIED = "permissionToggleForm:showSpecified";
public static final String PERMISSION_VIEW_EFFECTIVE = "permissionToggleForm:showEffective";

public static final int RESTRICTION_ANONYMOUS_VCP = 0;
public static final int RESTRICTION_AUTHENTICATED_P = 1;
public static final int RESTRICTION_AUTHENTICATED_CP = 2;
public static final int RESTRICTION_AUTHENTICATED_VCP = 3;

public static final int AUTHCONTROL_RWALL = 0;
public static final int AUTHOCONTROL_FINE = 1;

public RepoEditView(WebDriver driver) {
super(driver, null);
}

public void changeName(String newName) {
String pathName = "//input[@id = \"name\" ]";
WebElement field = getDriver().findElement(By.xpath(pathName));
field.clear();
field.sendKeys(newName);
}

public boolean navigateToPermissionsTab() {
String linkText = "access permissions";
List<WebElement> found = getDriver().findElements(
By.partialLinkText(linkText));
System.out.println("PERM TABS found =" + found.size());
if (found != null && found.size() == 1) {
found.get(0).click();
return true;
}
return false;
}

private void changeRepoAdministrators(String action,
String affectedSelection, String username) {
String xpath = "//select[@name=\"" + affectedSelection
+ "\"]/option[@value = \"" + username + "\" ]";
WebElement option = getDriver().findElement(By.xpath(xpath));
option.click();
String buttonPath = "//button[@class=\"button " + action + "\"]";
WebElement button = getDriver().findElement(By.xpath(buttonPath));
button.click();
}

public void removeRepoAdministrator(String username) {
changeRepoAdministrators("remove", "repoAdministrators:selection",
username);
}

public void addRepoAdministrator(String username) {
changeRepoAdministrators("add", "repoAdministrators:choices", username);
}

public WebElement getAccessRestrictionSelection() {
String xpath = "//select[@name =\"accessRestriction\"]";
List<WebElement> found = getDriver().findElements(By.xpath(xpath));
if (found != null && found.size() == 1) {
return found.get(0);
}
return null;
}

public boolean changeAccessRestriction(int option) {
WebElement accessRestrictionSelection = getAccessRestrictionSelection();
if (accessRestrictionSelection == null) {
return false;
}
accessRestrictionSelection.click();
sleep(100);
String xpath = "//select[@name =\"accessRestriction\"]/option[@value=\""
+ option + "\"]";
List<WebElement> found = getDriver().findElements(By.xpath(xpath));
if (found == null || found.size() == 0 || found.size() > 1) {
return false;
}
found.get(0).click();
return true;
}

public boolean changeAuthorizationControl(int option) {
System.out.println("try to change auth control");
String xpath = "//input[@name =\"authorizationControl\" and @value=\""
+ option + "\"]";
List<WebElement> found = getDriver().findElements(By.xpath(xpath));
System.out.println("found auth CONTROL options " + found.size());
if (found == null || found.size() == 0 || found.size() > 1) {
return false;
}
found.get(0).click();
return true;
}

private boolean isPermissionViewDisabled(String prefix, String view) {
String xpath = "//[@name =\"" + prefix + view + "\"]";
List<WebElement> found = getDriver().findElements(By.xpath(xpath));
if (found == null || found.size() == 0 || found.size() > 1) {
return false;
}
String attrValue = found.get(0).getAttribute("disabled");
return (attrValue != null) && (attrValue.equals("disabled"));
}

public boolean isPermissionViewSectionDisabled(String prefix) {
return isPermissionViewDisabled(prefix, PERMISSION_VIEW_MUTABLE)
&& isPermissionViewDisabled(prefix, PERMISSION_VIEW_SPECIFIED)
&& isPermissionViewDisabled(prefix, PERMISSION_VIEW_EFFECTIVE);
}

public boolean save() {
String xpath = "//div[@class=\"form-actions\"]/input[@name =\""
+ "save" + "\"]";
List<WebElement> found = getDriver().findElements(By.xpath(xpath));
if (found == null || found.size() == 0 || found.size() > 1) {
return false;
}
found.get(0).click();
WebDriverWait webDriverWait = new WebDriverWait(getDriver(), 1);
webDriverWait.until(new Exp.RepoListViewLoaded());
return true;
}
}

+ 130
- 0
tests/de/akquinet/devops/test/ui/view/RepoListView.java ファイルの表示

@@ -0,0 +1,130 @@
/*
* Copyright 2013 akquinet tech@spree GmbH
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package de.akquinet.devops.test.ui.view;

import java.util.List;

import org.openqa.selenium.By;
import org.openqa.selenium.WebDriver;
import org.openqa.selenium.WebElement;
import org.openqa.selenium.support.ui.WebDriverWait;

/**
* class representing the repo list view, which you see e.g. right after you
* logged in.
*
* @author saheba
*
*/
public class RepoListView extends GitblitDashboardView {

public RepoListView(WebDriver driver, String baseUrl) {
super(driver, baseUrl);
}
public boolean isEmptyRepo(String fullyQualifiedRepoName) {
String pathToLink = "//a[@href = \"?" + WICKET_HREF_PAGE_PATH
+ ".EmptyRepositoryPage&r=" + fullyQualifiedRepoName + "\"]";
List<WebElement> found = getDriver().findElements(By.xpath(pathToLink));
return found != null && found.size() > 0;
}

private String getEditRepoPath(String fullyQualifiedRepoName) {
return "//a[@href =\"?" + WICKET_HREF_PAGE_PATH
+ ".EditRepositoryPage&r=" + fullyQualifiedRepoName + "\"]";
}

private String getDeleteRepoOnclickIdentifier(
String fullyQualifiedRepoPathAndName) {
return "var conf = confirm('Delete repository \""
+ fullyQualifiedRepoPathAndName
+ "\"?'); if (!conf) return false; ";
}

public boolean navigateToNewRepo(long waitSecToLoad) {
String pathToLink = "//a[@href =\"?" + WICKET_HREF_PAGE_PATH
+ ".EditRepositoryPage\"]";
List<WebElement> found = getDriver().findElements(By.xpath(pathToLink));
if (found == null || found.size() == 0 || found.size() > 1) {
return false;
}
found.get(0).click();
WebDriverWait webDriverWait = new WebDriverWait(getDriver(),
waitSecToLoad);
webDriverWait.until(new Exp.EditRepoViewLoaded());
return true;
}

private boolean checkOrDoEditRepo(String fullyQualifiedRepoName,
boolean doEdit) {
List<WebElement> found = getDriver().findElements(
By.xpath(getEditRepoPath(fullyQualifiedRepoName)));
if (found == null || found.size() == 0 || found.size() > 1) {
return false;
}
if (doEdit) {
found.get(0).click();
}
return true;
}

public boolean navigateToEditRepo(String fullyQualifiedRepoName,
int waitSecToLoad) {
boolean result = checkOrDoEditRepo(fullyQualifiedRepoName, true);
WebDriverWait webDriverWait = new WebDriverWait(getDriver(),
waitSecToLoad);
webDriverWait.until(new Exp.EditRepoViewLoaded());
return result;
}

public boolean isEditableRepo(String fullyQualifiedRepoName) {
return checkOrDoEditRepo(fullyQualifiedRepoName, false);
}

private boolean checkOrDoDeleteRepo(String fullyQualifiedRepoPathAndName,
boolean doDelete) {
List<WebElement> found = getDriver().findElements(
By.partialLinkText("delete"));
String onclickIdentifier = getDeleteRepoOnclickIdentifier(fullyQualifiedRepoPathAndName);
WebElement result = null;
for (WebElement webElement : found) {
if (webElement.getAttribute("onclick") != null
&& webElement.getAttribute("onclick").equals(
onclickIdentifier)) {
result = webElement;
break;
}
}
System.out.println("result ? " + result);
if (result == null) {
return false;
}
if (doDelete) {
System.out.println(".............. DO DELETE .... ");
result.click();
}
return true;
}

public boolean isDeletableRepo(String fullyQualifiedRepoPathAndName) {
return checkOrDoDeleteRepo(fullyQualifiedRepoPathAndName, false);
}

public boolean navigateToDeleteRepo(String fullyQualifiedRepoPathAndName) {
return checkOrDoDeleteRepo(fullyQualifiedRepoPathAndName, true);

}
}

読み込み中…
キャンセル
保存