JENKINS-43906: Git creation ath tests (#1217)
* Test * Update jenkinsfile' * typo * typo * Increase timeout * more timeouts * Refresh page * wayward backtick One day we will crash into mars because of a typo * adding in a reload for activity screen * relaxing timeouts * Use sse for refresh * debugging * reorder tests * hail mary * More debugging * Ignore test
This commit is contained in:
parent
40ed3e647e
commit
5af7343343
|
@ -14,6 +14,9 @@ node() {
|
|||
configFileProvider([configFile(fileId: 'blueocean-maven-settings', variable: 'MAVEN_SETTINGS')]) {
|
||||
sh 'mv $MAVEN_SETTINGS settings.xml'
|
||||
}
|
||||
withCredentials([file(credentialsId: 'blueocean-ath-private-repo-key', variable: 'FILE')]) {
|
||||
sh 'mv $FILE acceptance-tests/bo-ath.key'
|
||||
}
|
||||
sh "./acceptance-tests/runner/scripts/start-selenium.sh"
|
||||
}
|
||||
|
||||
|
|
|
@ -0,0 +1,21 @@
|
|||
github.repo=
|
||||
github.org=
|
||||
github.token=
|
||||
github.deleteRepo=true
|
||||
github.randomSuffix=true
|
||||
|
||||
# git@github.com:myorg/private-repo.git
|
||||
git.ssh.repository=
|
||||
# /Users/ivan/.ssh/id_rsa
|
||||
git.ssh.keyfile=
|
||||
# Name of the created pipeline (will match repo name).
|
||||
git.ssh.pipelineName=
|
||||
|
||||
# https://github.com/myorg/private-repo.git
|
||||
git.https.repository=
|
||||
# org/user
|
||||
git.https.user=
|
||||
# personal access token
|
||||
git.https.pass=
|
||||
# Name of the created pipeline (will match repo name).
|
||||
git.https.pipelineName=
|
|
@ -82,7 +82,7 @@ public class ATHJUnitRunner extends BlockJUnit4ClassRunner {
|
|||
|
||||
WebDriver driver = injector.getInstance(WebDriver.class);
|
||||
driver.close();
|
||||
driver.quit();
|
||||
// driver.quit();
|
||||
}
|
||||
};
|
||||
}
|
||||
|
|
|
@ -2,6 +2,7 @@ package io.blueocean.ath;
|
|||
|
||||
import com.google.inject.AbstractModule;
|
||||
import com.google.inject.assistedinject.FactoryModuleBuilder;
|
||||
import com.google.inject.name.Names;
|
||||
import com.offbytwo.jenkins.JenkinsServer;
|
||||
import io.blueocean.ath.factory.ActivityPageFactory;
|
||||
import io.blueocean.ath.factory.BranchPageFactory;
|
||||
|
@ -18,10 +19,14 @@ import org.openqa.selenium.remote.Augmenter;
|
|||
import org.openqa.selenium.remote.DesiredCapabilities;
|
||||
import org.openqa.selenium.remote.RemoteWebDriver;
|
||||
|
||||
import java.io.FileInputStream;
|
||||
import java.io.IOException;
|
||||
import java.net.MalformedURLException;
|
||||
import java.net.URI;
|
||||
import java.net.URL;
|
||||
import java.nio.file.Files;
|
||||
import java.nio.file.Paths;
|
||||
import java.util.Properties;
|
||||
|
||||
public class AthModule extends AbstractModule {
|
||||
@Override
|
||||
|
@ -47,12 +52,15 @@ public class AthModule extends AbstractModule {
|
|||
"jenkins.model.Jenkins.getInstance().setNumExecutors(10);\n" +
|
||||
"jenkins.model.Jenkins.getInstance().save();\n");
|
||||
}
|
||||
|
||||
Properties properties = new Properties();
|
||||
properties.load(new FileInputStream("live.properties"));
|
||||
bind(Properties.class).annotatedWith(Names.named("live")).toInstance(properties);
|
||||
} catch (Exception e) {
|
||||
throw new RuntimeException(e);
|
||||
}
|
||||
|
||||
|
||||
|
||||
install(new FactoryModuleBuilder()
|
||||
.implement(ActivityPage.class, ActivityPage.class)
|
||||
.build(ActivityPageFactory.class));
|
||||
|
|
|
@ -17,6 +17,7 @@ import org.openqa.selenium.support.ui.ExpectedConditions;
|
|||
|
||||
import javax.inject.Inject;
|
||||
import java.net.URLEncoder;
|
||||
import java.util.List;
|
||||
|
||||
public class ActivityPage {
|
||||
private Logger logger = Logger.getLogger(ActivityPage.class);
|
||||
|
@ -58,13 +59,13 @@ public class ActivityPage {
|
|||
|
||||
public ActivityPage checkUrl() {
|
||||
wait.until(ExpectedConditions.urlContains(pipeline.getUrl() + "/activity"), 120000);
|
||||
wait.until(By.cssSelector("article.activity"));
|
||||
wait.until(By.cssSelector("article.activity"), 60000);
|
||||
return this;
|
||||
}
|
||||
|
||||
public ActivityPage checkUrl(String filter) {
|
||||
wait.until(ExpectedConditions.urlContains(pipeline.getUrl() + "/activity?branch=" + URLEncoder.encode(URLEncoder.encode(filter))), 30000);
|
||||
wait.until(By.cssSelector("article.activity"));
|
||||
wait.until(By.cssSelector("article.activity"), 60000);
|
||||
return this;
|
||||
}
|
||||
|
||||
|
@ -103,4 +104,10 @@ public class ActivityPage {
|
|||
final String durationRegex = "<1s|\\d+\\w";
|
||||
Assert.assertTrue("String (\"" + text + "\") contains a valid duration", text.matches(durationRegex));
|
||||
}
|
||||
|
||||
public void testNumberRunsComplete(int atLeast) {
|
||||
By selector = By.cssSelector("div[data-pipeline='" + pipeline.getName() + "'].JTable-row circle.success");
|
||||
wait.until(ExpectedConditions.numberOfElementsToBeMoreThan(selector, atLeast - 1));
|
||||
logger.info("At least " + atLeast + " runs are complete");
|
||||
}
|
||||
}
|
||||
|
|
|
@ -116,4 +116,11 @@ public class DashboardPage {
|
|||
public void clickPipeline(String pipelineName){
|
||||
wait.until(By.xpath("//*/div[@data-pipeline='" + pipelineName + "']/a[1]")).click();
|
||||
}
|
||||
|
||||
public void clickNewPipelineBtn() {
|
||||
open();
|
||||
wait.until(newPipelineButton).click();
|
||||
wait.until(ExpectedConditions.urlContains("create-pipeline"));
|
||||
logger.info("Clicked new pipeline");
|
||||
}
|
||||
}
|
||||
|
|
|
@ -0,0 +1,84 @@
|
|||
package io.blueocean.ath.pages.blue;
|
||||
|
||||
import com.google.common.base.Strings;
|
||||
import io.blueocean.ath.WaitUtil;
|
||||
import io.blueocean.ath.api.classic.ClassicJobApi;
|
||||
import io.blueocean.ath.factory.MultiBranchPipelineFactory;
|
||||
import io.blueocean.ath.factory.PipelineFactory;
|
||||
import io.blueocean.ath.model.MultiBranchPipeline;
|
||||
import io.blueocean.ath.model.Pipeline;
|
||||
import io.blueocean.ath.sse.SSEClientRule;
|
||||
import io.blueocean.ath.sse.SSEEvents;
|
||||
import org.apache.log4j.Logger;
|
||||
import org.openqa.selenium.By;
|
||||
import org.openqa.selenium.WebDriver;
|
||||
import org.openqa.selenium.support.PageFactory;
|
||||
import org.openqa.selenium.support.ui.ExpectedConditions;
|
||||
|
||||
import javax.inject.Inject;
|
||||
import javax.inject.Singleton;
|
||||
import java.io.IOException;
|
||||
|
||||
@Singleton
|
||||
public class GitCreationPage {
|
||||
private Logger logger = Logger.getLogger(GitCreationPage.class);
|
||||
|
||||
private WebDriver driver;
|
||||
|
||||
@Inject
|
||||
WaitUtil wait;
|
||||
|
||||
@Inject
|
||||
DashboardPage dashboardPage;
|
||||
|
||||
@Inject
|
||||
ClassicJobApi jobApi;
|
||||
|
||||
@Inject
|
||||
MultiBranchPipelineFactory multiBranchPipelineFactory;
|
||||
|
||||
@Inject
|
||||
public GitCreationPage(WebDriver driver) {
|
||||
this.driver = driver;
|
||||
PageFactory.initElements(driver, this);
|
||||
}
|
||||
|
||||
public GitCreationPage clickGitCreationOption() {
|
||||
wait.until(By.xpath("//span[text()='Git']")).click();
|
||||
logger.info("Selected git creation");
|
||||
return this;
|
||||
}
|
||||
|
||||
public MultiBranchPipeline createPipeline(SSEClientRule sseCLient, String pipelineName, String url, String sshPrivateKey, String user, String pass) throws IOException {
|
||||
jobApi.deletePipeline(pipelineName);
|
||||
dashboardPage.clickNewPipelineBtn();
|
||||
clickGitCreationOption();
|
||||
wait.until(By.cssSelector("div.text-repository-url input")).sendKeys(url);
|
||||
wait.until(By.cssSelector("button.button-create-credential")).click();
|
||||
|
||||
if(!Strings.isNullOrEmpty(sshPrivateKey)) {
|
||||
wait.until(By.xpath("//span[text()='SSH Key']")).click();
|
||||
wait.until(By.cssSelector("textarea.TextArea-control")).sendKeys(sshPrivateKey);
|
||||
wait.until(By.cssSelector(".Dialog-button-bar button.button-create-credental")).click();
|
||||
wait.until(ExpectedConditions.invisibilityOfElementLocated(By.cssSelector(".create-credential-dialog")));
|
||||
logger.info("Created credential");
|
||||
} else if(!Strings.isNullOrEmpty(user) && !Strings.isNullOrEmpty(pass)) {
|
||||
wait.until(By.xpath("//span[text()='Username & Password']")).click();
|
||||
wait.until(By.cssSelector("div.text-username input")).sendKeys(user);
|
||||
wait.until(By.cssSelector("div.text-password input")).sendKeys(pass);
|
||||
wait.until(By.cssSelector(".Dialog-button-bar button.button-create-credental")).click();
|
||||
wait.until(ExpectedConditions.invisibilityOfElementLocated(By.cssSelector(".create-credential-dialog")));
|
||||
logger.info("Created user/pass credential");
|
||||
}
|
||||
|
||||
wait.until(By.cssSelector(".button-create-pipeline")).click();
|
||||
logger.info("Click create pipeline button");
|
||||
|
||||
MultiBranchPipeline pipeline = multiBranchPipelineFactory.pipeline(pipelineName);
|
||||
wait.until(ExpectedConditions.urlContains(pipeline.getUrl() + "/activity"), 30000);
|
||||
sseCLient.untilEvents(SSEEvents.activityComplete(pipeline.getName()));
|
||||
driver.navigate().refresh();
|
||||
pipeline.getActivityPage().checkUrl();
|
||||
return pipeline;
|
||||
}
|
||||
}
|
|
@ -9,6 +9,7 @@ import org.openqa.selenium.WebDriver;
|
|||
import org.openqa.selenium.WebElement;
|
||||
import org.openqa.selenium.support.FindBy;
|
||||
import org.openqa.selenium.support.PageFactory;
|
||||
import org.openqa.selenium.support.ui.ExpectedConditions;
|
||||
|
||||
import javax.inject.Inject;
|
||||
import javax.inject.Singleton;
|
||||
|
@ -52,12 +53,18 @@ public class LoginPage{
|
|||
open();
|
||||
|
||||
|
||||
wait.until(loginUsername).sendKeys(getUsername());
|
||||
WebElement usernameField = wait.until(By.id("j_username"));
|
||||
usernameField.sendKeys(getUsername());
|
||||
|
||||
wait.until(loginPassword).sendKeys(getPassword());
|
||||
wait.until(By.name("j_password")).sendKeys(getPassword());
|
||||
|
||||
wait.until(By.xpath("//*/button[contains(text(), 'log')]")).click();
|
||||
|
||||
wait.until(driver -> {
|
||||
if(driver.getCurrentUrl().contains("loginError")) {
|
||||
throw new RuntimeException("Error logging in");
|
||||
}
|
||||
return ExpectedConditions.urlToBe(base + "/").apply(driver);
|
||||
});
|
||||
logger.info("Logged in as alice");
|
||||
}
|
||||
}
|
||||
|
|
|
@ -74,7 +74,16 @@ public class SSEClientRule extends ExternalResource {
|
|||
|
||||
private EventListener listener = inboundEvent -> {
|
||||
JSONObject jenkinsEvent = new JSONObject(inboundEvent.readData());
|
||||
events.add(jenkinsEvent);
|
||||
if(jenkinsEvent.has("jenkins_event") && jenkinsEvent.getString("jenkins_event").equals("job_run_queue_enter")) {
|
||||
if(jenkinsEvent.has("jenkins_object_type") &&
|
||||
jenkinsEvent.getString("jenkins_object_type").equals("org.jenkinsci.plugins.workflow.multibranch.WorkflowMultiBranchProject")) {
|
||||
} else
|
||||
if(jenkinsEvent.has("blueocean_job_pipeline_name")) {
|
||||
String pipelineName = jenkinsEvent.getString("blueocean_job_pipeline_name");
|
||||
logger.info("Build for " + pipelineName + " entered queue");
|
||||
}
|
||||
}
|
||||
events.add(jenkinsEvent);
|
||||
if(logEvents) {
|
||||
logger.info("SSE - " + jenkinsEvent.toString());
|
||||
}
|
||||
|
|
|
@ -25,8 +25,11 @@ public class SSEEvents {
|
|||
json.getString("jenkins_object_type").equals("org.jenkinsci.plugins.workflow.multibranch.WorkflowMultiBranchProject")) {
|
||||
continue;
|
||||
}
|
||||
if(json.has("blueocean_job_pipeline_name") && json.getString("blueocean_job_pipeline_name").equals(jobName)) {
|
||||
jobsQueued.add(json);
|
||||
if(json.has("blueocean_job_pipeline_name")) {
|
||||
String pipelineName = json.getString("blueocean_job_pipeline_name");
|
||||
if (pipelineName.equals(jobName)) {
|
||||
jobsQueued.add(json);
|
||||
}
|
||||
}
|
||||
}
|
||||
if(json.has("jenkins_event") && json.getString("jenkins_event").equals("job_run_ended")) {
|
||||
|
|
|
@ -0,0 +1,86 @@
|
|||
package io.blueocean.ath.live.creation;
|
||||
|
||||
import io.blueocean.ath.ATHJUnitRunner;
|
||||
import io.blueocean.ath.BaseTest;
|
||||
import io.blueocean.ath.GitRepositoryRule;
|
||||
import io.blueocean.ath.Login;
|
||||
import io.blueocean.ath.WaitUtil;
|
||||
import io.blueocean.ath.model.MultiBranchPipeline;
|
||||
import io.blueocean.ath.model.Pipeline;
|
||||
import io.blueocean.ath.pages.blue.DashboardPage;
|
||||
import io.blueocean.ath.pages.blue.GitCreationPage;
|
||||
import io.blueocean.ath.sse.SSEClientRule;
|
||||
import org.apache.commons.io.IOUtils;
|
||||
import org.apache.log4j.Logger;
|
||||
import org.eclipse.jgit.api.errors.GitAPIException;
|
||||
import org.junit.Assert;
|
||||
import org.junit.Ignore;
|
||||
import org.junit.Rule;
|
||||
import org.junit.Test;
|
||||
import org.junit.runner.RunWith;
|
||||
import org.openqa.selenium.support.ui.ExpectedConditions;
|
||||
|
||||
import javax.inject.Inject;
|
||||
import javax.inject.Named;
|
||||
import java.io.FileInputStream;
|
||||
import java.io.IOException;
|
||||
import java.net.URI;
|
||||
import java.net.URISyntaxException;
|
||||
import java.net.URL;
|
||||
import java.util.Properties;
|
||||
|
||||
@Login
|
||||
@RunWith(ATHJUnitRunner.class)
|
||||
public class GitCreationTest extends BaseTest{
|
||||
private Logger logger = Logger.getLogger(GitCreationTest.class);
|
||||
|
||||
@Inject @Named("live")
|
||||
Properties liveProperties;
|
||||
|
||||
@Inject
|
||||
DashboardPage dashboardPage;
|
||||
@Inject
|
||||
GitCreationPage gitCreationPage;
|
||||
|
||||
@Inject
|
||||
WaitUtil wait;
|
||||
|
||||
@Inject @Rule
|
||||
public SSEClientRule sseClient;
|
||||
|
||||
@Test
|
||||
public void testHttpsPrivateRepository() throws IOException, GitAPIException, URISyntaxException {
|
||||
String gitUrl = liveProperties.getProperty("git.https.repository");
|
||||
String user = liveProperties.getProperty("git.https.user");
|
||||
String pass = liveProperties.getProperty("git.https.pass");
|
||||
String pipelineName = liveProperties.getProperty("git.https.pipelineName");
|
||||
Assert.assertNotNull(gitUrl);
|
||||
Assert.assertNotNull(user);
|
||||
Assert.assertNotNull(pass);
|
||||
Assert.assertNotNull(pipelineName);
|
||||
logger.info("PipelineNameHttps: " + pipelineName);
|
||||
logger.info("git repo - " + gitUrl);
|
||||
Pipeline pipeline = gitCreationPage.createPipeline(sseClient, pipelineName, gitUrl, null, user, pass);
|
||||
pipeline.getActivityPage().testNumberRunsComplete(1);
|
||||
}
|
||||
|
||||
@Ignore
|
||||
@Test
|
||||
public void testSSHPrivateRepostory() throws IOException, GitAPIException, URISyntaxException {
|
||||
String gitUrl = liveProperties.getProperty("git.ssh.repository");
|
||||
String privateKeyFile = liveProperties.getProperty("git.ssh.keyfile");
|
||||
String pipelineName = liveProperties.getProperty("git.ssh.pipelineName");
|
||||
Assert.assertNotNull(gitUrl);
|
||||
Assert.assertNotNull(privateKeyFile);
|
||||
Assert.assertNotNull(pipelineName);
|
||||
logger.info("PipelineName: " + pipelineName);
|
||||
logger.info("git repo - " + gitUrl);
|
||||
String key = IOUtils.toString(new FileInputStream(privateKeyFile));
|
||||
|
||||
MultiBranchPipeline pipeline = gitCreationPage.createPipeline(sseClient, pipelineName, gitUrl, key, null, null);
|
||||
pipeline.getActivityPage().testNumberRunsComplete(1);
|
||||
|
||||
}
|
||||
|
||||
|
||||
}
|
Loading…
Reference in New Issue