Skip to content

Commit

Permalink
JBEHAVE-1605 Fix execution of nested composite steps in the After Sto…
Browse files Browse the repository at this point in the history
…ry hook following a failed story
  • Loading branch information
draker94 authored Nov 21, 2024
1 parent bfbff3c commit a41219c
Show file tree
Hide file tree
Showing 5 changed files with 43 additions and 16 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -424,6 +424,15 @@ public SomethingHappened(UUIDExceptionWrapper failure) {
@Override
public State run(Step step, List<StepResult> results, Keywords keywords, StoryReporter reporter) {
StepResult result = step.doNotPerform(reporter, getFailure());

List<Step> composedSteps = step.getComposedSteps();
if (!composedSteps.isEmpty()) {
reporter.beforeComposedSteps();
for (Step composedStep : composedSteps) {
run(composedStep, results, keywords, reporter);
}
reporter.afterComposedSteps();
}
results.add(result);
result.describeTo(reporter);
return this;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -117,7 +117,7 @@ private List<Step> collectMatchedSteps(List<String> stepsAsString, Map<String, S
List<Step> composedSteps = new ArrayList<>();
if (candidate.isComposite()) {
candidate.addComposedSteps(composedSteps, stepAsString, namedParameters,
prioritisedCandidates);
prioritisedCandidates, outcome);
}
if (outcome != null) {
step = candidate.createMatchedStepUponOutcome(stepAsString, namedParameters, composedSteps,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -186,7 +186,7 @@ public Step createMatchedStepUponOutcome(String stepAsString, Map<String, String
}

public void addComposedSteps(List<Step> steps, String stepAsString, Map<String, String> namedParameters,
List<StepCandidate> allCandidates) {
List<StepCandidate> allCandidates, Outcome outcome) {
Map<String, String> matchedParameters = stepCreator.matchedParameters(method,
keywords.stepWithoutStartingWord(stepAsString), namedParameters);

Expand All @@ -195,7 +195,7 @@ public void addComposedSteps(List<Step> steps, String stepAsString, Map<String,

String previousNonAndStep = null;
for (String composedStep : composedSteps) {
addComposedStep(steps, composedStep, previousNonAndStep, mergedParameters, allCandidates);
addComposedStep(steps, composedStep, previousNonAndStep, mergedParameters, allCandidates, outcome);
if (!(keywords.isAndStep(composedStep) || keywords.isIgnorableStep(composedStep))) {
// only update previous step if not AND or IGNORABLE step
previousNonAndStep = composedStep;
Expand All @@ -204,7 +204,7 @@ public void addComposedSteps(List<Step> steps, String stepAsString, Map<String,
}

private void addComposedStep(List<Step> steps, String composedStep, String previousNonAndStep,
Map<String, String> matchedParameters, List<StepCandidate> allCandidates) {
Map<String, String> matchedParameters, List<StepCandidate> allCandidates, Outcome outcome) {
if (ignore(composedStep)) {
// ignorable steps are added so they can be reported
steps.add(StepCreator.createIgnorableStep(composedStep));
Expand All @@ -217,9 +217,11 @@ private void addComposedStep(List<Step> steps, String composedStep, String previ
List<Step> composedSteps = new ArrayList<>();
if (candidate.isComposite()) {
// candidate is itself composite: recursively add composed steps
candidate.addComposedSteps(composedSteps, composedStep, matchedParameters, allCandidates);
candidate.addComposedSteps(composedSteps, composedStep, matchedParameters, allCandidates, outcome);
}
steps.add(candidate.createMatchedStep(composedStep, matchedParameters, composedSteps));
steps.add(outcome != null
? candidate.createMatchedStepUponOutcome(composedStep, matchedParameters, composedSteps, outcome)
: candidate.createMatchedStep(composedStep, matchedParameters, composedSteps));
} else {
steps.add(StepCreator.createPendingStep(composedStep, previousNonAndStep));
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@
import static org.hamcrest.Matchers.is;
import static org.hamcrest.Matchers.notNullValue;
import static org.jbehave.core.steps.StepCandidateBehaviour.candidateMatchingStep;
import static org.junit.jupiter.api.Assertions.assertEquals;
import static org.mockito.ArgumentMatchers.any;
import static org.mockito.ArgumentMatchers.eq;
import static org.mockito.Mockito.mock;
Expand All @@ -18,6 +19,7 @@

import com.thoughtworks.paranamer.BytecodeReadingParanamer;

import org.jbehave.core.annotations.AfterScenario;
import org.jbehave.core.annotations.Composite;
import org.jbehave.core.annotations.Given;
import org.jbehave.core.annotations.Named;
Expand Down Expand Up @@ -50,7 +52,7 @@ void shouldMatchInnerCompositeStepWithoutParamsAndMonitorIt() {
innerCompositeCandidate.useStepMonitor(monitor);

outerCompositeCandidate.addComposedSteps(new ArrayList<>(), outerCompositeStep, new HashMap<>(),
listCandidates);
listCandidates, null);
verify(monitor).stepMatchesPattern(eq(innerCompositeStep), eq(true), any(), any(), any());
}

Expand All @@ -72,9 +74,10 @@ private void shouldMatchCompositesAndCreateComposedStepsUsingMatchedParameters(C
namedParameters.put("customer", "Ms Smith");
List<Step> composedSteps = new ArrayList<>();
candidate.addComposedSteps(composedSteps, "Given Mr Jones has previously bought a ticket", namedParameters,
candidates);
candidates, null);
assertThat(composedSteps.size(), equalTo(2));
for (Step step : composedSteps) {
assertEquals(StepCreator.ParametrisedStep.class, step.getClass());
step.perform(mock(StoryReporter.class), null);
}
assertThat(steps.loggedIn, equalTo("Mr Jones"));
Expand Down Expand Up @@ -123,7 +126,7 @@ void shouldMatchCompositesAndCreateComposedStepsUsingNamedParameters() {
namedParameters.put("product", "ticket");
List<Step> composedSteps = new ArrayList<>();
candidate.addComposedSteps(composedSteps, "Given <customer> has previously bought a <product>", namedParameters,
candidates);
candidates, null);
assertThat(composedSteps.size(), equalTo(2));
for (Step step : composedSteps) {
step.perform(mock(StoryReporter.class), null);
Expand Down Expand Up @@ -170,7 +173,7 @@ void shouldMatchCompositesAndCreateComposedStepsUsingParanamerNamedParameters()
namedParameters.put("product", "ticket");
List<Step> composedSteps = new ArrayList<>();
candidate.addComposedSteps(composedSteps, "Given <customer> has previously bought a <product>", namedParameters,
candidates);
candidates, null);
assertThat(composedSteps.size(), equalTo(2));
for (Step step : composedSteps) {
step.perform(mock(StoryReporter.class), null);
Expand Down Expand Up @@ -220,7 +223,7 @@ void shouldMatchCompositesAndCreateComposedNestedSteps() {
assertThat(candidate.isComposite(), is(true));
Map<String, String> noNamedParameters = new HashMap<>();
List<Step> composedSteps = new ArrayList<>();
candidate.addComposedSteps(composedSteps, "Then all buttons are enabled", noNamedParameters, candidates);
candidate.addComposedSteps(composedSteps, "Then all buttons are enabled", noNamedParameters, candidates, null);
assertThat(composedSteps.size(), equalTo(2));
for (Step step : composedSteps) {
StoryReporter storyReporter = mock(StoryReporter.class);
Expand Down Expand Up @@ -270,7 +273,7 @@ void shouldMatchCompositesWhenStepParameterIsProvided() {
assertThat(candidate.isComposite(), is(true));
Map<String, String> noNamedParameters = new HashMap<>();
List<Step> composedSteps = new ArrayList<>();
candidate.addComposedSteps(composedSteps, "When I login", noNamedParameters, candidates);
candidate.addComposedSteps(composedSteps, "When I login", noNamedParameters, candidates, null);
assertThat(composedSteps.size(), equalTo(1));
for (Step step : composedSteps) {
step.perform(mock(StoryReporter.class), null);
Expand Down Expand Up @@ -304,7 +307,7 @@ void recursiveCompositesShouldWorkWithSomeMissingParameters() {
Map<String, String> noNamedParameters = new HashMap<>();
List<Step> composedSteps = new ArrayList<>();
candidate.addComposedSteps(composedSteps, "Given I am logged in as someUserName", noNamedParameters,
candidates);
candidates, null);
for (Step step : composedSteps) {
step.perform(mock(StoryReporter.class), null);
}
Expand Down Expand Up @@ -367,7 +370,7 @@ void shouldIgnoreCompositesIgnorableStep() {
assertThat(candidate.isComposite(), is(true));
Map<String, String> noNamedParameters = new HashMap<>();
List<Step> composedSteps = new ArrayList<>();
candidate.addComposedSteps(composedSteps, compositeName, noNamedParameters, candidates);
candidate.addComposedSteps(composedSteps, compositeName, noNamedParameters, candidates, null);
StoryReporter reporter = mock(StoryReporter.class);
for (Step step : composedSteps) {
StepResult result = step.perform(reporter, null);
Expand Down Expand Up @@ -397,7 +400,7 @@ void shouldCommentCompositesComment() {
assertThat(candidate.isComposite(), is(true));
Map<String, String> noNamedParameters = new HashMap<>();
List<Step> composedSteps = new ArrayList<>();
candidate.addComposedSteps(composedSteps, compositeName, noNamedParameters, candidates);
candidate.addComposedSteps(composedSteps, compositeName, noNamedParameters, candidates, null);
StoryReporter reporter = mock(StoryReporter.class);
for (Step step : composedSteps) {
StepResult result = step.perform(reporter, null);
Expand All @@ -406,6 +409,19 @@ void shouldCommentCompositesComment() {
Mockito.verify(reporter).comment("!-- comment");
}

@Test
void shouldWrapCompositeStepsUponOutcome() {
CompositeStepsWithParameterMissing steps = new CompositeStepsWithParameterMissing();
String compositeStep = "Given I am logged in as USER";
List<StepCandidate> listCandidates = steps.listCandidates();
StepCandidate candidate = candidateMatchingStep(listCandidates, compositeStep);
List<Step> compositeSteps = new ArrayList<>();

candidate.addComposedSteps(compositeSteps, compositeStep, new HashMap<>(),
listCandidates, AfterScenario.Outcome.ANY);
compositeSteps.forEach(s -> assertEquals(StepCreator.UponAnyStep.class, s.getClass()));
}

static class CompositeWithComment extends Steps {

@When("comment my comment")
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -201,7 +201,7 @@ void shouldAddPrioritizedComposedStepsWhenACompositeIsMatched() {

// Then
verify(compositeCandidate, times(1)).addComposedSteps(new ArrayList<>(), compositeAsText, parameters,
asList(compositeCandidate, composedCandidate1, composedCandidate2));
asList(compositeCandidate, composedCandidate1, composedCandidate2), null);
}

@Test
Expand Down

0 comments on commit a41219c

Please sign in to comment.