Skip to content

Commit

Permalink
Merge branch 'dcendents-badge_text'
Browse files Browse the repository at this point in the history
Closes #278
  • Loading branch information
jan-molak committed Jan 7, 2017
2 parents 23d1c71 + 85a8e10 commit 0334b96
Show file tree
Hide file tree
Showing 25 changed files with 520 additions and 2 deletions.
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
package com.smartcodeltd.jenkinsci.plugins.build_monitor.questions;

import com.smartcodeltd.jenkinsci.plugins.build_monitor.model.ProjectInformation;
import com.smartcodeltd.jenkinsci.plugins.build_monitor.questions.project_widget.ProjectBadgesState;
import com.smartcodeltd.jenkinsci.plugins.build_monitor.questions.project_widget.ProjectWidgetDetails;
import com.smartcodeltd.jenkinsci.plugins.build_monitor.questions.project_widget.ProjectWidgetInformation;
import com.smartcodeltd.jenkinsci.plugins.build_monitor.questions.project_widget.ProjectWidgetState;
Expand All @@ -25,6 +26,10 @@ public Question<String> details() {
return new ProjectWidgetDetails(projectOfInterest);
}

public Question<WebElementState> badges() {
return new ProjectBadgesState(projectOfInterest);
}

public ProjectWidget(String projectOfInterest) {
this.projectOfInterest = projectOfInterest;
}
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
package com.smartcodeltd.jenkinsci.plugins.build_monitor.questions.project_widget;

import com.smartcodeltd.jenkinsci.plugins.build_monitor.user_interface.BuildMonitorDashboard;
import net.serenitybdd.core.pages.WebElementState;
import net.serenitybdd.screenplay.Actor;
import net.serenitybdd.screenplay.Question;
import net.serenitybdd.screenplay.annotations.Subject;
import net.serenitybdd.screenplay.targets.Target;

import static net.serenitybdd.screenplay.questions.WebElementQuestion.stateOf;

