Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Multiconfiguration Job Support - Extends "features mixins" #338

Open
wants to merge 2 commits into
base: master
Choose a base branch
from
Open
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
Original file line number Diff line number Diff line change
Expand Up @@ -37,5 +37,9 @@ public ProjectWidget(String projectOfInterest) {
this.projectOfInterest = projectOfInterest;
}

public Question<String> multiConfigBadgeNames() {
return new ProjectMultiConfigWidget();
}

private final String projectOfInterest;
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
package com.smartcodeltd.jenkinsci.plugins.build_monitor.questions.project_widget;

import com.smartcodeltd.jenkinsci.plugins.build_monitor.user_interface.BuildMonitorDashboard;
import net.serenitybdd.screenplay.Actor;
import net.serenitybdd.screenplay.Question;
import net.serenitybdd.screenplay.questions.Text;
import net.serenitybdd.screenplay.targets.Target;

public class ProjectMultiConfigWidget implements Question<String> {

@Override
public String answeredBy(Actor actor) {
Target multiConfigBadge1 = BuildMonitorDashboard.Multi_Config_1;
Target multiConfigBadge2 = BuildMonitorDashboard.Multi_Config_2;

return Text.of(multiConfigBadge1).viewedBy(actor).resolve() + ":::" + Text.of(multiConfigBadge2).viewedBy(actor).resolve();
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
package com.smartcodeltd.jenkinsci.plugins.build_monitor.tasks.configuration;
import net.serenitybdd.screenplay.Actor;
import net.serenitybdd.screenplay.Task;
import net.serenitybdd.screenplay.jenkins.actions.Choose;
import net.serenitybdd.screenplay.jenkins.user_interface.ViewConfigurationPage;
import net.thucydides.core.annotations.Step;

import static net.serenitybdd.screenplay.Tasks.instrumented;

public class DisplayMultiConfig implements Task{

public static Task usingDisplayMultiConfigCheckbox() {
return instrumented(DisplayMultiConfig.class);
}

@Step("{0} clicks the Display Multi-Config Jobs checkbox")
@Override
public <T extends Actor> void performAs(T actor) {
actor.attemptsTo(
Choose.the(ViewConfigurationPage.Display_Multi_Config_Jobs)
);
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,9 @@ public class BuildMonitorDashboard {
public static final Target Project_Widget_Badges = Target.the("Project Widget Badges").locatedBy("//li[header/h2[.='{0}']]//*[@class='badges']");
public static final Target Project_Widget_Pipeline_Stages = Target.the("Project Widget Builds").locatedBy("//li[header/h2[.='{0}']]//*[contains(@class, 'build-stages')]");

public static final Target Multi_Config_1 = Target.the("Multi Config Badge One").locatedBy("//*[@id='multiproject-1']/header/h2/a");
public static final Target Multi_Config_2 = Target.the("Multi Config Badge Two").locatedBy("//*[@id='multiproject-2']/header/h2/a");

public static final Target Control_Panel = Target.the("Control Panel").locatedBy("//label[@for='settings-toggle']");
public static final Target Show_Badges = Target.the("Show Badges Toggle").locatedBy("//input[@id='settings-show-badges']");
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,43 @@
package net.serenitybdd.screenplay.jenkins;


import net.serenitybdd.screenplay.Actor;
import net.serenitybdd.screenplay.Task;
import net.serenitybdd.screenplay.actions.Click;
import net.serenitybdd.screenplay.jenkins.tasks.CreateAMultiConfigurationProject;
import net.serenitybdd.screenplay.jenkins.tasks.configuration.TodoList;
import net.thucydides.core.annotations.Step;

import static net.serenitybdd.screenplay.Tasks.instrumented;
import static net.serenitybdd.screenplay.jenkins.user_interface.navigation.SidePanel.Back_to_Dashboard;

public class HaveAMultiConfigProjectCreated implements Task{

public static HaveAMultiConfigProjectCreated called(String name) {
return instrumented(HaveAMultiConfigProjectCreated.class, name);
}

public Task andConfigureItTo(Task... configurationTasks) {
this.requiredConfiguration.addAll(configurationTasks);

return this;
}

@Step("{0} creates the '#projectName' pipeline")
@Override
public <T extends Actor> void performAs(T actor) {
actor.attemptsTo(
CreateAMultiConfigurationProject.called(projectName)
.andConfigureItTo(requiredConfiguration),
Click.on(Back_to_Dashboard)
);
}

public HaveAMultiConfigProjectCreated (String projectName) {
this.projectName = projectName;
}


private final String projectName;
private final TodoList requiredConfiguration = TodoList.empty();
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,41 @@
package net.serenitybdd.screenplay.jenkins.tasks;

import net.serenitybdd.screenplay.Actor;
import net.serenitybdd.screenplay.Task;
import net.serenitybdd.screenplay.jenkins.tasks.configuration.AddAxis;
import net.serenitybdd.screenplay.jenkins.tasks.configuration.TodoList;
import net.serenitybdd.screenplay.jenkins.user_interface.NewJobPage;
import net.thucydides.core.annotations.Step;

import static net.serenitybdd.screenplay.Tasks.instrumented;

public class CreateAMultiConfigurationProject implements Task {

public static CreateAMultiConfigurationProject called(String name) {
return instrumented(CreateAMultiConfigurationProject.class, name);
}

public CreateAMultiConfigurationProject andConfigureItTo(Task configurationTask) {
this.configureTheProject.add(configurationTask);

return this;
}

@Step("{0} creates a 'Multi-Configuration' called '#name'")
@Override
public <T extends Actor> void performAs(T actor) {
actor.attemptsTo(
CreateAProject.called(name)
.ofType(NewJobPage.Multi_Configuration_Project)
.andConfigureItTo(configureTheProject)
);
}

public CreateAMultiConfigurationProject(String jobName) {
this.name = jobName;
}

private final String name;
private final TodoList configureTheProject = TodoList.empty();

}
Original file line number Diff line number Diff line change
Expand Up @@ -48,7 +48,7 @@ public CreateAProject(String jobName) {
this.name = jobName;
}

private final String name;
private final TodoList configureTheProject = TodoList.empty();
private Target projectType;
private final String name;
private final TodoList configureTheProject = TodoList.empty();
private Target projectType;
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
package net.serenitybdd.screenplay.jenkins.tasks.configuration;

import net.serenitybdd.screenplay.actions.Click;
import net.serenitybdd.screenplay.actions.Enter;
import net.serenitybdd.screenplay.jenkins.targets.Link;
import net.serenitybdd.screenplay.jenkins.user_interface.ProjectConfigurationPage;
import net.serenitybdd.screenplay.jenkins.user_interface.EditUserDefinedAxis;
import net.serenitybdd.screenplay.Actor;
import net.serenitybdd.screenplay.Task;
import net.serenitybdd.screenplayx.actions.Scroll;
import net.thucydides.core.annotations.Step;

public class AddAxis implements Task {
public static Task of(Axis axis) {
return new AddAxis(axis);
}

@Step("{0} configures Multi-Configuration project axis")
@Override
public <T extends Actor> void performAs(T actor) {
actor.attemptsTo(
Scroll.to(ProjectConfigurationPage.Add_Axis),
Click.on(ProjectConfigurationPage.Add_Axis),
Click.on(Link.called("User-defined Axis")),
Enter.theValue(axis.getName()).into(EditUserDefinedAxis.EditAxisName),
Enter.theValue(axis.getValues()).into(EditUserDefinedAxis.EditAxisVals)
);
}

public AddAxis(Axis axis) {
this.axis = axis;
}

private Axis axis;
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
package net.serenitybdd.screenplay.jenkins.tasks.configuration;

public class Axis {

private String name;
private String[] values;

public Axis(String name, String[] values) {
this.name = name;
this.values = values;
}

public String getName() {
return this.name;
}

public String getValues() {
String dimensions = "";
for(String val : values) {
dimensions += val + " ";
}

return dimensions;
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
package net.serenitybdd.screenplay.jenkins.user_interface;

import net.serenitybdd.screenplay.targets.Target;

public class EditUserDefinedAxis {
public static final Target EditAxisName = Target.the("code editor").locatedBy("(//div[@descriptorid='hudson.matrix.TextAxis']//input[@class='setting-input validated '])");
public static final Target EditAxisVals = Target.the("code editor").locatedBy("(//div[@descriptorid='hudson.matrix.TextAxis']//input[@class='setting-input'])");
}
Original file line number Diff line number Diff line change
Expand Up @@ -8,8 +8,9 @@

@DefaultUrl("/newJob")
public class NewJobPage extends PageObject {
public static final Target Item_Name_Field = Setting.defining("Item name");
public static final Target Freestyle_Project = RadioButton.withLabel("Freestyle project");
public static final Target Pipeline = RadioButton.withLabel("Pipeline");
public static final Target External_Project = RadioButton.withLabel("External Job");
public static final Target Item_Name_Field = Setting.defining("Item name");
public static final Target Freestyle_Project = RadioButton.withLabel("Freestyle project");
public static final Target Pipeline = RadioButton.withLabel("Pipeline");
public static final Target External_Project = RadioButton.withLabel("External Job");
public static final Target Multi_Configuration_Project = RadioButton.withLabel("Multi-configuration project");
}
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,8 @@
import net.serenitybdd.screenplay.targets.Target;

public class ProjectConfigurationPage {
public static final Target Execute_Concurrent_Builds = Checkbox.withLabel("Execute concurrent builds if necessary");
public static final Target Add_Build_Step = Button.called("Add build step");
public static final Target Add_Post_Build_Action = Button.called("Add post-build action");
public static final Target Execute_Concurrent_Builds = Checkbox.withLabel("Execute concurrent builds if necessary");
public static final Target Add_Build_Step = Button.called("Add build step");
public static final Target Add_Post_Build_Action = Button.called("Add post-build action");
public static final Target Add_Axis = Button.called("Add axis");
}
Original file line number Diff line number Diff line change
Expand Up @@ -8,4 +8,5 @@ public class ViewConfigurationPage {
public static final Target Recurse_In_Subfolders = Target.the("the 'Recurse in subfolders' option").locatedBy("#recurse");
public static final Target Use_Regular_Expression = Checkbox.withLabel("Use a regular expression to include jobs into the view");
public static final Target Regular_Expression = Target.the("the 'Regular expression' field").located(By.name("includeRegex"));
public static final Target Display_Multi_Config_Jobs = Target.the("the 'Show multiple configuration jobs' option").locatedBy("#multiConfig");
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,60 @@
package features;

import com.smartcodeltd.jenkinsci.plugins.build_monitor.questions.ProjectWidget;
import com.smartcodeltd.jenkinsci.plugins.build_monitor.tasks.ConfigureEmptyBuildMonitorView;
import com.smartcodeltd.jenkinsci.plugins.build_monitor.tasks.CreateABuildMonitorView;
import com.smartcodeltd.jenkinsci.plugins.build_monitor.tasks.configuration.DisplayAllProjects;
import com.smartcodeltd.jenkinsci.plugins.build_monitor.tasks.configuration.DisplayMultiConfig;
import environment.JenkinsSandbox;
import net.serenitybdd.integration.jenkins.JenkinsInstance;
import net.serenitybdd.junit.runners.SerenityRunner;
import net.serenitybdd.screenplay.Actor;
import net.serenitybdd.screenplay.abilities.BrowseTheWeb;
import net.serenitybdd.screenplay.jenkins.HaveAMultiConfigProjectCreated;
import net.serenitybdd.screenplay.jenkins.tasks.configuration.AddAxis;
import net.serenitybdd.screenplay.jenkins.tasks.configuration.Axis;
import net.serenitybdd.screenplayx.actions.Navigate;
import net.thucydides.core.annotations.Managed;
import org.junit.Before;
import org.junit.Rule;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.openqa.selenium.WebDriver;

import static net.serenitybdd.screenplay.GivenWhenThen.*;
import static org.hamcrest.Matchers.is;

@RunWith(SerenityRunner.class)
public class ShouldDisplayMultiConfigJobs {

Actor mason = Actor.named("Mason");

Axis numbers = new Axis("Numbers", new String[] {"1", "2"});

@Managed public WebDriver hisBrowser;

@Rule
public JenkinsInstance jenkins = JenkinsSandbox.configure().create();

@Before
public void actorCanBrowseTheWeb() {
mason.can(BrowseTheWeb.with(hisBrowser));
}

@Test
public void displaying_two_configuration_widgets() throws Exception {

givenThat(mason).wasAbleTo(
Navigate.to(jenkins.url()),
HaveAMultiConfigProjectCreated.called("MultiProject")
.andConfigureItTo(AddAxis.of(numbers))
);

when(mason).attemptsTo(
CreateABuildMonitorView.called("Build Monitor"),
ConfigureEmptyBuildMonitorView.to(DisplayMultiConfig.usingDisplayMultiConfigCheckbox(), DisplayAllProjects.usingARegularExpression())
);

then(mason).should(seeThat(ProjectWidget.of("MultiProject").multiConfigBadgeNames(), is("MultiProject » 1:::MultiProject » 2")));
}
}
8 changes: 7 additions & 1 deletion build-monitor-plugin/pom.xml
Original file line number Diff line number Diff line change
Expand Up @@ -145,6 +145,12 @@
<version>2.1.10</version>
<optional>true</optional>
</dependency>
<dependency>
<groupId>org.jenkins-ci.plugins</groupId>
<artifactId>matrix-project</artifactId>
<version>1.2.1</version>
<optional>true</optional>
</dependency>
<dependency>
<groupId>com.sonyericsson.jenkins.plugins.bfa</groupId>
<artifactId>build-failure-analyzer</artifactId>
Expand Down Expand Up @@ -302,7 +308,7 @@
</goals>
<configuration>
<outputTemplate>version={{ version }}</outputTemplate>
<outputUri>file://${project.basedir}/target/classes/build-monitor.properties</outputUri>
<outputUri>${project.baseUri}/target/classes/build-monitor.properties</outputUri>
</configuration>
</execution>
</executions>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -55,6 +55,8 @@ public class BuildMonitorView extends ListView {

private String title;

private static final StaticJenkinsAPIs jenkinsAPIs = new StaticJenkinsAPIs();

/**
* @param name Name of the view to be displayed on the Views tab
* @param title Title to be displayed on the Build Monitor; defaults to 'name' if not set
Expand Down Expand Up @@ -96,6 +98,11 @@ public boolean isDisplayCommitters() {
return currentConfig().shouldDisplayCommitters();
}

@SuppressWarnings("unused") // used in the configure-entries.jelly form
public boolean isDisplayMultiConfigJob() {
return currentConfig().shouldDisplayMultiConfigJobs();
}

private static final BuildMonitorInstallation installation = new BuildMonitorInstallation();

@SuppressWarnings("unused") // used in index.jelly
Expand All @@ -121,6 +128,7 @@ protected void submit(StaplerRequest req) throws ServletException, IOException,

currentConfig().setDisplayCommitters(json.optBoolean("displayCommitters", true));
currentConfig().setBuildFailureAnalyzerDisplayedField(req.getParameter("buildFailureAnalyzerDisplayedField"));
currentConfig().setDisplayMultiConfigJobs(req.getParameter("displayMultiConfigJobs"));

try {
currentConfig().setOrder(orderIn(requestedOrdering));
Expand Down Expand Up @@ -158,7 +166,7 @@ private List<JobView> jobViews() {
Collections.sort(projects, currentConfig().getOrder());

for (Job project : projects) {
jobs.add(views.viewOf(project));
jobs.addAll(views.viewsOf(project));
}

return jobs;
Expand Down Expand Up @@ -210,6 +218,11 @@ private void migrateFromOldToNewConfigFormat() {
return (Comparator<Job<?, ?>>) Class.forName(packageName + requestedOrdering).newInstance();
}

@SuppressWarnings("unused") // Used in configure-entries.jelly
public Boolean containsMatrixProjectPlugin() {
return jenkinsAPIs.hasPlugin("matrix-project");
}

private Config config;

@Deprecated // use Config instead
Expand Down
Loading