James Moger
2013-01-23 795b227ed376f6ea9a6e13952a79770f33766266
Merged selenium tests from akquinet (pull request #65)
13 files added
2 files modified
2375 ■■■■■ changed files
.classpath 12 ●●●●● patch | view | raw | blame | history
src/com/gitblit/build/Build.java 114 ●●●●● patch | view | raw | blame | history
test-ui-gitblit.properties 1203 ●●●●● patch | view | raw | blame | history
test-ui-users.conf 44 ●●●●● patch | view | raw | blame | history
tests/de/akquinet/devops/GitblitRunnable.java 134 ●●●●● patch | view | raw | blame | history
tests/de/akquinet/devops/LaunchWithUITestConfig.java 126 ●●●●● patch | view | raw | blame | history
tests/de/akquinet/devops/ManualUITestLaunch.java 14 ●●●●● patch | view | raw | blame | history
tests/de/akquinet/devops/test/ui/TestUISuite.java 33 ●●●●● patch | view | raw | blame | history
tests/de/akquinet/devops/test/ui/cases/UI_MultiAdminSupportTest.java 93 ●●●●● patch | view | raw | blame | history
tests/de/akquinet/devops/test/ui/generic/AbstractUITest.java 96 ●●●●● patch | view | raw | blame | history
tests/de/akquinet/devops/test/ui/view/Exp.java 45 ●●●●● patch | view | raw | blame | history
tests/de/akquinet/devops/test/ui/view/GitblitDashboardView.java 100 ●●●●● patch | view | raw | blame | history
tests/de/akquinet/devops/test/ui/view/GitblitPageView.java 73 ●●●●● patch | view | raw | blame | history
tests/de/akquinet/devops/test/ui/view/RepoEditView.java 158 ●●●●● patch | view | raw | blame | history
tests/de/akquinet/devops/test/ui/view/RepoListView.java 130 ●●●●● patch | view | raw | blame | history
.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>
src/com/gitblit/build/Build.java
@@ -109,6 +109,20 @@
        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 @@
        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 @@
        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 @@
     *            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 @@
            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);