@Subject("the badges of widget representing the '#projectName' project on the Build Monitor")
public class ProjectBadgesState implements Question<WebElementState> {

@Override
public WebElementState answeredBy(Actor actor) {
Target widget = BuildMonitorDashboard.Project_Widget_Badges.of(projectName);

return stateOf(widget).answeredBy(actor);
}

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

private final String projectName;
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@
package com.smartcodeltd.jenkinsci.plugins.build_monitor.tasks;

import com.smartcodeltd.jenkinsci.plugins.build_monitor.user_interface.BuildMonitorDashboard;

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

import java.util.List;

import static java.util.Arrays.asList;
import static net.serenitybdd.screenplay.Tasks.instrumented;

public class ModifyControlPanelOptions implements Task {

public static ModifyControlPanelOptions to(Task... configurationTasks) {
return instrumented(ModifyControlPanelOptions.class, asList(configurationTasks));
}

@Override
@Step("{0} modifies the Build Monitor View control panel options")
public <T extends Actor> void performAs(T actor) {
actor.attemptsTo(
Click.on(BuildMonitorDashboard.Control_Panel),
configureTheView,
Click.on(BuildMonitorDashboard.Control_Panel)
);
}

public ModifyControlPanelOptions(List<Performable> actions) {
this.configureTheView.addAll(actions);
}

private TodoList configureTheView = TodoList.empty();
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
package com.smartcodeltd.jenkinsci.plugins.build_monitor.tasks;

import com.smartcodeltd.jenkinsci.plugins.build_monitor.user_interface.BuildMonitorDashboard;

import net.serenitybdd.screenplay.Actor;
import net.serenitybdd.screenplay.Task;
import net.serenitybdd.screenplay.actions.Click;
import net.thucydides.core.annotations.Step;

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

public class ShowBadges implements Task {
public static Task onTheDashboard() {
return instrumented(ShowBadges.class);
}

@Step("{0} decides to display the badges on the dashboard")
@Override
public <T extends Actor> void performAs(T actor) {
actor.attemptsTo(
Click.on(BuildMonitorDashboard.Show_Badges)
);
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -8,4 +8,8 @@ public class BuildMonitorDashboard extends PageObject {
public static final Target Add_Some_Projects_link = Link.called("add some projects");
public static final Target Project_Widget = Target.the("Project Widget").locatedBy("//li[header/h2[.='{0}']]");
public static final Target Project_Widget_Details = Target.the("Project Widget Details").locatedBy("//li[header/h2[.='{0}']]//*[@class='details']");
public static final Target Project_Widget_Badges = Target.the("Project Widget Badges").locatedBy("//li[header/h2[.='{0}']]//*[@class='badges']");

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,31 @@
package net.serenitybdd.screenplay.jenkins.tasks.configuration.build_steps;

import net.serenitybdd.screenplay.jenkins.user_interface.project_configuration.build_steps.GroovyPostBuildStep;
import net.serenitybdd.screenplay.Actor;
import net.serenitybdd.screenplay.Task;
import net.serenitybdd.screenplay.actions.Enter;
import net.thucydides.core.annotations.Step;

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

public class AddAGroovyPostbuildScript implements Task {

public static Task that(GroovyScript expectedOutcome) {
return instrumented(AddAGroovyPostbuildScript.class, expectedOutcome);
}

@Step("{0} configures the Groovy PostBuild Step to execute a script that '#scriptOutcome'")
@Override
public <T extends Actor> void performAs(T actor) {
actor.attemptsTo(
AddAPostBuildAction.called("Groovy Postbuild"),
Enter.theValue(scriptOutcome.code()).into(GroovyPostBuildStep.Editor)
);
}

public AddAGroovyPostbuildScript(GroovyScript script) {
this.scriptOutcome = script;
}

private final GroovyScript scriptOutcome;
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,58 @@
package net.serenitybdd.screenplay.jenkins.tasks.configuration.build_steps;

import com.google.common.base.Function;
import com.google.common.base.Joiner;

import javax.annotation.Nullable;
import java.util.List;

import static com.google.common.collect.Lists.transform;
import static java.util.Arrays.asList;

public class GroovyScript {

public static GroovyScript that(String descriptionOfScriptsBehaviour) {
return new GroovyScript(descriptionOfScriptsBehaviour);
}

public GroovyScript definedAs(String... lines) {
return this.definedAs(asList(lines));
}

public GroovyScript definedAs(List<String> lines) {
this.code = Joiner.on('\n').join(lines);

return this;
}

public GroovyScript andOutputs(String... lines) {
return definedAs(transform(asList(lines), mapEachLineTo("echo \"%s\";")));
}

public String code() {
return code;
}

@Override
public String toString() {
return description;
}

private GroovyScript(String descriptionOfScriptsBehaviour) {
this.description = descriptionOfScriptsBehaviour;
}

private Function<String, String> mapEachLineTo(final String template) {
return new Function<String, String>() {
@Nullable
@Override
public String apply(@Nullable String line) {
return String.format(template, line);
}
};
}

private final String description;

private String code = "";
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
package net.serenitybdd.screenplay.jenkins.tasks.configuration.build_steps;

public class GroovyScriptThat {
public static final GroovyScript Adds_A_Badge = GroovyScript.that("Adds a badge")
.definedAs("manager.addShortText('Coverage', 'black', 'repeating-linear-gradient(45deg, yellow, yellow 10px, Orange 10px, Orange 20px)', '0px', 'white')");
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
package net.serenitybdd.screenplay.jenkins.user_interface.project_configuration.build_steps;

import net.serenitybdd.screenplay.targets.Target;

public class GroovyPostBuildStep {
public static final Target Editor = Target.the("code editor").locatedBy("(//div[@descriptorid='org.jvnet.hudson.plugins.groovypostbuild.GroovyPostbuildRecorder']//textarea)[last()]");
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,64 @@
package features;

import com.smartcodeltd.jenkinsci.plugins.build_monitor.questions.ProjectWidget;
import com.smartcodeltd.jenkinsci.plugins.build_monitor.tasks.HaveABuildMonitorViewCreated;
import com.smartcodeltd.jenkinsci.plugins.build_monitor.tasks.ModifyControlPanelOptions;
import com.smartcodeltd.jenkinsci.plugins.build_monitor.tasks.ShowBadges;
import environment.JenkinsSandbox;
import net.serenitybdd.integration.jenkins.JenkinsInstance;
import net.serenitybdd.integration.jenkins.environment.rules.InstallPlugins;
import net.serenitybdd.junit.runners.SerenityRunner;
import net.serenitybdd.screenplay.Actor;
import net.serenitybdd.screenplay.abilities.BrowseTheWeb;
import net.serenitybdd.screenplay.jenkins.HaveAProjectCreated;
import net.serenitybdd.screenplay.jenkins.tasks.ScheduleABuild;
import net.serenitybdd.screenplay.jenkins.tasks.configuration.build_steps.AddAGroovyPostbuildScript;
import net.serenitybdd.screenplay.jenkins.tasks.configuration.build_steps.ExecuteAShellScript;
import net.serenitybdd.screenplay.jenkins.tasks.configuration.build_steps.GroovyScriptThat;
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 net.serenitybdd.screenplay.jenkins.tasks.configuration.build_steps.ShellScriptThat.Finishes_With_Success;
import static net.serenitybdd.screenplay.matchers.WebElementStateMatchers.isCurrentlyVisible;

@RunWith(SerenityRunner.class)
public class ShouldDisplayBadges {

Actor paul = Actor.named("Paul");

@Managed public WebDriver hisBrowser;

@Rule public JenkinsInstance jenkins = JenkinsSandbox.configure().afterStart(
InstallPlugins.fromUpdateCenter("buildtriggerbadge", "groovy-postbuild")
).create();

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

@Test
public void displaying_build_badges() throws Exception {
givenThat(paul).wasAbleTo(
Navigate.to(jenkins.url()),
HaveAProjectCreated.called("My App").andConfiguredTo(
ExecuteAShellScript.that(Finishes_With_Success),
AddAGroovyPostbuildScript.that(GroovyScriptThat.Adds_A_Badge)
),
ScheduleABuild.of("My App"),
HaveABuildMonitorViewCreated.showingAllTheProjects()
);

when(paul).attemptsTo(ModifyControlPanelOptions.to(ShowBadges.onTheDashboard()));

then(paul).should(seeThat(ProjectWidget.of("My App").badges(),
isCurrentlyVisible()
));
}
}
6 changes: 6 additions & 0 deletions build-monitor-plugin/pom.xml
Original file line number Diff line number Diff line change
Expand Up @@ -163,6 +163,12 @@
<version>1.26</version>
<optional>true</optional>
</dependency>
<dependency>
<groupId>org.jvnet.hudson.plugins</groupId>
<artifactId>groovy-postbuild</artifactId>
<version>2.3.1</version>
<optional>true</optional>
</dependency>
<!-- /Jenkins CI plugins supported by the Build Monitor -->

<dependency>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@
import hudson.scm.ChangeLogSet;

import java.util.Date;
import java.util.List;
import java.util.Set;
import java.util.TreeSet;

Expand Down Expand Up @@ -158,6 +159,11 @@ private <T> T nonNullIterable(T list) {
public <A extends Action> Optional<A> detailsOf(Class<A> jenkinsAction) {
return Optional.fromNullable(build.getAction(jenkinsAction));
}

@Override
public <A extends Action> List<A> allDetailsOf(Class<A> jenkinsAction) {
return build.getActions(jenkinsAction);
}

@Override
public String toString() {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,8 +3,10 @@
import com.google.common.base.Optional;
import com.smartcodeltd.jenkinsci.plugins.buildmonitor.viewmodel.duration.Duration;
import hudson.model.Action;
import hudson.model.BuildBadgeAction;
import hudson.model.Result;

import java.util.List;
import java.util.Set;

public interface BuildViewModel {
Expand All @@ -27,4 +29,5 @@ public interface BuildViewModel {
Set<String> committers();

<A extends Action> Optional<A> detailsOf(Class<A> jenkinsAction);
<A extends Action> List<A> allDetailsOf(Class<A> jenkinsAction);
}
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@
public class JobViews {
public static final String Claim = "claim";
public static final String Build_Failure_Analyzer = "build-failure-analyzer";
public static final String Groovy_Post_Build = "groovy-postbuild";

private final StaticJenkinsAPIs jenkins;
private final com.smartcodeltd.jenkinsci.plugins.buildmonitor.Config config;
Expand All @@ -39,6 +40,10 @@ public JobView viewOf(Job<?, ?> job) {
viewFeatures.add(new CanBeDiagnosedForProblems());
}

if (jenkins.hasPlugin(Groovy_Post_Build)) {
viewFeatures.add(new HasBadges());
}

return JobView.of(job, viewFeatures);
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -3,9 +3,12 @@
import com.google.common.base.Optional;
import com.smartcodeltd.jenkinsci.plugins.buildmonitor.viewmodel.duration.Duration;
import hudson.model.Action;
import hudson.model.BuildBadgeAction;
import hudson.model.Result;

import java.util.ArrayList;
import java.util.HashSet;
import java.util.List;
import java.util.Set;

public class NullBuildView implements BuildViewModel {
Expand Down Expand Up @@ -84,4 +87,9 @@ public Set<String> committers() {
public <A extends Action> Optional<A> detailsOf(Class<A> jenkinsAction) {
return Optional.absent();
}

@Override
public <A extends Action> List<A> allDetailsOf(Class<A> jenkinsAction) {
return new ArrayList<A>();
}
}
Loading

0 comments on commit 0334b96

Please sign in to comment.