diff --git a/pom.xml b/pom.xml
index 76008ab..41a1378 100644
--- a/pom.xml
+++ b/pom.xml
@@ -45,7 +45,7 @@
http://wiki.jenkins-ci.org/display/JENKINS/Job+Import+Plugin
- 1.580.3
+ 1.609.1
6
false
@@ -103,6 +103,18 @@
credentials
1.24
+
+ org.jenkins-ci.plugins
+ cloudbees-folder
+ 5.12
+
+
+
+ com.github.tomakehurst
+ wiremock
+ 1.58
+ test
+
diff --git a/src/main/java/org/jenkins/ci/plugins/jobimport/CredentialsUtils.java b/src/main/java/org/jenkins/ci/plugins/jobimport/CredentialsUtils.java
new file mode 100644
index 0000000..4cb11bd
--- /dev/null
+++ b/src/main/java/org/jenkins/ci/plugins/jobimport/CredentialsUtils.java
@@ -0,0 +1,59 @@
+package org.jenkins.ci.plugins.jobimport;
+
+import com.cloudbees.plugins.credentials.CredentialsMatchers;
+import com.cloudbees.plugins.credentials.CredentialsProvider;
+import com.cloudbees.plugins.credentials.common.StandardUsernamePasswordCredentials;
+import com.cloudbees.plugins.credentials.domains.DomainRequirement;
+import com.google.common.base.Strings;
+import hudson.model.Item;
+import hudson.security.ACL;
+
+import java.util.Collections;
+import java.util.List;
+
+import static com.google.inject.internal.guava.base.$Preconditions.checkNotNull;
+
+/**
+ * Created by evildethow on 28/06/2016.
+ */
+final class CredentialsUtils {
+
+ private CredentialsUtils() {
+ throw new UnsupportedOperationException("Cannot instantiate utility class");
+ }
+
+ static NullSafeCredentials getCredentials(String credentialId) {
+ if (!Strings.isNullOrEmpty(credentialId)) {
+ StandardUsernamePasswordCredentials cred = CredentialsMatchers.firstOrNull(allCredentials(), CredentialsMatchers.withId(credentialId));
+ if (cred != null) {
+ return new NullSafeCredentials(cred.getUsername(), cred.getPassword().getPlainText());
+ }
+ }
+ return new NullSafeCredentials();
+ }
+
+ static List allCredentials() {
+ return CredentialsProvider.lookupCredentials(
+ StandardUsernamePasswordCredentials.class,
+ (Item) null,
+ ACL.SYSTEM,
+ Collections.emptyList()
+ );
+ }
+
+ static final class NullSafeCredentials {
+
+ final String username;
+ final String password;
+
+ NullSafeCredentials(String username, String password) {
+ this.username = checkNotNull(username);
+ this.password = checkNotNull(password);
+ }
+
+ NullSafeCredentials() {
+ this.username = "";
+ this.password = "";
+ }
+ }
+}
diff --git a/src/main/java/org/jenkins/ci/plugins/jobimport/JobImportAction.java b/src/main/java/org/jenkins/ci/plugins/jobimport/JobImportAction.java
index ed9ac16..f933920 100644
--- a/src/main/java/org/jenkins/ci/plugins/jobimport/JobImportAction.java
+++ b/src/main/java/org/jenkins/ci/plugins/jobimport/JobImportAction.java
@@ -24,39 +24,18 @@
package org.jenkins.ci.plugins.jobimport;
-import com.cloudbees.plugins.credentials.CredentialsMatchers;
-import com.cloudbees.plugins.credentials.CredentialsProvider;
import com.cloudbees.plugins.credentials.common.StandardUsernameListBoxModel;
-import com.cloudbees.plugins.credentials.common.StandardUsernamePasswordCredentials;
-import com.cloudbees.plugins.credentials.domains.DomainRequirement;
-import com.google.common.base.Strings;
import hudson.Extension;
import hudson.model.Describable;
import hudson.model.Descriptor;
-import hudson.model.Item;
import hudson.model.RootAction;
import hudson.model.TopLevelItem;
-import hudson.model.AbstractProject;
-import hudson.security.ACL;
import hudson.util.FormValidation;
-import java.io.IOException;
-import java.io.InputStream;
-import java.util.Arrays;
-import java.util.Collections;
-import java.util.List;
-import java.util.SortedMap;
-import java.util.SortedSet;
-import java.util.TreeMap;
-import java.util.TreeSet;
-import java.util.logging.Level;
-import java.util.logging.Logger;
-import javax.servlet.ServletException;
-import javax.xml.parsers.DocumentBuilderFactory;
-
import hudson.util.ListBoxModel;
import jenkins.model.Jenkins;
import org.apache.commons.io.IOUtils;
import org.apache.commons.lang.StringUtils;
+import org.jenkins.ci.plugins.jobimport.CredentialsUtils.NullSafeCredentials;
import org.kohsuke.stapler.QueryParameter;
import org.kohsuke.stapler.StaplerRequest;
import org.kohsuke.stapler.StaplerResponse;
@@ -64,6 +43,21 @@
import org.w3c.dom.Element;
import org.w3c.dom.NodeList;
+import javax.servlet.ServletException;
+import javax.xml.parsers.DocumentBuilderFactory;
+import java.io.IOException;
+import java.io.InputStream;
+import java.util.Arrays;
+import java.util.SortedMap;
+import java.util.SortedSet;
+import java.util.TreeMap;
+import java.util.TreeSet;
+import java.util.logging.Level;
+import java.util.logging.Logger;
+
+import static org.jenkins.ci.plugins.jobimport.CredentialsUtils.allCredentials;
+import static org.jenkins.ci.plugins.jobimport.RemoteJobUtils.getRemoteJob;
+
/**
* @author Jesse Farinacci
* @since 1.0
@@ -73,6 +67,11 @@ public final class JobImportAction implements RootAction, Describable getRemoteJobs() {
return remoteJobs;
}
- private RemoteJob getRemoteJobs(final String jobUrl) {
- if (StringUtils.isNotEmpty(jobUrl)) {
- for (final RemoteJob remoteJob : remoteJobs) {
- if (jobUrl.equals(remoteJob.getUrl())) {
- return remoteJob;
- }
- }
- }
-
- return null;
- }
-
public SortedMap getRemoteJobsImportStatus() {
return remoteJobsImportStatus;
}
@@ -258,7 +239,7 @@ public String getRemoteUrl() {
}
public String getUrlName() {
- return "/job-import";
+ return "/" + URL_NAME;
}
public boolean isRemoteJobsAvailable() {
@@ -275,23 +256,11 @@ public void setRemoteUrl(final String remoteUrl) {
public String getCredentialId() { return credentialId; }
- private static List allCredentials() {
- return CredentialsProvider.lookupCredentials(
- StandardUsernamePasswordCredentials.class,
- (Item) null,
- ACL.SYSTEM,
- Collections.emptyList()
- );
- }
+
@Override
public Descriptor getDescriptor() {
- // TODO switch to Jenkins.getActiveInstance() once 1.590+ is the baseline
- Jenkins jenkins = Jenkins.getInstance();
- if (jenkins == null) {
- throw new IllegalStateException("Jenkins has not been started, or was already shut down");
- }
- return jenkins.getDescriptorOrDie(getClass());
+ return Jenkins.getActiveInstance().getDescriptorOrDie(getClass());
}
@Extension
diff --git a/src/main/java/org/jenkins/ci/plugins/jobimport/RemoteJob.java b/src/main/java/org/jenkins/ci/plugins/jobimport/RemoteJob.java
index ff38a2e..edb500f 100644
--- a/src/main/java/org/jenkins/ci/plugins/jobimport/RemoteJob.java
+++ b/src/main/java/org/jenkins/ci/plugins/jobimport/RemoteJob.java
@@ -24,61 +24,63 @@
package org.jenkins.ci.plugins.jobimport;
-import org.apache.commons.lang.StringEscapeUtils;
-import org.apache.commons.lang.StringUtils;
+import java.util.SortedSet;
+import java.util.TreeSet;
+
+import static org.jenkins.ci.plugins.jobimport.RemoteJobUtils.cleanRemoteString;
+import static org.jenkins.ci.plugins.jobimport.RemoteJobUtils.fullName;
/**
* @author Jesse Farinacci
* @since 1.0
*/
public final class RemoteJob implements Comparable {
- private String name;
- private String url;
- private String description;
-
- public RemoteJob() {
- this((String) null, (String) null, (String) null);
- }
-
- public RemoteJob(final String name) {
- this(name, (String) null, (String) null);
- }
-
- public RemoteJob(final String name, final String url) {
- this(name, url, (String) null);
- }
+ private final String name;
+ private final String url;
+ private final String description;
+ private final RemoteJob parent;
+ private final SortedSet children = new TreeSet();
- public RemoteJob(final String name, final String url, final String description) {
- super();
+ public RemoteJob(final String name, final String url, final String description, RemoteJob parent) {
this.name = name;
this.url = url;
- this.description = cleanRemoteString(description);
+ this.description = cleanRemoteString(description != null ? description : "");
+ this.parent = parent;
}
public String getName() {
return name;
}
- public void setName(final String name) {
- this.name = name;
- }
-
public String getUrl() {
return url;
}
- public void setUrl(final String url) {
- this.url = url;
- }
-
public String getDescription() {
return description;
}
- public void setDescription(final String description) {
- this.description = cleanRemoteString(description);
+ public RemoteJob getParent() {
+ return parent;
+ }
+
+ public SortedSet getChildren() {
+ return children;
+ }
+
+ boolean hasChildren() {
+ return !this.children.isEmpty();
+ }
+
+ boolean hasParent() {
+ return this.parent != null;
+ }
+
+ public String getFullName() {
+ return fullName(this);
}
+ @Override
public int compareTo(final RemoteJob other) {
if (this == other) {
return 0;
@@ -89,15 +91,8 @@ public int compareTo(final RemoteJob other) {
@Override
public boolean equals(final Object obj) {
- if (this == obj) {
- return true;
- }
-
- if (!(obj instanceof RemoteJob)) {
- return false;
- }
+ return this == obj || obj instanceof RemoteJob && name.equals(((RemoteJob) obj).getName());
- return name.equals(((RemoteJob) obj).getName());
}
@Override
@@ -107,13 +102,6 @@ public int hashCode() {
@Override
public String toString() {
- return new StringBuilder().append("RemoteJob: ").append(name).append(", ").append(url).append(", ")
- .append(description).toString();
- }
-
- protected static final int MAX_STRLEN = 4096;
-
- protected static final String cleanRemoteString(final String string) {
- return StringUtils.substring(StringEscapeUtils.escapeHtml(string), 0, MAX_STRLEN);
+ return "RemoteJob: " + name + ", " + url + ", " + description;
}
}
diff --git a/src/main/java/org/jenkins/ci/plugins/jobimport/RemoteJobUtils.java b/src/main/java/org/jenkins/ci/plugins/jobimport/RemoteJobUtils.java
new file mode 100644
index 0000000..5cbcfda
--- /dev/null
+++ b/src/main/java/org/jenkins/ci/plugins/jobimport/RemoteJobUtils.java
@@ -0,0 +1,61 @@
+package org.jenkins.ci.plugins.jobimport;
+
+import org.apache.commons.lang.StringEscapeUtils;
+import org.apache.commons.lang.StringUtils;
+
+import java.util.ArrayList;
+import java.util.List;
+import java.util.SortedSet;
+
+/**
+ * Created by evildethow on 28/06/2016.
+ */
+final class RemoteJobUtils {
+
+ private RemoteJobUtils() {
+ throw new UnsupportedOperationException("Cannot instantiate utility class");
+ }
+
+ static String fullName(RemoteJob remoteJob) {
+ if (remoteJob == null) {
+ return "";
+ }
+
+ if (!remoteJob.hasParent()) {
+ return remoteJob.getName();
+ }
+
+ return StringUtils.substringBeforeLast(fullName(remoteJob, ""), "jobs/");
+ }
+
+ private static String fullName(RemoteJob remoteJob, String name) {
+ name = remoteJob.getName() + "/jobs/" + name;
+ return remoteJob.hasParent() ? fullName(remoteJob.getParent(), name) : name;
+ }
+
+ private static final int MAX_STR_LEN = 4096;
+
+ static String cleanRemoteString(final String string) {
+ return StringUtils.substring(StringEscapeUtils.escapeHtml(string), 0, MAX_STR_LEN);
+ }
+
+ static RemoteJob getRemoteJob(SortedSet remoteJobs, String jobUrl) {
+ List matches = new ArrayList();
+
+ findRemoteJob(remoteJobs, jobUrl, matches);
+
+ return matches.isEmpty() ? null : matches.get(0);
+ }
+
+ private static void findRemoteJob(SortedSet remoteJobs, String jobUrl, List matches) {
+ if (StringUtils.isNotEmpty(jobUrl) && matches.isEmpty()) {
+ for (final RemoteJob remoteJob : remoteJobs) {
+ if (jobUrl.trim().equals(remoteJob.getUrl().trim())) {
+ matches.add(remoteJob);
+ } else if (remoteJob.hasChildren()) {
+ findRemoteJob(remoteJob.getChildren(), jobUrl, matches);
+ }
+ }
+ }
+ }
+}
diff --git a/src/test/java/org/jenkins/ci/plugins/jobimport/JobImportActionTest.java b/src/test/java/org/jenkins/ci/plugins/jobimport/JobImportActionTest.java
new file mode 100644
index 0000000..2a255b8
--- /dev/null
+++ b/src/test/java/org/jenkins/ci/plugins/jobimport/JobImportActionTest.java
@@ -0,0 +1,42 @@
+package org.jenkins.ci.plugins.jobimport;
+
+import com.github.tomakehurst.wiremock.junit.WireMockRule;
+import org.junit.Before;
+import org.junit.Rule;
+import org.junit.Test;
+import org.jvnet.hudson.test.JenkinsRule;
+
+import static com.github.tomakehurst.wiremock.core.WireMockConfiguration.wireMockConfig;
+
+/**
+ * Created by evildethow on 29/06/2016.
+ */
+public class JobImportActionTest {
+
+ @Rule
+ public JenkinsRule jenkinsRule = new JenkinsRule();
+
+ @Rule
+ public WireMockRule wireMockRule = new WireMockRule(wireMockConfig().dynamicPort());
+
+ private JobImportClient client;
+ private RemoteJenkins remoteJenkins;
+
+ @Before
+ public void setUp() throws Exception {
+ client = new JobImportClient(jenkinsRule.createWebClient());
+ remoteJenkins = new RemoteJenkins(wireMockRule.port());
+ }
+
+ @Test
+ public void doImport() throws Exception {
+ client.doQuerySubmit(remoteJenkins.getUrl());
+
+ remoteJenkins.verifyQueried();
+
+ client.selectJobs();
+ client.doImportSubmit();
+
+ remoteJenkins.verifyImported();
+ }
+}
diff --git a/src/test/java/org/jenkins/ci/plugins/jobimport/JobImportClient.java b/src/test/java/org/jenkins/ci/plugins/jobimport/JobImportClient.java
new file mode 100644
index 0000000..e9838ad
--- /dev/null
+++ b/src/test/java/org/jenkins/ci/plugins/jobimport/JobImportClient.java
@@ -0,0 +1,56 @@
+package org.jenkins.ci.plugins.jobimport;
+
+import com.gargoylesoftware.htmlunit.FailingHttpStatusCodeException;
+import com.gargoylesoftware.htmlunit.html.*;
+import org.jvnet.hudson.test.JenkinsRule;
+
+import static org.jenkins.ci.plugins.jobimport.JobImportAction.JOB_URL_PARAM;
+import static org.jenkins.ci.plugins.jobimport.JobImportAction.REMOTE_URL_PARAM;
+import static org.jenkins.ci.plugins.jobimport.JobImportAction.URL_NAME;
+
+/**
+ * Created by evildethow on 30/06/2016.
+ */
+public final class JobImportClient {
+
+ private static final int IMPORT_SUBMIT_RETRY = 5;
+ private static final long IMPORT_SUBMIT_RETRY_WAIT_TIME = 1000L;
+
+ private HtmlPage currentPage;
+
+ public JobImportClient(JenkinsRule.WebClient webClient) throws Exception {
+ this.currentPage = webClient.goTo(URL_NAME);
+ }
+
+ public void doQuerySubmit(String remoteUrl) throws Exception {
+ HtmlInput input = (HtmlInput) currentPage.getElementsByName(REMOTE_URL_PARAM).get(0);
+ input.setValueAttribute(remoteUrl);
+ HtmlForm form = currentPage.getFormByName("query");
+ currentPage = form.getInputByValue("Query!").click();
+ }
+
+ public void selectJobs() {
+ for (DomElement checkBox : currentPage.getElementsByName(JOB_URL_PARAM)) {
+ ((HtmlCheckBoxInput) checkBox).setChecked(true);
+ }
+ }
+
+ public void doImportSubmit() throws Exception {
+ doImportSubmitWithRetry(IMPORT_SUBMIT_RETRY);
+ }
+
+ private void doImportSubmitWithRetry(int retry) throws Exception {
+ try {
+ HtmlForm form = currentPage.getFormByName("import");
+ currentPage = form.getInputByValue("Import!").click();
+ } catch (FailingHttpStatusCodeException e) {
+ if (retry > 0) {
+ Thread.sleep(IMPORT_SUBMIT_RETRY_WAIT_TIME);
+ retry--;
+ doImportSubmitWithRetry(retry);
+ } else {
+ throw e;
+ }
+ }
+ }
+}
diff --git a/src/test/java/org/jenkins/ci/plugins/jobimport/RemoteJenkins.java b/src/test/java/org/jenkins/ci/plugins/jobimport/RemoteJenkins.java
new file mode 100644
index 0000000..d7628f9
--- /dev/null
+++ b/src/test/java/org/jenkins/ci/plugins/jobimport/RemoteJenkins.java
@@ -0,0 +1,166 @@
+package org.jenkins.ci.plugins.jobimport;
+
+import org.apache.commons.io.IOUtils;
+
+import java.io.IOException;
+
+import static com.github.tomakehurst.wiremock.client.WireMock.*;
+import static java.io.File.separator;
+import static org.jenkins.ci.plugins.jobimport.JobImportAction.XML_API_QUERY;
+
+/**
+ * Created by evildethow on 30/06/2016.
+ */
+public final class RemoteJenkins {
+
+ private static final String BASE_URL = "http://localhost";
+
+ private static final String TOP_LVL_RSP_XML = "xml-api-response.xml";
+ private static final String SECOND_LVL_RSP_XML = "folder" + separator + "xml-api-response.xml";
+ private static final String THIRD_LVL_RSP_XML = "folder" + separator + "jobs" + separator + "aFolder" + separator + "xml-api-response.xml";
+
+ private static final String TOP_LVL_QUERY = XML_API_QUERY;
+ private static final String SECOND_LVL_FOLDER_QUERY = "/job/folder/" + XML_API_QUERY;
+ private static final String SECOND_LVL_JOB_QUERY = "/job/job/" + XML_API_QUERY;
+ private static final String THIRD_LVL_A_FOLDER_QUERY = "/job/folder/job/aFolder/" + XML_API_QUERY;
+ private static final String THIRD_LVL_A_FREESTYLE_JOB_IN_FOLDER_QUERY = "/job/folder/job/aFreestyleJobInFolder/" + XML_API_QUERY;
+ private static final String THIRD_LVL_A_MAVEN_JOB_IN_FOLDER_QUERY = "/job/folder/job/aMavenJobInFolder/" + XML_API_QUERY;
+ private static final String FOURTH_LVL_B_FREESTYLE_JOB_IN_A_FOLDER_QUERY = "/job/folder/job/aFolder/job/bFreestyleJobInFolder/" + XML_API_QUERY;
+ private static final String FOURTH_LVL_B_MAVEN_JOB_IN_A_FOLDER_QUERY = "/job/folder/job/aFolder/job/bMavenJobInFolder/" + XML_API_QUERY;
+
+ private static final String EMPTY_FREESTYLE_JOB_BODY = "";
+ private static final String EMPTY_MAVEN_JOB_BODY = "";
+
+ private static final String FOLDER_CONFIG_QUERY = "/job/folder//config.xml";
+ private static final String JOB_CONFIG_QUERY = "/job/job//config.xml";
+ private static final String A_FOLDER_CONFIG_QUERY = "/job/folder/job/aFolder//config.xml";
+ private static final String A_FREESTYLE_JOB_IN_FOLDER_CONFIG_QUERY = "/job/folder/job/aFreestyleJobInFolder//config.xml";
+ private static final String A_MAVEN_JOB_IN_FOLDER_CONFIG_QUERY = "/job/folder/job/aMavenJobInFolder//config.xml";
+ private static final String B_FREESTYLE_JOB_IN_FOLDER_CONFIG_QUERY = "/job/folder/job/aFolder/job/bFreestyleJobInFolder//config.xml";
+ private static final String B_MAVEN_JOB_IN_FOLDER_CONFIG_QUERY = "/job/folder/job/aFolder/job/bMavenJobInFolder//config.xml";
+
+ private static final String FOLDER_CONFIG = "folder" + separator + "config.xml";
+ private static final String JOB_CONFIG = "job" + separator + "config.xml";
+ private static final String A_FOLDER_CONFIG = "folder" + separator + "jobs" + separator + "aFolder" + separator + "config.xml";
+ private static final String A_FREESTYLE_JOB_IN_FOLDER_CONFIG = "folder" + separator + "jobs" + separator + "aFreestyleJobInFolder" + separator + "config.xml";
+ private static final String A_MAVEN_JOB_IN_FOLDER_CONFIG = "folder" + separator + "jobs" + separator + "aMavenJobInFolder" + separator + "config.xml";
+ private static final String B_FREESTYLE_JOB_IN_FOLDER_CONFIG = "folder" + separator + "jobs" + separator + "aFolder" + separator + "jobs" + separator + "bFreestyleJobInFolder" + separator + "config.xml";
+ private static final String B_MAVEN_JOB_IN_FOLDER_CONFIG = "folder" + separator + "jobs" + separator + "aFolder" + separator + "jobs" + separator + "bMavenJobInFolder" + separator + "config.xml";
+
+ private final String url;
+
+ public RemoteJenkins(int port) {
+ this.url = BASE_URL + ":" + port;
+
+ stubQueryResponses();
+ stubImportResponses();
+ }
+
+ private void stubQueryResponses() {
+ stubTopLevelResponse();
+ stubSecondLevelResponse();
+ stubThirdLevelResponse();
+ stubFourthLevelResponse();
+ }
+
+ private void stubImportResponses() {
+ stubTopLevelConfigResponse();
+ stubSecondLevelConfigResponse();
+ stubThirdLevelConfigResponse();
+ }
+
+ private void stubTopLevelResponse() {
+ stubGetRequest(TOP_LVL_QUERY, getResponse(TOP_LVL_RSP_XML));
+ }
+
+ private void stubSecondLevelResponse() {
+ stubGetRequest(SECOND_LVL_FOLDER_QUERY, getResponse(SECOND_LVL_RSP_XML));
+ stubGetRequest(SECOND_LVL_JOB_QUERY, EMPTY_FREESTYLE_JOB_BODY);
+ }
+
+ private void stubThirdLevelResponse() {
+ stubGetRequest(THIRD_LVL_A_FOLDER_QUERY, getResponse(THIRD_LVL_RSP_XML));
+ stubGetRequest(THIRD_LVL_A_FREESTYLE_JOB_IN_FOLDER_QUERY, EMPTY_FREESTYLE_JOB_BODY);
+ stubGetRequest(THIRD_LVL_A_MAVEN_JOB_IN_FOLDER_QUERY, EMPTY_MAVEN_JOB_BODY);
+ }
+
+ private void stubFourthLevelResponse() {
+ stubGetRequest(FOURTH_LVL_B_FREESTYLE_JOB_IN_A_FOLDER_QUERY, EMPTY_FREESTYLE_JOB_BODY);
+ stubGetRequest(FOURTH_LVL_B_MAVEN_JOB_IN_A_FOLDER_QUERY, EMPTY_MAVEN_JOB_BODY);
+ }
+
+ private void stubTopLevelConfigResponse() {
+ stubGetRequest(FOLDER_CONFIG_QUERY, getResponse(FOLDER_CONFIG));
+ stubGetRequest(JOB_CONFIG_QUERY, getResponse(JOB_CONFIG));
+ }
+
+ private void stubSecondLevelConfigResponse() {
+ stubGetRequest(A_FOLDER_CONFIG_QUERY, getResponse(A_FOLDER_CONFIG));
+ stubGetRequest(A_FREESTYLE_JOB_IN_FOLDER_CONFIG_QUERY, getResponse(A_FREESTYLE_JOB_IN_FOLDER_CONFIG));
+ stubGetRequest(A_MAVEN_JOB_IN_FOLDER_CONFIG_QUERY, getResponse(A_MAVEN_JOB_IN_FOLDER_CONFIG));
+ }
+
+ private void stubThirdLevelConfigResponse() {
+ stubGetRequest(B_FREESTYLE_JOB_IN_FOLDER_CONFIG_QUERY, getResponse(B_FREESTYLE_JOB_IN_FOLDER_CONFIG));
+ stubGetRequest(B_MAVEN_JOB_IN_FOLDER_CONFIG_QUERY, getResponse(B_MAVEN_JOB_IN_FOLDER_CONFIG));
+ }
+
+ private void stubGetRequest(String url, String template) {
+ stubFor(get(urlEqualTo(url))
+ .willReturn(aResponse()
+ .withStatus(200)
+ .withBody(template)));
+ }
+
+ public String getUrl() {
+ return url;
+ }
+
+ public void verifyQueried() {
+ verifyGetRequest(TOP_LVL_QUERY);
+ verifyGetRequest(SECOND_LVL_FOLDER_QUERY);
+ verifyGetRequest(SECOND_LVL_JOB_QUERY);
+ verifyGetRequest(THIRD_LVL_A_FOLDER_QUERY);
+ verifyGetRequest(THIRD_LVL_A_FREESTYLE_JOB_IN_FOLDER_QUERY);
+ verifyGetRequest(THIRD_LVL_A_MAVEN_JOB_IN_FOLDER_QUERY);
+ verifyGetRequest(FOURTH_LVL_B_FREESTYLE_JOB_IN_A_FOLDER_QUERY);
+ verifyGetRequest(FOURTH_LVL_B_MAVEN_JOB_IN_A_FOLDER_QUERY);
+ }
+
+ public void verifyImported() {
+ verifyGetRequest(FOLDER_CONFIG_QUERY);
+ verifyGetRequest(JOB_CONFIG_QUERY);
+ verifyGetRequest(A_FOLDER_CONFIG_QUERY);
+ verifyGetRequest(A_FREESTYLE_JOB_IN_FOLDER_CONFIG_QUERY);
+ verifyGetRequest(A_MAVEN_JOB_IN_FOLDER_CONFIG_QUERY);
+ verifyGetRequest(B_FREESTYLE_JOB_IN_FOLDER_CONFIG_QUERY);
+ verifyGetRequest(B_MAVEN_JOB_IN_FOLDER_CONFIG_QUERY);
+ }
+
+ private void verifyGetRequest(String url) {
+ verify(getRequestedFor(urlEqualTo(url)));
+ }
+
+ private static final String FIELD_START = "\\$\\{";
+ private static final String FIELD_END = "\\}";
+ private static final String REGEX = FIELD_START + "(baseUrl)" + FIELD_END;
+
+ private String getResponse(String template) {
+ String rawXml = templateToString(template);
+ return rawXml.replaceAll(REGEX, url);
+ }
+
+ private String templateToString(String template) {
+ try {
+ return IOUtils.toString(Thread.currentThread().getContextClassLoader().getResourceAsStream(template));
+ } catch (IOException e) {
+ throw new RemoteJenkinsIOException(e.getMessage());
+ }
+ }
+
+ private static final class RemoteJenkinsIOException extends RuntimeException {
+ RemoteJenkinsIOException(String message) {
+ super(message);
+ }
+ }
+}
diff --git a/src/test/resources/README.md b/src/test/resources/README.md
new file mode 100644
index 0000000..a22ebbf
--- /dev/null
+++ b/src/test/resources/README.md
@@ -0,0 +1,19 @@
+```
+.
+├── folder
+│ ├── config.xml
+│ └── jobs
+│ ├── aFolder
+│ │ ├── config.xml
+│ │ └── jobs
+│ │ ├── bFreestyleJobInFolder
+│ │ │ ├── config.xml
+│ │ └── bMavenJobInFolder
+│ │ ├── config.xml
+│ ├── aFreestyleJobInFolder
+│ │ ├── config.xml
+│ └── aMavenJobInFolder
+│ ├── config.xml
+├── job
+│ ├── config.xml
+```
\ No newline at end of file
diff --git a/src/test/resources/folder/config.xml b/src/test/resources/folder/config.xml
new file mode 100644
index 0000000..d085f4f
--- /dev/null
+++ b/src/test/resources/folder/config.xml
@@ -0,0 +1,37 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ All
+ false
+ false
+
+
+
+
+
+
+
+
+ true
+ true
+ true
+ true
+ false
+
+
+
+
+
\ No newline at end of file
diff --git a/src/test/resources/folder/jobs/aFolder/config.xml b/src/test/resources/folder/jobs/aFolder/config.xml
new file mode 100644
index 0000000..d085f4f
--- /dev/null
+++ b/src/test/resources/folder/jobs/aFolder/config.xml
@@ -0,0 +1,37 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ All
+ false
+ false
+
+
+
+
+
+
+
+
+ true
+ true
+ true
+ true
+ false
+
+
+
+
+
\ No newline at end of file
diff --git a/src/test/resources/folder/jobs/aFolder/jobs/bFreestyleJobInFolder/config.xml b/src/test/resources/folder/jobs/aFolder/jobs/bFreestyleJobInFolder/config.xml
new file mode 100644
index 0000000..9e076fb
--- /dev/null
+++ b/src/test/resources/folder/jobs/aFolder/jobs/bFreestyleJobInFolder/config.xml
@@ -0,0 +1,50 @@
+
+
+
+
+ false
+
+
+ false
+
+
+
+
+
+
+
+
+
+
+
+
+ false
+
+
+ false
+
+
+ false
+ false
+
+
+ 0
+ 0
+
+ false
+ project
+ false
+
+
+
+
+ true
+ false
+ false
+ false
+
+ false
+
+
+
+
\ No newline at end of file
diff --git a/src/test/resources/folder/jobs/aFolder/jobs/bMavenJobInFolder/config.xml b/src/test/resources/folder/jobs/aFolder/jobs/bMavenJobInFolder/config.xml
new file mode 100644
index 0000000..e10d6b7
--- /dev/null
+++ b/src/test/resources/folder/jobs/aFolder/jobs/bMavenJobInFolder/config.xml
@@ -0,0 +1,73 @@
+
+
+
+
+ false
+
+
+ false
+
+
+
+
+
+
+
+
+
+
+
+
+ false
+
+
+ false
+
+
+ false
+ false
+
+
+ 0
+ 0
+
+ false
+ project
+ false
+
+
+
+
+ true
+ false
+ false
+ false
+
+ false
+ true
+ false
+ false
+ false
+ false
+ false
+ false
+ false
+ false
+ -1
+ false
+ false
+ true
+
+
+
+
+
+
+
+
+ FAILURE
+ 2
+ RED
+ true
+
+
\ No newline at end of file
diff --git a/src/test/resources/folder/jobs/aFolder/xml-api-response.xml b/src/test/resources/folder/jobs/aFolder/xml-api-response.xml
new file mode 100644
index 0000000..ed261e0
--- /dev/null
+++ b/src/test/resources/folder/jobs/aFolder/xml-api-response.xml
@@ -0,0 +1,12 @@
+
+
+
+ bFreestyleJobInFolder
+ ${baseUrl}/job/folder/job/aFolder/job/bFreestyleJobInFolder/
+
+
+
+ bMavenJobInFolder
+ ${baseUrl}/job/folder/job/aFolder/job/bMavenJobInFolder/
+
+
\ No newline at end of file
diff --git a/src/test/resources/folder/jobs/aFreestyleJobInFolder/config.xml b/src/test/resources/folder/jobs/aFreestyleJobInFolder/config.xml
new file mode 100644
index 0000000..9e076fb
--- /dev/null
+++ b/src/test/resources/folder/jobs/aFreestyleJobInFolder/config.xml
@@ -0,0 +1,50 @@
+
+
+
+
+ false
+
+
+ false
+
+
+
+
+
+
+
+
+
+
+
+
+ false
+
+
+ false
+
+
+ false
+ false
+
+
+ 0
+ 0
+
+ false
+ project
+ false
+
+
+
+
+ true
+ false
+ false
+ false
+
+ false
+
+
+
+
\ No newline at end of file
diff --git a/src/test/resources/folder/jobs/aMavenJobInFolder/config.xml b/src/test/resources/folder/jobs/aMavenJobInFolder/config.xml
new file mode 100644
index 0000000..e10d6b7
--- /dev/null
+++ b/src/test/resources/folder/jobs/aMavenJobInFolder/config.xml
@@ -0,0 +1,73 @@
+
+
+
+
+ false
+
+
+ false
+
+
+
+
+
+
+
+
+
+
+
+
+ false
+
+
+ false
+
+
+ false
+ false
+
+
+ 0
+ 0
+
+ false
+ project
+ false
+
+
+
+
+ true
+ false
+ false
+ false
+
+ false
+ true
+ false
+ false
+ false
+ false
+ false
+ false
+ false
+ false
+ -1
+ false
+ false
+ true
+
+
+
+
+
+
+
+
+ FAILURE
+ 2
+ RED
+ true
+
+
\ No newline at end of file
diff --git a/src/test/resources/folder/xml-api-response.xml b/src/test/resources/folder/xml-api-response.xml
new file mode 100644
index 0000000..c0f18ed
--- /dev/null
+++ b/src/test/resources/folder/xml-api-response.xml
@@ -0,0 +1,17 @@
+
+
+
+ aFolder
+ ${baseUrl}/job/folder/job/aFolder/
+
+
+
+ aFreestyleJobInFolder
+ ${baseUrl}/job/folder/job/aFreestyleJobInFolder/
+
+
+
+ aMavenJobInFolder
+ ${baseUrl}/job/folder/job/aMavenJobInFolder/
+
+
\ No newline at end of file
diff --git a/src/test/resources/job/config.xml b/src/test/resources/job/config.xml
new file mode 100644
index 0000000..e29817a
--- /dev/null
+++ b/src/test/resources/job/config.xml
@@ -0,0 +1,97 @@
+
+
+
+
+ false
+
+
+ false
+
+
+
+
+ false
+
+
+ https://github.com/Evildethow/test-ghpr-plugin/
+
+
+
+ false
+
+
+ false
+ false
+
+
+ 0
+ 0
+
+ false
+ project
+ false
+
+
+
+
+ 2
+
+
+ +refs/pull/*:refs/remotes/origin/pr/*
+ git@github.com:Evildethow/test-ghpr-plugin.git
+ 23dfb353-8d71-40d3-9773-314613f37221
+
+
+
+
+ ${sha1}
+
+
+ false
+
+
+
+ true
+ false
+ false
+ false
+
+
+ H/5 * * * *
+ 3
+ 3
+
+ false
+
+ H/5 * * * *
+
+ false
+ false
+ false
+
+ false
+ false
+
+
+
+
+
+ fcad1491-7719-4dd5-8eb3-2d6da3503cac
+
+ .*\[skip\W+ci\].*
+
+
+
+
+
+
+ false
+
+
+
+
+ false
+
+
+
+
\ No newline at end of file
diff --git a/src/test/resources/xml-api-response.xml b/src/test/resources/xml-api-response.xml
new file mode 100644
index 0000000..3b19604
--- /dev/null
+++ b/src/test/resources/xml-api-response.xml
@@ -0,0 +1,12 @@
+
+
+
+ folder
+ ${baseUrl}/job/folder/
+
+
+
+ job
+ ${baseUrl}/job/job/
+
+
\ No newline at end of file