@@ -500,6 +528,31 @@
            removeObsoleteArtifacts(mo, type, targetFile.getParentFile());
        }
        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) {
@@ -796,6 +849,59 @@
                "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;
test-ui-gitblit.properties
New file
@@ -0,0 +1,1203 @@
#
# Git Servlet Settings
#
# Base folder for repositories.
# This folder may contain bare and non-bare repositories but Gitblit will only
# allow you to push to bare repositories.
# Use forward slashes even on Windows!!
# e.g. c:/gitrepos
#
# SINCE 0.5.0
# RESTART REQUIRED
git.repositoriesFolder = ${baseFolder}/git
# Build the available repository list at startup and cache this list for reuse.
# This reduces disk io when presenting the repositories page, responding to rpcs,
# etc, but it means that  Gitblit will not automatically identify repositories
# added or deleted by external tools.
#
# For this case you can use curl, wget, etc to issue an rpc request to clear the
# cache (e.g. https://localhost/rpc?req=CLEAR_REPOSITORY_CACHE)
#
# SINCE 1.1.0
git.cacheRepositoryList = true
# Search the repositories folder subfolders for other repositories.
# Repositories MAY NOT be nested (i.e. one repository within another)
# but they may be grouped together in subfolders.
# e.g. c:/gitrepos/libraries/mylibrary.git
#      c:/gitrepos/libraries/myotherlibrary.git
#
# SINCE 0.5.0
git.searchRepositoriesSubfolders = true
# Maximum number of folders to recurse into when searching for repositories.
# The default value, -1, disables depth limits.
#
# SINCE 1.1.0
git.searchRecursionDepth = -1
# List of regex exclusion patterns to match against folders found in
# *git.repositoriesFolder*.
# Use forward slashes even on Windows!!
# e.g. test/jgit\.git
#
# SPACE-DELIMITED
# CASE-SENSITIVE
# SINCE 1.1.0
git.searchExclusions =
# List of regex url patterns for extracting a repository name when locating
# submodules.
#   e.g. git.submoduleUrlPatterns = .*?://github.com/(.*) will extract
#   *gitblit/gitblit.git* from *git://github.com/gitblit/gitblit.git*
# If no matches are found then the submodule repository name is assumed to be
# whatever trails the last / character. (e.g. gitblit.git).
#
# SPACE-DELIMITED
# CASE-SENSITIVE
# SINCE 1.1.0
git.submoduleUrlPatterns = .*?://github.com/(.*)
# Allow push/pull over http/https with JGit servlet.
# If you do NOT want to allow Git clients to clone/push to Gitblit set this
# to false.  You might want to do this if you are only using ssh:// or git://.
# If you set this false, consider changing the *web.otherUrls* setting to
# indicate your clone/push urls.
#
# SINCE 0.5.0
git.enableGitServlet = true
# If you want to restrict all git servlet access to those with valid X509 client
# certificates then set this value to true.
#
# SINCE 1.2.0
git.requiresClientCertificate = false
# Enforce date checks on client certificates to ensure that they are not being
# used prematurely and that they have not expired.
#
# SINCE 1.2.0
git.enforceCertificateValidity = true
# List of OIDs to extract from a client certificate DN to map a certificate to
# an account username.
#
# e.g. git.certificateUsernameOIDs = CN
# e.g. git.certificateUsernameOIDs = FirstName LastName
#
# SPACE-DELIMITED
# SINCE 1.2.0
git.certificateUsernameOIDs = CN
# Only serve/display bare repositories.
# If there are non-bare repositories in git.repositoriesFolder and this setting
# is true, they will be excluded from the ui.
#
# SINCE 0.9.0
git.onlyAccessBareRepositories = false
# Allow an authenticated user to create a destination repository on a push if
# the repository does not already exist.
#
# Administrator accounts can create a repository in any project.
# These repositories are created with the default access restriction and authorization
# control values.  The pushing account is set as the owner.
#
# Non-administrator accounts with the CREATE role may create personal repositories.
# These repositories are created as VIEW restricted for NAMED users.
# The pushing account is set as the owner.
#
# SINCE 1.2.0
git.allowCreateOnPush = true
# The default access restriction for new repositories.
# Valid values are NONE, PUSH, CLONE, VIEW
#  NONE = anonymous view, clone, & push
#  PUSH = anonymous view & clone and authenticated push
#  CLONE = anonymous view, authenticated clone & push
#  VIEW = authenticated view, clone, & push
#
# SINCE 1.0.0
git.defaultAccessRestriction = NONE
# The default authorization control for new repositories.
# Valid values are AUTHENTICATED and NAMED
#  AUTHENTICATED = any authenticated user is granted restricted access
#  NAMED = only named users/teams are granted restricted access
#
# SINCE 1.1.0
git.defaultAuthorizationControl = NAMED
# Enable JGit-based garbage collection. (!!EXPERIMENTAL!!)
#
# USE AT YOUR OWN RISK!
#
# If enabled, the garbage collection executor scans all repositories once a day
# at the hour of your choosing.  The GC executor will take each repository "offline",
# one-at-a-time, to check if the repository satisfies it's GC trigger requirements.
#
# While the repository is offline it will be inaccessible from the web UI or from
# any of the other services (git, rpc, rss, etc).
#
# Gitblit's GC Executor MAY NOT PLAY NICE with the other Git kids on the block,
# especially on Windows systems, so if you are using other tools please coordinate
# their usage with your GC Executor schedule or do not use this feature.
#
# The GC algorithm complex and the JGit team advises caution when using their
# young implementation of GC.
#
# http://wiki.eclipse.org/EGit/New_and_Noteworthy/2.1#Garbage_Collector_and_Repository_Storage_Statistics
#
# EXPERIMENTAL
# SINCE 1.2.0
# RESTART REQUIRED
git.enableGarbageCollection = false
# Hour of the day for the GC Executor to scan repositories.
# This value is in 24-hour time.
#
# SINCE 1.2.0
git.garbageCollectionHour = 0
# The default minimum total filesize of loose objects to trigger early garbage
# collection.
#
# You may specify a custom threshold for a repository in the repository's settings.
# Common unit suffixes of k, m, or g are supported.
#
# SINCE 1.2.0
git.defaultGarbageCollectionThreshold = 500k
# The default period, in days, between GCs for a repository.  If the total filesize
# of the loose object exceeds *git.garbageCollectionThreshold* or the repository's
# custom threshold, this period will be short-circuited.
#
# e.g. if a repository collects 100KB of loose objects every day with a 500KB
# threshold and a period of 7 days, it will take 5 days for the loose objects to
# be collected, packed, and pruned.
#
# OR
#
# if a repository collects 10KB of loose objects every day with a 500KB threshold
# and a period of 7 days, it will take the full 7 days for the loose objects to be
# collected, packed, and pruned.
#
# You may specify a custom period for a repository in the repository's settings.
#
# The minimum value is 1 day since the GC Executor only runs once a day.
#
# SINCE 1.2.0
git.defaultGarbageCollectionPeriod = 7
# Number of bytes of a pack file to load into memory in a single read operation.
# This is the "page size" of the JGit buffer cache, used for all pack access
# operations. All disk IO occurs as single window reads. Setting this too large
# may cause the process to load more data than is required; setting this too small
# may increase the frequency of read() system calls.
#
# Default on JGit is 8 KiB on all platforms.
#
# Common unit suffixes of k, m, or g are supported.
# Documentation courtesy of the Gerrit project.
#
# SINCE 1.0.0
# RESTART REQUIRED
git.packedGitWindowSize = 8k
# Maximum number of bytes to load and cache in memory from pack files. If JGit
# needs to access more than this many bytes it will unload less frequently used
# windows to reclaim memory space within the process. As this buffer must be shared
# with the rest of the JVM heap, it should be a fraction of the total memory available.
#
# The JGit team recommends setting this value larger than the size of your biggest
# repository. This ensures you can serve most requests from memory.
#
# Default on JGit is 10 MiB on all platforms.
#
# Common unit suffixes of k, m, or g are supported.
# Documentation courtesy of the Gerrit project.
#
# SINCE 1.0.0
# RESTART REQUIRED
git.packedGitLimit = 10m
# Maximum number of bytes to reserve for caching base objects that multiple deltafied
# objects reference. By storing the entire decompressed base object in a cache Git
# is able to avoid unpacking and decompressing frequently used base objects multiple times.
#
# Default on JGit is 10 MiB on all platforms. You probably do not need to adjust
# this value.
#
# Common unit suffixes of k, m, or g are supported.
# Documentation courtesy of the Gerrit project.
#
# SINCE 1.0.0
# RESTART REQUIRED
git.deltaBaseCacheLimit = 10m
# Maximum number of pack files to have open at once. A pack file must be opened
# in order for any of its data to be available in a cached window.
#
# If you increase this to a larger setting you may need to also adjust the ulimit
# on file descriptors for the host JVM, as Gitblit needs additional file descriptors
# available for network sockets and other repository data manipulation.
#
# Default on JGit is 128 file descriptors on all platforms.
# Documentation courtesy of the Gerrit project.
#
# SINCE 1.0.0
# RESTART REQUIRED
git.packedGitOpenFiles = 128
# Largest object size, in bytes, that JGit will allocate as a contiguous byte
# array. Any file revision larger than this threshold will have to be streamed,
# typically requiring the use of temporary files under $GIT_DIR/objects to implement
# psuedo-random access during delta decompression.
#
# Servers with very high traffic should set this to be larger than the size of
# their common big files. For example a server managing the Android platform
# typically has to deal with ~10-12 MiB XML files, so 15 m would be a reasonable
# setting in that environment. Setting this too high may cause the JVM to run out
# of heap space when handling very big binary files, such as device firmware or
# CD-ROM ISO images. Make sure to adjust your JVM heap accordingly.
#
# Default is 50 MiB on all platforms.
#
# Common unit suffixes of k, m, or g are supported.
# Documentation courtesy of the Gerrit project.
#
# SINCE 1.0.0
# RESTART REQUIRED
git.streamFileThreshold = 50m
# When true, JGit will use mmap() rather than malloc()+read() to load data from
# pack files.  The use of mmap can be problematic on some JVMs as the garbage
# collector must deduce that a memory mapped segment is no longer in use before
# a call to munmap() can be made by the JVM native code.
#
# In server applications (such as Gitblit) that need to access many pack files,
# setting this to true risks artificially running out of virtual address space,
# as the garbage collector cannot reclaim unused mapped spaces fast enough.
#
# Default on JGit is false. Although potentially slower, it yields much more
# predictable behavior.
# Documentation courtesy of the Gerrit project.
#
# SINCE 1.0.0
# RESTART REQUIRED
git.packedGitMmap = false
#
# Groovy Integration
#
# Location of Groovy scripts to use for Pre and Post receive hooks.
# Use forward slashes even on Windows!!
# e.g. c:/groovy
#
# RESTART REQUIRED
# SINCE 0.8.0
groovy.scriptsFolder = ${baseFolder}/groovy
# Specify the directory Grape uses for downloading libraries.
# http://groovy.codehaus.org/Grape
#
# RESTART REQUIRED
# SINCE 1.0.0
groovy.grapeFolder = ${baseFolder}/groovy/grape
# Scripts to execute on Pre-Receive.
#
# These scripts execute after an incoming push has been parsed and validated
# but BEFORE the changes are applied to the repository.  You might reject a
# push in this script based on the repository and branch the push is attempting
# to change.
#
# Script names are case-sensitive on case-sensitive file systems.  You may omit
# the traditional ".groovy" from this list if your file extension is ".groovy"
#
# NOTE:
# These scripts are only executed when pushing to *Gitblit*, not to other Git
# tooling you may be using.  Also note that these scripts are shared between
# repositories. These are NOT repository-specific scripts!  Within the script
# you may customize the control-flow for a specific repository by checking the
# *repository* variable.
#
# SPACE-DELIMITED
# CASE-SENSITIVE
# SINCE 0.8.0
groovy.preReceiveScripts =
# Scripts to execute on Post-Receive.
#
# These scripts execute AFTER an incoming push has been applied to a repository.
# You might trigger a continuous-integration build here or send a notification.
#
# Script names are case-sensitive on case-sensitive file systems.  You may omit
# the traditional ".groovy" from this list if your file extension is ".groovy"
#
# NOTE:
# These scripts are only executed when pushing to *Gitblit*, not to other Git
# tooling you may be using.  Also note that these scripts are shared between
# repositories. These are NOT repository-specific scripts!  Within the script
# you may customize the control-flow for a specific repository by checking the
# *repository* variable.
#
# SPACE-DELIMITED
# CASE-SENSITIVE
# SINCE 0.8.0
groovy.postReceiveScripts =
# Repository custom fields for Groovy Hook mechanism
#
# List of key=label pairs of custom fields to prompt for in the Edit Repository
# page.  These keys are stored in the repository's git config file in the
# section [gitblit "customFields"].  Key names are alphanumeric only.  These
# fields are intended to be used for the Groovy hook mechanism where a script
# can adjust it's execution based on the custom fields stored in the repository
# config.
#
# e.g. "commitMsgRegex=Commit Message Regular Expression" anotherProperty=Another
#
# SPACE-DELIMITED
# SINCE 1.0.0
groovy.customFields =
#
# Authentication Settings
#
# Require authentication to see everything but the admin pages
#
# SINCE 0.5.0
# RESTART REQUIRED
web.authenticateViewPages = false
# Require admin authentication for the admin functions and pages
#
# SINCE 0.5.0
# RESTART REQUIRED
web.authenticateAdminPages = true
# Allow Gitblit to store a cookie in the user's browser for automatic
# authentication.  The cookie is generated by the user service.
#
# SINCE 0.5.0
web.allowCookieAuthentication = true
# Config file for storing project metadata
#
# SINCE 1.2.0
web.projectsFile = ${baseFolder}/projects.conf
# Either the full path to a user config file (users.conf)
# OR the full path to a simple user properties file (users.properties)
# OR a fully qualified class name that implements the IUserService interface.
#
# Alternative user services:
#    com.gitblit.LdapUserService
#    com.gitblit.RedmineUserService
#
# Any custom user service implementation must have a public default constructor.
#
# SINCE 0.5.0
# RESTART REQUIRED
realm.userService = test-ui-users.conf
# How to store passwords.
# Valid values are plain, md5, or combined-md5.  md5 is the hash of password.
# combined-md5 is the hash of username.toLowerCase()+password.
# Default is md5.
#
# SINCE 0.5.0
realm.passwordStorage = md5
# Minimum valid length for a plain text password.
# Default value is 5.  Absolute minimum is 4.
#
# SINCE 0.5.0
realm.minPasswordLength = 5
#
# Gitblit Web Settings
#
# If blank Gitblit is displayed.
#
# SINCE 0.5.0
web.siteName =
# If *web.authenticateAdminPages*=true, users with "admin" role can create
# repositories, create users, and edit repository metadata.
#
# If *web.authenticateAdminPages*=false, any user can execute the aforementioned
# functions.
#
# SINCE 0.5.0
web.allowAdministration = true
# Allows rpc clients to list repositories and possibly manage or administer the
# Gitblit server, if the authenticated account has administrator permissions.
# See *web.enableRpcManagement* and *web.enableRpcAdministration*.
#
# SINCE 0.7.0
web.enableRpcServlet = true
# Allows rpc clients to manage repositories and users of the Gitblit instance,
# if the authenticated account has administrator permissions.
# Requires *web.enableRpcServlet=true*.
#
# SINCE 0.7.0
web.enableRpcManagement = false
# Allows rpc clients to control the server settings and monitor the health of this
# this Gitblit instance, if the authenticated account has administrator permissions.
# Requires *web.enableRpcServlet=true* and *web.enableRpcManagement*.
#
# SINCE 0.7.0
web.enableRpcAdministration = false
# Full path to a configurable robots.txt file.  With this file you can control
# what parts of your Gitblit server respectable robots are allowed to traverse.
# http://googlewebmastercentral.blogspot.com/2008/06/improving-on-robots-exclusion-protocol.html
#
# SINCE 1.0.0
web.robots.txt =
# If true, the web ui layout will respond and adapt to the browser's dimensions.
# if false, the web ui will use a 940px fixed-width layout.
# http://twitter.github.com/bootstrap/scaffolding.html#responsive
#
# SINCE 1.0.0
web.useResponsiveLayout = true
# Allow Gravatar images to be displayed in Gitblit pages.
#
# SINCE 0.8.0
web.allowGravatar = true
# Allow dynamic zip downloads.
#
# SINCE 0.5.0
web.allowZipDownloads = true
# If *web.allowZipDownloads=true* the following formats will be displayed for
# download compressed archive links:
#
# zip   = standard .zip
# tar   = standard tar format (preserves *nix permissions and symlinks)
# gz    = gz-compressed tar
# xz    = xz-compressed tar
# bzip2 = bzip2-compressed tar
#
# SPACE-DELIMITED
# SINCE 1.2.0
web.compressedDownloads = zip gz
# Allow optional Lucene integration. Lucene indexing is an opt-in feature.
# A repository may specify branches to index with Lucene instead of using Git
# commit traversal. There are scenarios where you may want to completely disable
# Lucene indexing despite a repository specifying indexed branches.  One such
# scenario is on a resource-constrained federated Gitblit mirror.
#
# SINCE 0.9.0
web.allowLuceneIndexing = false
# Allows an authenticated user to create forks of a repository
#
# set this to false if you want to disable all fork controls on the web site
#
web.allowForking = true
# Controls the length of shortened commit hash ids
#
# SINCE 1.2.0
web.shortCommitIdLength = 6
# Use Clippy (Flash solution) to provide a copy-to-clipboard button.
# If false, a button with a more primitive JavaScript-based prompt box will
# offer a 3-step (click, ctrl+c, enter) copy-to-clipboard alternative.
#
# SINCE 0.8.0
web.allowFlashCopyToClipboard = true
# Default maximum number of commits that a repository may contribute to the
# activity page, regardless of the selected duration.  This setting may be valuable
# for an extremely busy server.  This value may also be configed per-repository
# in Edit Repository. 0 disables this throttle.
#
# SINCE 1.2.0
web.maxActivityCommits = 0
# Default number of entries to include in RSS Syndication links
#
# SINCE 0.5.0
web.syndicationEntries = 25
# Show the size of each repository on the repositories page.
# This requires recursive traversal of each repository folder.  This may be
# non-performant on some operating systems and/or filesystems.
#
# SINCE 0.5.2
web.showRepositorySizes = true
# List of custom regex expressions that can be displayed in the Filters menu
# of the Repositories and Activity pages.  Keep them very simple because you
# are likely to run into encoding issues if they are too complex.
#
# Use !!! to separate the filters
#
# SINCE 0.8.0
web.customFilters =
# Show federation registrations (without token) and the current pull status
# to non-administrator users.
#
# SINCE 0.6.0
web.showFederationRegistrations = false
# This is the message displayed when *web.authenticateViewPages=true*.
# This can point to a file with Markdown content.
# Specifying "gitblit" uses the internal login message.
#
# SINCE 0.7.0
web.loginMessage = gitblit
# This is the message displayed above the repositories table.
# This can point to a file with Markdown content.
# Specifying "gitblit" uses the internal welcome message.
#
# SINCE 0.5.0
web.repositoriesMessage = gitblit
# Ordered list of charsets/encodings to use when trying to display a blob.
# If empty, UTF-8 and ISO-8859-1 are used.  The server's default charset
# is always appended to the encoding list.  If all encodings fail to cleanly
# decode the blob content, UTF-8 will be used with the standard malformed
# input/unmappable character replacement strings.
#
# SPACE-DELIMITED
# SINCE 1.0.0
web.blobEncodings = UTF-8 ISO-8859-1
# Manually set the default timezone to be used by Gitblit for display in the
# web ui.  This value is independent of the JVM timezone.  Specifying a blank
# value will default to the JVM timezone.
# e.g. America/New_York, US/Pacific, UTC, Europe/Berlin
#
# SINCE 0.9.0
# RESTART REQUIRED
web.timezone =
# Use the client timezone when formatting dates.
# This uses AJAX to determine the browser's timezone and may require more
# server overhead because a Wicket session is created.  All Gitblit pages
# attempt to be stateless, if possible.
#
# SINCE 0.5.0
# RESTART REQUIRED
web.useClientTimezone = false
# Time format
# <http://download.oracle.com/javase/6/docs/api/java/text/SimpleDateFormat.html>
#
# SINCE 0.8.0
web.timeFormat = HH:mm
# Short date format
# <http://download.oracle.com/javase/6/docs/api/java/text/SimpleDateFormat.html>
#
# SINCE 0.5.0
web.datestampShortFormat = yyyy-MM-dd
# Long date format
#
# SINCE 0.8.0
web.datestampLongFormat = EEEE, MMMM d, yyyy
# Long timestamp format
# <http://download.oracle.com/javase/6/docs/api/java/text/SimpleDateFormat.html>
#
# SINCE 0.5.0
web.datetimestampLongFormat = EEEE, MMMM d, yyyy HH:mm Z
# Mount URL parameters
# This setting controls if pretty or parameter URLs are used.
# i.e.
# if true:
#     http://localhost/commit/myrepo/abcdef
# if false:
#     http://localhost/commit/?r=myrepo&h=abcdef
#
# SINCE 0.5.0
# RESTART REQUIRED
web.mountParameters = true
# Some servlet containers (e.g. Tomcat >= 6.0.10) disallow '/' (%2F) encoding
# in URLs as a security precaution for proxies.  This setting tells Gitblit
# to preemptively replace '/' with '*' or '!' for url string parameters.
#
# <https://issues.apache.org/jira/browse/WICKET-1303>
# <http://tomcat.apache.org/security-6.html#Fixed_in_Apache_Tomcat_6.0.10>
# Add *-Dorg.apache.tomcat.util.buf.UDecoder.ALLOW_ENCODED_SLASH=true* to your
# *CATALINA_OPTS* or to your JVM launch parameters
#
# SINCE 0.5.2
web.forwardSlashCharacter = /
# Show other URLs on the summary page for accessing your git repositories
# Use spaces to separate urls. {0} is the token for the repository name.
# e.g.
# web.otherUrls = ssh://localhost/git/{0} git://localhost/git/{0}
#
# SPACE-DELIMITED
# SINCE 0.5.0
web.otherUrls =
# Choose how to present the repositories list.
#   grouped = group nested/subfolder repositories together (no sorting)
#   flat = flat list of repositories (sorting allowed)
#
# SINCE 0.5.0
web.repositoryListType = grouped
# If using a grouped repository list and there are repositories at the
# root level of your repositories folder, you may specify the displayed
# group name with this setting.  This value is only used for web presentation.
#
# SINCE 0.5.0
web.repositoryRootGroupName = main
# Display the repository swatch color next to the repository name link in the
# repositories list.
#
# SINCE 0.8.0
web.repositoryListSwatches = true
# Choose the diff presentation style: gitblt, gitweb, or plain
#
# SINCE 0.5.0
web.diffStyle = gitblit
# Control if email addresses are shown in web ui
#
# SINCE 0.5.0
web.showEmailAddresses = true
# Shows a combobox in the page links header with commit, committer, and author
# search selection.  Default search is commit.
#
# SINCE 0.5.0
web.showSearchTypeSelection = false
# Generates a line graph of repository activity over time on the Summary page.
# This uses the Google Charts API.
#
# SINCE 0.5.0
web.generateActivityGraph = true
# The number of days to show on the activity page.
# Value must exceed 0 else default of 14 is used
#
# SINCE 0.8.0
web.activityDuration = 14
# The number of commits to display on the summary page
# Value must exceed 0 else default of 20 is used
#
# SINCE 0.5.0
web.summaryCommitCount = 16
# The number of tags/branches to display on the summary page.
# -1 = all tags/branches
# 0 = hide tags/branches
# N = N tags/branches
#
# SINCE 0.5.0
web.summaryRefsCount = 5
# The number of items to show on a page before showing the first, prev, next
# pagination links.  A default if 50 is used for any invalid value.
#
# SINCE 0.5.0
web.itemsPerPage = 50
# Registered file extensions to ignore during Lucene indexing
#
# SPACE-DELIMITED
# SINCE 0.9.0
web.luceneIgnoreExtensions = 7z arc arj bin bmp dll doc docx exe gif gz jar jpg lib lzh odg odf odt pdf ppt png so swf xcf xls xlsx zip
# Registered extensions for google-code-prettify
#
# SPACE-DELIMITED
# SINCE 0.5.0
web.prettyPrintExtensions = c cpp cs css frm groovy htm html java js php pl prefs properties py rb scala sh sql xml vb
# Registered extensions for markdown transformation
#
# SPACE-DELIMITED
# CASE-SENSITIVE
# SINCE 0.5.0
web.markdownExtensions = md mkd markdown MD MKD
# Image extensions
#
# SPACE-DELIMITED
# SINCE 0.5.0
web.imageExtensions = bmp jpg gif png
# Registered extensions for binary blobs
#
# SPACE-DELIMITED
# SINCE 0.5.0
web.binaryExtensions = jar pdf tar.gz zip
# Aggressive heap management will run the garbage collector on every generated
# page.  This slows down page generation a little but improves heap consumption.
#
# SINCE 0.5.0
web.aggressiveHeapManagement = false
# Run the webapp in debug mode
#
# SINCE 0.5.0
# RESTART REQUIRED
web.debugMode = false
# Enable/disable global regex substitutions (i.e. shared across repositories)
#
# SINCE 0.5.0
regex.global = true
# Example global regex substitutions
# Use !!! to separate the search pattern and the replace pattern
# searchpattern!!!replacepattern
# SINCE 0.5.0
regex.global.bug = \\b(Bug:)(\\s*[#]?|-){0,1}(\\d+)\\b!!!<a href="http://somehost/bug/$3">Bug-Id: $3</a>
# SINCE 0.5.0
regex.global.changeid = \\b(Change-Id:\\s*)([A-Za-z0-9]*)\\b!!!<a href="http://somehost/changeid/$2">Change-Id: $2</a>
# Example per-repository regex substitutions overrides global
# SINCE 0.5.0
regex.myrepository.bug = \\b(Bug:)(\\s*[#]?|-){0,1}(\\d+)\\b!!!<a href="http://elsewhere/bug/$3">Bug-Id: $3</a>
#
# Mail Settings
# SINCE 0.6.0
#
# Mail settings are used to notify administrators of received federation proposals
#
# ip or hostname of smtp server
#
# SINCE 0.6.0
mail.server =
# port to use for smtp requests
#
# SINCE 0.6.0
mail.port = 25
# debug the mail executor
#
# SINCE 0.6.0
mail.debug = false
# if your smtp server requires authentication, supply the credentials here
#
# SINCE 0.6.0
mail.username =
# SINCE 0.6.0
mail.password =
# from address for generated emails
#
# SINCE 0.6.0
mail.fromAddress =
# List of email addresses for the Gitblit administrators
#
# SPACE-DELIMITED
# SINCE 0.6.0
mail.adminAddresses =
# List of email addresses for sending push email notifications.
#
# This key currently requires use of the sendemail.groovy hook script.
# If you set sendemail.groovy in *groovy.postReceiveScripts* then email
# notifications for all repositories (regardless of access restrictions!)
# will be sent to these addresses.
#
# SPACE-DELIMITED
# SINCE 0.8.0
mail.mailingLists =
#
# Federation Settings
# SINCE 0.6.0
#
# A Gitblit federation is a way to backup one Gitblit instance to another.
#
# *git.enableGitServlet* must be true to use this feature.
# Your federation name is used for federation status acknowledgments.  If it is
# unset, and you elect to send a status acknowledgment, your Gitblit instance
# will be identified by its hostname, if available, else your internal ip address.
# The source Gitblit instance will also append your external IP address to your
# identification to differentiate multiple pulling systems behind a single proxy.
#
# SINCE 0.6.0
federation.name =
# Specify the passphrase of this Gitblit instance.
#
# An unspecified (empty) passphrase disables processing federation requests.
#
# This value can be anything you want: an integer, a sentence, an haiku, etc.
# Keep the value simple, though, to avoid Java properties file encoding issues.
#
# Changing your passphrase will break any registrations you have established with other
# Gitblit instances.
#
# CASE-SENSITIVE
# SINCE 0.6.0
# RESTART REQUIRED *(only to enable or disable federation)*
federation.passphrase =
# Control whether or not this Gitblit instance can receive federation proposals
# from another Gitblit instance.  Registering a federated Gitblit is a manual
# process.  Proposals help to simplify that process by allowing a remote Gitblit
# instance to send your Gitblit instance the federation pull data.
#
# SINCE 0.6.0
federation.allowProposals = false
# The destination folder for cached federation proposals.
# Use forward slashes even on Windows!!
#
# SINCE 0.6.0
federation.proposalsFolder = ${baseFolder}/proposals
# The default pull frequency if frequency is unspecified on a registration
#
# SINCE 0.6.0
federation.defaultFrequency = 60 mins
# Federation Sets are named groups of repositories.  The Federation Sets are
# available for selection in the repository settings page.  You can assign a
# repository to one or more sets and then distribute the token for the set.
# This allows you to grant federation pull access to a subset of your available
# repositories.  Tokens for federation sets only grant repository pull access.
#
# SPACE-DELIMITED
# CASE-SENSITIVE
# SINCE 0.6.0
federation.sets =
# Federation pull registrations
# Registrations are read once, at startup.
#
# RESTART REQUIRED
#
# frequency:
#   The shortest frequency allowed is every 5 minutes
#   Decimal frequency values are cast to integers
#   Frequency values may be specified in mins, hours, or days
#   Values that can not be parsed or are unspecified default to *federation.defaultFrequency*
#
# folder:
#   if unspecified, the folder is *git.repositoriesFolder*
#   if specified, the folder is relative to *git.repositoriesFolder*
#
# bare:
#   if true, each repository will be created as a *bare* repository and will not
#   have a working directory.
#
#   if false, each repository will be created as a normal repository suitable
#   for local work.
#
# mirror:
#   if true, each repository HEAD is reset to *origin/master* after each pull.
#   The repository will be flagged *isFrozen* after the initial clone.
#
#   if false, each repository HEAD will point to the FETCH_HEAD of the initial
#   clone from the origin until pushed to or otherwise manipulated.
#
# mergeAccounts:
#   if true, remote accounts and their permissions are merged into your
#   users.properties file
#
# notifyOnError:
#   if true and the mail configuration is properly set, administrators will be
#   notified by email of pull failures
#
# include and exclude:
#   Space-delimited list of repositories to include or exclude from pull
#   may be * wildcard to include or exclude all
#   may use fuzzy match (e.g. org.eclipse.*)
#
# (Nearly) Perfect Mirror example
#
#federation.example1.url = https://go.gitblit.com
#federation.example1.token = 6f3b8a24bf970f17289b234284c94f43eb42f0e4
#federation.example1.frequency = 120 mins
#federation.example1.folder =
#federation.example1.bare = true
#federation.example1.mirror = true
#federation.example1.mergeAccounts = true
#
# Advanced Realm Settings
#
# URL of the LDAP server.
# To use encrypted transport, use either ldaps:// URL for SSL or ldap+tls:// to
# send StartTLS command.
#
# SINCE 1.0.0
realm.ldap.server = ldap://localhost
# Login username for LDAP searches.
# If this value is unspecified, anonymous LDAP login will be used.
#
# e.g. mydomain\\username
#
# SINCE 1.0.0
realm.ldap.username = cn=Directory Manager
# Login password for LDAP searches.
#
# SINCE 1.0.0
realm.ldap.password = password
# The LdapUserService must be backed by another user service for standard user
# and team management.
# default: users.conf
#
# SINCE 1.0.0
# RESTART REQUIRED
realm.ldap.backingUserService = test-ui-users.conf
# Delegate team membership control to LDAP.
#
# If true, team user memberships will be specified by LDAP groups.  This will
# disable team selection in Edit User and user selection in Edit Team.
#
# If false, LDAP will only be used for authentication and Gitblit will maintain
# team memberships with the *realm.ldap.backingUserService*.
#
# SINCE 1.0.0
realm.ldap.maintainTeams = false
# Root node for all LDAP users
#
# This is the root node from which subtree user searches will begin.
# If blank, Gitblit will search ALL nodes.
#
# SINCE 1.0.0
realm.ldap.accountBase = OU=Users,OU=UserControl,OU=MyOrganization,DC=MyDomain
# Filter criteria for LDAP users
#
# Query pattern to use when searching for a user account. This may be any valid
# LDAP query expression, including the standard (&) and (|) operators.
#
# Variables may be injected via the ${variableName} syntax.
# Recognized variables are:
#    ${username} - The text entered as the user name
#
# SINCE 1.0.0
realm.ldap.accountPattern = (&(objectClass=person)(sAMAccountName=${username}))
# Root node for all LDAP groups to be used as Gitblit Teams
#
# This is the root node from which subtree team searches will begin.
# If blank, Gitblit will search ALL nodes.
#
# SINCE 1.0.0
realm.ldap.groupBase = OU=Groups,OU=UserControl,OU=MyOrganization,DC=MyDomain
# Filter criteria for LDAP groups
#
# Query pattern to use when searching for a team. This may be any valid
# LDAP query expression, including the standard (&) and (|) operators.
#
# Variables may be injected via the ${variableName} syntax.
# Recognized variables are:
#    ${username} - The text entered as the user name
#    ${dn} - The Distinguished Name of the user logged in
#
# All attributes from the LDAP User record are available. For example, if a user
# has an attribute "fullName" set to "John", "(fn=${fullName})" will be
# translated to "(fn=John)".
#
# SINCE 1.0.0
realm.ldap.groupMemberPattern = (&(objectClass=group)(member=${dn}))
# LDAP users or groups that should be given administrator privileges.
#
# Teams are specified with a leading '@' character.  Groups with spaces in the
# name can be entered as "@team name".
#
# e.g. realm.ldap.admins = john @git_admins "@git admins"
#
# SPACE-DELIMITED
# SINCE 1.0.0
realm.ldap.admins = @Git_Admins
# Attribute(s) on the USER record that indicate their display (or full) name.
# Leave blank for no mapping available in LDAP.
#
# This may be a single attribute, or a string of multiple attributes.  Examples:
#  displayName - Uses the attribute 'displayName' on the user record
#  ${personalTitle}. ${givenName} ${surname} - Will concatenate the 3
#       attributes together, with a '.' after personalTitle
#
# SINCE 1.0.0
realm.ldap.displayName = displayName
# Attribute(s) on the USER record that indicate their email address.
# Leave blank for no mapping available in LDAP.
#
# This may be a single attribute, or a string of multiple attributes.  Examples:
#  email - Uses the attribute 'email' on the user record
#  ${givenName}.${surname}@gitblit.com -Will concatenate the 2 attributes
#       together with a '.' and '@' creating something like first.last@gitblit.com
#
# SINCE 1.0.0
realm.ldap.email = email
# The RedmineUserService must be backed by another user service for standard user
# and team management.
# default: users.conf
#
# RESTART REQUIRED
realm.redmine.backingUserService = test-ui-users.conf
# URL of the Redmine.
realm.redmine.url = http://example.com/redmine
#
# Server Settings
#
# The temporary folder to decompress the embedded gitblit webapp.
#
# SINCE 0.5.0
# RESTART REQUIRED
server.tempFolder = ${baseFolder}/temp
# Use Jetty NIO connectors.  If false, Jetty Socket connectors will be used.
#
# SINCE 0.5.0
# RESTART REQUIRED
server.useNio = true
# Context path for the GO application.  You might want to change the context
# path if running Gitblit behind a proxy layer such as mod_proxy.
#
# SINCE 0.7.0
# RESTART REQUIRED
server.contextPath = /
# Standard http port to serve.  <= 0 disables this connector.
# On Unix/Linux systems, ports < 1024 require root permissions.
# Recommended value: 80 or 8080
#
# SINCE 0.5.0
# RESTART REQUIRED
server.httpPort = 0
# Secure/SSL https port to serve. <= 0 disables this connector.
# On Unix/Linux systems, ports < 1024 require root permissions.
# Recommended value: 443 or 8443
#
# SINCE 0.5.0
# RESTART REQUIRED
server.httpsPort = 8443
# Port for serving an Apache JServ Protocol (AJP) 1.3 connector for integrating
# Gitblit GO into an Apache HTTP server setup.  <= 0 disables this connector.
# Recommended value: 8009
#
# SINCE 0.9.0
# RESTART REQUIRED
server.ajpPort = 0
# Specify the interface for Jetty to bind the standard connector.
# You may specify an ip or an empty value to bind to all interfaces.
# Specifying localhost will result in Gitblit ONLY listening to requests to
# localhost.
#
# SINCE 0.5.0
# RESTART REQUIRED
server.httpBindInterface = localhost
# Specify the interface for Jetty to bind the secure connector.
# You may specify an ip or an empty value to bind to all interfaces.
# Specifying localhost will result in Gitblit ONLY listening to requests to
# localhost.
#
# SINCE 0.5.0
# RESTART REQUIRED
server.httpsBindInterface = localhost
# Specify the interface for Jetty to bind the AJP connector.
# You may specify an ip or an empty value to bind to all interfaces.
# Specifying localhost will result in Gitblit ONLY listening to requests to
# localhost.
#
# SINCE 0.9.0
# RESTART REQUIRED
server.ajpBindInterface = localhost
# Alias of certificate to use for https/SSL serving.  If blank the first
# certificate found in the keystore will be used.
#
# SINCE 1.2.0
# RESTART REQUIRED
server.certificateAlias = localhost
# Password for SSL keystore.
# Keystore password and certificate password must match.
# This is provided for convenience, its probably more secure to set this value
# using the --storePassword command line parameter.
#
# If you are using the official JRE or JDK from Oracle you may not have the
# JCE Unlimited Strength Jurisdiction Policy files bundled with your JVM.  Because
# of this, your store/key password can not exceed 7 characters.  If you require
# longer passwords you may need to install the JCE Unlimited Strength Jurisdiction
# Policy files from Oracle.
#
# http://www.oracle.com/technetwork/java/javase/downloads/index.html
#
# Gitblit and the Gitblit Certificate Authority will both indicate if Unlimited
# Strength encryption is available.
#
# SINCE 0.5.0
# RESTART REQUIRED
server.storePassword = gitblit
# If serving over https (recommended) you might consider requiring clients to
# authenticate with ssl certificates.  If enabled, only https clients with the
# a valid client certificate will be able to access Gitblit.
#
# If disabled, client certificate authentication is optional and will be tried
# first before falling-back to form authentication or basic authentication.
#
# Requiring client certificates to access any of Gitblit may be too extreme,
# consider this carefully.
#
# SINCE 1.2.0
# RESTART REQUIRED
server.requireClientCertificates = false
# Port for shutdown monitor to listen on.
#
# SINCE 0.5.0
# RESTART REQUIRED
server.shutdownPort = 8081
test-ui-users.conf
New file
@@ -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
tests/de/akquinet/devops/GitblitRunnable.java
New file
@@ -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;
    }
}
tests/de/akquinet/devops/LaunchWithUITestConfig.java
New file
@@ -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();
        }
    }
}
tests/de/akquinet/devops/ManualUITestLaunch.java
New file
@@ -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();
}
}
tests/de/akquinet/devops/test/ui/TestUISuite.java
New file
@@ -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 {
}
tests/de/akquinet/devops/test/ui/cases/UI_MultiAdminSupportTest.java
New file
@@ -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());
    }
}
tests/de/akquinet/devops/test/ui/generic/AbstractUITest.java
New file
@@ -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;
    }
}
tests/de/akquinet/devops/test/ui/view/Exp.java
New file
@@ -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;
        }
    }
}
tests/de/akquinet/devops/test/ui/view/GitblitDashboardView.java
New file
@@ -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();
    }
}
tests/de/akquinet/devops/test/ui/view/GitblitPageView.java
New file
@@ -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;
    }
}
tests/de/akquinet/devops/test/ui/view/RepoEditView.java
New file
@@ -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;
    }
}
tests/de/akquinet/devops/test/ui/view/RepoListView.java
New file
@@ -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);
    }
}