Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
10 changes: 10 additions & 0 deletions pom.xml
Original file line number Diff line number Diff line change
Expand Up @@ -492,6 +492,10 @@ and
</systemPropertyVariables>
<!-- SUREFIRE-1588 workaround; too late for systemProperties: -->
<argLine>-Djdk.net.URLClassPath.disableClassPathURLCheck=true</argLine>
<environmentVariables>
<!-- Use local version of the plugin over the released one ATH would otherwise use -->
<LOCAL_JARS>target/credentials.hpi</LOCAL_JARS>
</environmentVariables>
</configuration>
</plugin>
<plugin>
Expand Down Expand Up @@ -765,6 +769,12 @@ and
<version>${jenkins.version}</version>
<type>war</type>
</artifactItem>
<artifactItem>
<groupId>org.jenkins-ci.plugins</groupId>
<artifactId>credentials</artifactId>
<version>1561.v172b_32e210ef</version>
<type>hpi</type>
</artifactItem>
</artifactItems>
<outputDirectory>${project.build.directory}</outputDirectory>
<stripVersion>true</stripVersion>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,6 @@
import org.jenkinsci.test.acceptance.plugins.credentials.UserPwdCredential;
import org.jenkinsci.test.acceptance.plugins.ssh_credentials.SshPrivateKeyCredential;
import org.jenkinsci.test.acceptance.po.Jenkins;
import org.junit.AssumptionViolatedException;
import org.junit.rules.TestRule;
import org.junit.runner.Description;
import org.junit.runners.model.Statement;
Expand Down Expand Up @@ -107,19 +106,13 @@ private boolean enterCredentials(WithCredentials wp) {
* @param sshKeyPath path to the ssh key
*/
private void addSshUsernamePrivateKeyCredentials(String username, String sshKeyPath, String id) {
try {
CredentialsPage cp = new CredentialsPage(jenkins, ManagedCredentials.DEFAULT_DOMAIN);
cp.open();
SshPrivateKeyCredential sc = cp.add(SshPrivateKeyCredential.class);
sc.username.set(username);
sc.selectEnterDirectly()
.privateKey
.set(resource(sshKeyPath).asText());
maybeSetId(sc, id);
cp.create();
} catch (Exception ex) {
throw new AssumptionViolatedException("@WithCredentials requires [email protected].", ex);
}
CredentialsPage cp = new CredentialsPage(jenkins, ManagedCredentials.DEFAULT_DOMAIN);
cp.open();
SshPrivateKeyCredential sc = cp.add(SshPrivateKeyCredential.class);
sc.username.set(username);
sc.selectEnterDirectly().privateKey.set(resource(sshKeyPath).asText());
maybeSetId(sc, id);
cp.create();
}

/**
Expand All @@ -128,17 +121,13 @@ private void addSshUsernamePrivateKeyCredentials(String username, String sshKeyP
* @param password password
*/
private void addUsernamePasswordCredentials(String username, String password, String id) {
try {
CredentialsPage c = new CredentialsPage(jenkins, ManagedCredentials.DEFAULT_DOMAIN);
c.open();
final UserPwdCredential upc = c.add(UserPwdCredential.class);
upc.username.set(username);
upc.password.set(password);
maybeSetId(upc, id);
c.create();
} catch (Exception ex) {
throw new AssumptionViolatedException("@WithCredentials requires [email protected].", ex);
}
CredentialsPage c = new CredentialsPage(jenkins, ManagedCredentials.DEFAULT_DOMAIN);
c.open();
final UserPwdCredential upc = c.add(UserPwdCredential.class);
upc.username.set(username);
upc.password.set(password);
maybeSetId(upc, id);
c.create();
}

private void maybeSetId(BaseStandardCredentials creds, String id) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -110,6 +110,7 @@ protected <T extends BaseStandardCredentials> T createCredentials(
SshPrivateKeyCredential castedCred = (SshPrivateKeyCredential) cred;
castedCred.description.set(CRED_DSCR);
if (scope != null) {
waitFor(by.option(scope));
castedCred.scope.select(scope);
}
castedCred.username.set(CRED_USER);
Expand All @@ -126,7 +127,7 @@ private void navigateToCreateCredentials() {
tryCredentialsClick();
waitFor(by.href("/user/" + CREATED_USER + "/credentials/store/user")).click();
waitFor(by.href("domain/_")).click();
waitFor(by.href("newCredentials")).click();
waitFor(by.button("Add Credentials")).click();
waitFor(by.name("_.id"));
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -29,11 +29,11 @@ protected Credential(PageArea area, String relativePath) {
*/
public void add() {
WebElement dialog = find(by.id("credentials-dialog-form"));
WebElement we = find(submitButton());
WebElement we = find(by.id("cr-dialog-submit"));
we.click();
// wait for the form to be removed from the UI
waitFor(driver).until(ExpectedConditions.invisibilityOf(dialog));
// the notification bar can place itslef over other elements
// the notification bar can place itself over other elements
// so wait for it to be added and then disappear
waitFor(waitFor(By.id("notification-bar"))).until(bar -> !bar.isDisplayed());
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,9 @@
import org.jenkinsci.test.acceptance.po.Control;
import org.jenkinsci.test.acceptance.po.Folder;
import org.jenkinsci.test.acceptance.po.Jenkins;
import org.jenkinsci.test.acceptance.selenium.Scroller;
import org.openqa.selenium.WebDriver;
import org.openqa.selenium.WebElement;

public class CredentialsPage extends ConfigurablePageObject {
public final Control addButton = control(by.xpath("//select[contains(@class, 'setting-input dropdownList')] | "
Expand All @@ -22,26 +24,41 @@ public class CredentialsPage extends ConfigurablePageObject {
* Create a new Credential
*/
public CredentialsPage(Jenkins j, String domainName) {
super(j, j.url("credentials/store/system/domain/" + domainName + "/newCredentials"));
super(j, j.url("credentials/store/system/domain/" + domainName));
}

/**
* Create a new Credential scoped to a Folder
*/
public CredentialsPage(Folder f, String domainName) {
super(f, f.url("credentials/store/folder/domain/" + domainName + "/newCredentials"));
super(f, f.url("credentials/store/folder/domain/" + domainName));
}

/**
* Create a new personal Credential
*/
public CredentialsPage(Jenkins j, String domainName, String userName) {
super(j, j.url(String.format("user/%s/credentials/store/user/domain/%s/newCredentials", userName, domainName)));
super(j, j.url(String.format("user/%s/credentials/store/user/domain/%s", userName, domainName)));
}

public <T extends Credential> T add(Class<T> type) {
addButton.selectDropdownMenuAlt(type);
String path = find(by.name("credentials")).getAttribute("path");
WebElement radio = findCaption(type, caption -> {
for (WebElement webElement : all(by.css(".jenkins-choice-list__item__label"))) {
if (webElement.getText().equals(caption)) {
webElement.click();
return webElement.findElement(by.xpath("./../input"));
}
}
return null;
});

String path = radio.getAttribute("path");

WebElement nextButton = find(by.id("cr-dialog-next"));
nextButton.click();
waitFor(by.id("cr-dialog-submit"));
new Scroller(driver).disableStickyElements();

return newInstance(type, this, path);
}

Expand All @@ -56,7 +73,7 @@ public void setConfigUrl(String url) throws MalformedURLException {
}

public void create() {
find(by.name("Submit")).click();
find(by.id("cr-dialog-submit")).click();
assertThat(driver, not(hasContent("This page expects a form submission")));
}

Expand All @@ -72,9 +89,10 @@ public void delete() {
@Override
public WebDriver open() {
WebDriver wd = super.open();
// wait for default form fields to be present to avoid possible race
// condition when changing credentials type too fast (happens rarely)
waitFor(by.name("_.id"));

clickButton("Add Credentials");
// Selenium will execute the next step before the options have loaded if we don't wait for them
waitFor(by.css(".jenkins-choice-list__item__label"));
return wd;
}

Expand Down
Original file line number Diff line number Diff line change
@@ -1,7 +1,6 @@
package org.jenkinsci.test.acceptance.plugins.ssh_credentials;

import org.jenkinsci.test.acceptance.plugins.credentials.BaseStandardCredentials;
import org.jenkinsci.test.acceptance.plugins.credentials.Credential;
import org.jenkinsci.test.acceptance.po.Control;
import org.jenkinsci.test.acceptance.po.PageObject;

Expand All @@ -16,19 +15,4 @@ public class SshCredentialDialog extends BaseStandardCredentials {
public SshCredentialDialog(PageObject context, String path) {
super(context, path);
}

/**
* Selects the credential type and bind the controls to the page area.
*/
public <T extends Credential> T select(Class<T> type) {

findCaption(type, new Resolver() {
@Override
protected void resolve(String caption) {
kind.select(caption);
}
});

return newInstance(type, getPage(), getPath());
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -4,14 +4,16 @@

import edu.umd.cs.findbugs.annotations.CheckForNull;
import java.time.Duration;
import org.jenkinsci.test.acceptance.plugins.credentials.Credential;
import org.jenkinsci.test.acceptance.plugins.credentials.UserPwdCredential;
import org.jenkinsci.test.acceptance.plugins.ssh_credentials.SshCredentialDialog;
import org.jenkinsci.test.acceptance.plugins.ssh_credentials.SshPrivateKeyCredential;
import org.jenkinsci.test.acceptance.po.ComputerLauncher;
import org.jenkinsci.test.acceptance.po.Control;
import org.jenkinsci.test.acceptance.po.Describable;
import org.jenkinsci.test.acceptance.po.PageObject;
import org.jenkinsci.test.acceptance.selenium.Scroller;
import org.jenkinsci.test.acceptance.selenium.UselessFileDetectorReplacement;
import org.openqa.selenium.WebElement;

/**
* @author Kohsuke Kawaguchi
Expand All @@ -32,14 +34,31 @@ public SshSlaveLauncher(PageObject context, String path) {
super(context, path);
}

public SshCredentialDialog addCredential() {
public <T extends Credential> T addCredential(Class<T> type) {
find(by.button("Add")).click();

find(by.css(".jenkins-dropdown"))
.findElement(by.button("Jenkins Credentials Provider"))
.click();
find(by.css(".jenkins-dropdown")).findElement(by.button("Global")).click();

return new SshCredentialDialog(getPage(), "/credentials");
// Selenium will execute the next step before the options have loaded if we don't wait for them
waitFor(by.css(".jenkins-choice-list__item__label"));

WebElement radio = findCaption(type, caption -> {
for (WebElement webElement : all(by.css(".jenkins-choice-list__item__label"))) {
if (webElement.getText().equals(caption)) {
webElement.click();
return webElement.findElement(by.xpath("./../input"));
}
}
return null;
});

String path = radio.getAttribute("path");

WebElement nextButton = find(by.id("cr-dialog-next"));
nextButton.click();
waitFor(by.id("cr-dialog-submit"));
new Scroller(driver).disableStickyElements();
return newInstance(type, getPage(), path);
}

public void setJavaPath(String jvmPath) {
Expand All @@ -55,6 +74,8 @@ public SshSlaveLauncher port(int port) {
}

private void ensureAdvancedOpen() {
new Scroller(driver).disableStickyElements();

control("advanced-button").click();
}

Expand All @@ -66,8 +87,7 @@ private void ensureAdvancedOpen() {
* @return the SshSlaveLauncher to be configured
*/
public SshSlaveLauncher pwdCredentials(String username, String password) {
final SshCredentialDialog dia = this.addCredential();
final UserPwdCredential cred = dia.select(UserPwdCredential.class);
final UserPwdCredential cred = this.addCredential(UserPwdCredential.class);
cred.username.set(username);
cred.password.set(password);
// credentials are identified by their id. Set username as id so it can be found by it
Expand All @@ -86,8 +106,7 @@ public SshSlaveLauncher pwdCredentials(String username, String password) {
* @return the SshSlaveLauncher to be configured
*/
public SshSlaveLauncher pwdCredentials(String username, String password, String id) {
final SshCredentialDialog dia = this.addCredential();
final UserPwdCredential cred = dia.select(UserPwdCredential.class);
final UserPwdCredential cred = this.addCredential(UserPwdCredential.class);
cred.username.set(username);
cred.password.set(password);
// credentials are identified by their id.
Expand All @@ -105,8 +124,7 @@ public SshSlaveLauncher pwdCredentials(String username, String password, String
* @return the SshSlaveLauncher to be configured
*/
public SshSlaveLauncher keyCredentials(String username, String key, @CheckForNull String passphrase) {
final SshCredentialDialog dia = this.addCredential();
final SshPrivateKeyCredential cred = dia.select(SshPrivateKeyCredential.class);
final SshPrivateKeyCredential cred = this.addCredential(SshPrivateKeyCredential.class);
cred.username.set(username);
if (passphrase != null) {
cred.passphrase.set(passphrase);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,20 @@ const bottomAppBar = document.getElementById("bottom-sticker");
// https://github.com/jenkinsci/jenkins/commit/6481e78d20a0c689859058da5a029489e8b5072c introduced a shadow on a different div!?
const bottomShadow = document.querySelector(".jenkins-bottom-app-bar__shadow")

document.querySelectorAll(".bottom-sticker-inner")
.forEach(element => {
// there can be multiple bottom stickers (e.g. in a dialog) but there's no class on the actual element
const bottomSticker = element.parentNode
if (bottomSticker) {
bottomSticker.style.position = "relative";
}
})

document.querySelectorAll(".jenkins-bottom-app-bar__shadow")
.forEach(element => {
element.style.position = "initial";
})

if (header) {
header.style.position = "relative";
}
Expand Down
6 changes: 2 additions & 4 deletions src/test/java/plugins/SshSlavesPluginTest.java
Original file line number Diff line number Diff line change
Expand Up @@ -41,7 +41,6 @@
import org.jenkinsci.test.acceptance.junit.WithPlugins;
import org.jenkinsci.test.acceptance.plugins.credentials.CredentialsPage;
import org.jenkinsci.test.acceptance.plugins.credentials.ManagedCredentials;
import org.jenkinsci.test.acceptance.plugins.ssh_credentials.SshCredentialDialog;
import org.jenkinsci.test.acceptance.plugins.ssh_credentials.SshPrivateKeyCredential;
import org.jenkinsci.test.acceptance.plugins.ssh_slaves.SshSlaveLauncher;
import org.jenkinsci.test.acceptance.po.Control;
Expand Down Expand Up @@ -96,14 +95,13 @@ public void newAgent() {
// ignore
}

SshCredentialDialog f = l.addCredential();
SshPrivateKeyCredential sc = l.addCredential(SshPrivateKeyCredential.class);
{
SshPrivateKeyCredential sc = f.select(SshPrivateKeyCredential.class);
sc.description.set(description);
sc.username.set(username);
sc.selectEnterDirectly().privateKey.set(privateKey);
sc.add();
}
f.add();

l.credentialsId.select(String.format("%s (%s)", username, description));
}
Expand Down