Skip to content

Commit 2b35c86

Browse files
authored
Merge pull request #2199 from jtnord/adapt-to-junit-727
Introduce TestResult PO and update junit (plugin) related code
2 parents 9274de5 + 0d5265c commit 2b35c86

15 files changed

Lines changed: 174 additions & 78 deletions

File tree

src/main/java/org/jenkinsci/test/acceptance/plugins/envinject/EnvInjectAction.java

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -28,11 +28,11 @@
2828
import org.jenkinsci.test.acceptance.po.Build;
2929
import org.jenkinsci.test.acceptance.po.ContainerPageObject;
3030

31-
@ActionPageObject("injectedEnvVars")
31+
@ActionPageObject(relativePath = "injectedEnvVars", linkText = "Environment variables")
3232
public class EnvInjectAction extends Action {
3333

34-
public EnvInjectAction(Build build, String path) {
35-
super(build, path);
34+
public EnvInjectAction(Build build, String path, String linkText) {
35+
super(build, path, linkText);
3636
}
3737

3838
public EnvInjectAction shouldContain(String key, String value) {

src/main/java/org/jenkinsci/test/acceptance/plugins/html_publisher/HtmlReport.java

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -31,10 +31,10 @@
3131
import org.jenkinsci.test.acceptance.po.ContainerPageObject;
3232
import org.jenkinsci.test.acceptance.po.Job;
3333

34-
@ActionPageObject("HTML_Report")
34+
@ActionPageObject(relativePath = "HTML_Report", linkText = "HTML Report")
3535
public class HtmlReport extends Action {
36-
public HtmlReport(Job parent, String relative) {
37-
super(parent, relative);
36+
public HtmlReport(Job parent, String relative, String linkText) {
37+
super(parent, relative, linkText);
3838
}
3939

4040
public HtmlReport fileShouldMatch(String path, String content) {

src/main/java/org/jenkinsci/test/acceptance/plugins/job_config_history/JobConfigHistory.java

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -32,11 +32,11 @@
3232
import org.jenkinsci.test.acceptance.po.PageObject;
3333
import org.openqa.selenium.WebElement;
3434

35-
@ActionPageObject("jobConfigHistory")
35+
@ActionPageObject(relativePath = "jobConfigHistory", linkText = "Job Config History")
3636
public class JobConfigHistory extends Action {
3737

38-
public JobConfigHistory(Job parent, String relative) {
39-
super(parent, relative);
38+
public JobConfigHistory(Job parent, String relative, String linkText) {
39+
super(parent, relative, linkText);
4040
}
4141

4242
public void showLastChange() {
Lines changed: 82 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,82 @@
1+
package org.jenkinsci.test.acceptance.plugins.junit;
2+
3+
import static org.hamcrest.MatcherAssert.assertThat;
4+
import static org.hamcrest.Matchers.empty;
5+
import static org.hamcrest.Matchers.not;
6+
7+
import java.util.List;
8+
import org.jenkinsci.test.acceptance.po.Action;
9+
import org.jenkinsci.test.acceptance.po.ActionPageObject;
10+
import org.jenkinsci.test.acceptance.po.Build;
11+
import org.jenkinsci.test.acceptance.po.CapybaraPortingLayerImpl;
12+
import org.jenkinsci.test.acceptance.po.ContainerPageObject;
13+
import org.openqa.selenium.By;
14+
import org.openqa.selenium.NoSuchElementException;
15+
import org.openqa.selenium.WebElement;
16+
17+
@ActionPageObject(relativePath = "testReport", linkText = "Tests")
18+
public class TestReport extends Action {
19+
20+
public TestReport(Build build, String path, String linkText) {
21+
super(build, path, linkText);
22+
}
23+
24+
public int getTotalTestCount() {
25+
// ugly hack as the junit plugin is not super friendly for testing.
26+
WebElement tests = find(by.xpath("//span[class='jenkins-app-bar__subtitle']"));
27+
return Integer.parseInt(tests.getText());
28+
}
29+
30+
public int getSkippedTestCount() {
31+
WebElement tests = getElement(by.xpath("//div[contains(@title, ' skipped')]"));
32+
if (tests == null) {
33+
return 0;
34+
}
35+
return Integer.parseInt(tests.getText());
36+
}
37+
38+
public int getFailedTestCount() {
39+
WebElement tests = getElement(by.xpath("//div[contains(@title, ' failing')]"));
40+
if (tests == null) {
41+
return 0;
42+
}
43+
return Integer.parseInt(tests.getText());
44+
}
45+
46+
public void assertFailureContent(String test, String content) {
47+
// Given that there may be several tests with the same name, we assert
48+
// that at least one of the pages have the requested content
49+
50+
final List<WebElement> rows = all(by.xpath("//tr[@data='%s']", test));
51+
52+
boolean found = false;
53+
for (WebElement row : rows) {
54+
// this is a javascript expand
55+
WebElement link = row.findElement(By.tagName("a"));
56+
link.click();
57+
WebElement details =
58+
waitFor(row).ignoring(NoSuchElementException.class).until(TestReport::getTestDetailsRow);
59+
found = details.getText().contains(content);
60+
link.click(); // hide the content
61+
waitFor(details).until(CapybaraPortingLayerImpl::isStale);
62+
if (found) {
63+
break;
64+
}
65+
}
66+
assertThat("No test found with name " + test, rows, not(empty()));
67+
assertThat("No test found with given content", found);
68+
}
69+
70+
@Override
71+
public boolean isApplicable(ContainerPageObject po) {
72+
return po instanceof Build;
73+
}
74+
75+
private static WebElement getTestDetailsRow(WebElement testRow) {
76+
WebElement sibling = testRow.findElement(By.xpath("following-sibling::*[1]"));
77+
if ("foldout-row".equals(sibling.getDomAttribute("data-type"))) {
78+
return sibling;
79+
}
80+
return null;
81+
}
82+
}

src/main/java/org/jenkinsci/test/acceptance/plugins/priority_sorter/PriorityConfig.java

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -30,11 +30,11 @@
3030
import org.jenkinsci.test.acceptance.po.Jenkins;
3131
import org.jenkinsci.test.acceptance.po.PageAreaImpl;
3232

33-
@ActionPageObject("advanced-build-queue")
33+
@ActionPageObject(relativePath = "advanced-build-queue", linkText = "Job Priorities")
3434
public class PriorityConfig extends Action {
3535

36-
public PriorityConfig(ContainerPageObject parent, String relative) {
37-
super(parent, relative);
36+
public PriorityConfig(ContainerPageObject parent, String relative, String linkText) {
37+
super(parent, relative, linkText);
3838
}
3939

4040
@Override

src/main/java/org/jenkinsci/test/acceptance/plugins/scriptler/Scriptler.java

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -32,11 +32,11 @@
3232
import org.jenkinsci.test.acceptance.po.Control;
3333
import org.jenkinsci.test.acceptance.po.Jenkins;
3434

35-
@ActionPageObject("scriptler")
35+
@ActionPageObject(relativePath = "scriptler")
3636
public class Scriptler extends Action {
3737

38-
public Scriptler(Jenkins parent, String relative) {
39-
super(parent, relative);
38+
public Scriptler(Jenkins parent, String relative, String linkText) {
39+
super(parent, relative, linkText);
4040
}
4141

4242
public Script upload(Resource script) {

src/main/java/org/jenkinsci/test/acceptance/po/Action.java

Lines changed: 22 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,7 @@
2323
*/
2424
package org.jenkinsci.test.acceptance.po;
2525

26+
import java.util.Objects;
2627
import org.openqa.selenium.WebDriver;
2728

2829
/**
@@ -33,25 +34,40 @@
3334
public abstract class Action extends PageObject {
3435

3536
protected final ContainerPageObject parent;
37+
private final String linkText;
3638

37-
public Action(ContainerPageObject parent, String relative) {
39+
public Action(ContainerPageObject parent, String relative, String linkText) {
3840
super(parent.injector, parent.url(relative + "/"));
3941
this.parent = parent;
42+
this.linkText = linkText;
4043
}
4144

4245
@Override
4346
public WebDriver open() {
4447
WebDriver wd = super.open();
45-
46-
if (!wd.getCurrentUrl().startsWith(url.toString())) {
47-
throw new AssertionError("Action " + url + " does not exist. Redirected to " + wd.getCurrentUrl());
48-
}
49-
48+
assertCorrectUrl();
5049
return wd;
5150
}
5251

52+
/**
53+
* Opens the Action page by clicking on the link on the parent page.
54+
*/
55+
public <T extends Action> T openViaLink() {
56+
Objects.requireNonNull(linkText, "The linkText must be provided in order to utilise this method");
57+
parent.ensureOpen();
58+
find(by.link(linkText)).click();
59+
assertCorrectUrl();
60+
return (T) this;
61+
}
62+
5363
/**
5464
* @return true if and action can be attached to given page object.
5565
*/
5666
public abstract boolean isApplicable(ContainerPageObject po);
67+
68+
private void assertCorrectUrl() {
69+
if (!driver.getCurrentUrl().startsWith(url.toString())) {
70+
throw new AssertionError("Action " + url + " does not exist. Redirected to " + driver.getCurrentUrl());
71+
}
72+
}
5773
}

src/main/java/org/jenkinsci/test/acceptance/po/ActionPageObject.java

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -39,5 +39,7 @@
3939
@Indexed
4040
public @interface ActionPageObject {
4141
/** Relative path to parent */
42-
String value();
42+
String relativePath();
43+
/** Text of the link for the action */
44+
String linkText() default "";
4345
}

src/main/java/org/jenkinsci/test/acceptance/po/ContainerPageObject.java

Lines changed: 14 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -86,13 +86,23 @@ public JsonNode getJson(String queryString) {
8686
* @param type Action type to create.
8787
*/
8888
public <T extends Action> T action(Class<T> type) {
89-
final String path = type.getAnnotation(ActionPageObject.class).value();
90-
return action(type, path);
89+
final String path = type.getAnnotation(ActionPageObject.class).relativePath();
90+
final String linkText = type.getAnnotation(ActionPageObject.class).linkText();
91+
return action(type, path, linkText.isBlank() ? null : linkText);
9192
}
9293

93-
public <T extends Action> T action(Class<T> type, String path) {
94+
/**
95+
* Create action of this page object.
96+
* Preffer to use {@link #action(Class)} where fixed paths and link text is known.
97+
* @param <T> The concrete action class to create.
98+
* @param type Action type to create
99+
* @param path the relative path from this PageObject
100+
* @param linkText optional text of the link in the sidebar.
101+
* @return the newly contructed Action of type T
102+
*/
103+
public <T extends Action> T action(Class<T> type, String path, String linkText) {
94104

95-
T instance = newInstance(type, this, path);
105+
T instance = newInstance(type, this, path, linkText);
96106

97107
if (!instance.isApplicable(this)) {
98108
throw new AssertionError(

src/main/java/org/jenkinsci/test/acceptance/po/PageObject.java

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -78,6 +78,15 @@ public WebDriver open() {
7878
return visit(url);
7979
}
8080

81+
/**
82+
* Ensures that the current page is the one represented by this PageObject, and opens it if not.
83+
*/
84+
protected void ensureOpen() {
85+
if (!url.toExternalForm().equals(driver.getCurrentUrl())) {
86+
open();
87+
}
88+
}
89+
8190
/**
8291
* Given the path relative to {@link #url}, visit that page
8392
*/

0 commit comments

Comments
 (0)