MarkUnmatchedStepsAsPending.java

  1. package org.jbehave.core.steps;

  2. import java.util.ArrayList;
  3. import java.util.EnumMap;
  4. import java.util.List;
  5. import java.util.Map;
  6. import java.util.stream.Collectors;
  7. import java.util.stream.Stream;

  8. import org.jbehave.core.annotations.AfterScenario.Outcome;
  9. import org.jbehave.core.annotations.Scope;
  10. import org.jbehave.core.configuration.Keywords;
  11. import org.jbehave.core.i18n.LocalizedKeywords;
  12. import org.jbehave.core.model.Lifecycle;
  13. import org.jbehave.core.model.Meta;
  14. import org.jbehave.core.model.Scenario;
  15. import org.jbehave.core.steps.AbstractStepResult.Pending;
  16. import org.jbehave.core.steps.StepCreator.PendingStep;

  17. /**
  18.  * StepCollector that marks unmatched steps as {@link Pending}. It uses a
  19.  * {@link StepFinder} to prioritise {@link StepCandidate}s.
  20.  */
  21. public class MarkUnmatchedStepsAsPending implements StepCollector {

  22.     private final StepFinder stepFinder;
  23.     private final Keywords keywords;

  24.     public MarkUnmatchedStepsAsPending() {
  25.         this(new StepFinder());
  26.     }

  27.     public MarkUnmatchedStepsAsPending(StepFinder stepFinder) {
  28.         this(stepFinder, new LocalizedKeywords());
  29.     }

  30.     public MarkUnmatchedStepsAsPending(StepFinder stepFinder, Keywords keywords) {
  31.         this.stepFinder = stepFinder;
  32.         this.keywords = keywords;
  33.     }

  34.     @Override
  35.     public List<Step> collectBeforeOrAfterStoriesSteps(List<BeforeOrAfterStep> beforeOrAfterStoriesSteps) {
  36.         return beforeOrAfterStoriesSteps.stream().map(BeforeOrAfterStep::createStep).collect(Collectors.toList());
  37.     }

  38.     @Override
  39.     public List<Step> collectBeforeOrAfterStorySteps(List<BeforeOrAfterStep> beforeOrAfterStorySteps, Meta storyMeta) {
  40.         return createSteps(beforeOrAfterStorySteps, storyMeta);
  41.     }

  42.     @Override
  43.     public List<Step> collectBeforeScenarioSteps(List<BeforeOrAfterStep> beforeScenarioSteps,
  44.             Meta storyAndScenarioMeta) {
  45.         return createSteps(beforeScenarioSteps, storyAndScenarioMeta);
  46.     }

  47.     @Override
  48.     public List<Step> collectAfterScenarioSteps(List<BeforeOrAfterStep> afterScenarioSteps, Meta storyAndScenarioMeta) {
  49.         return afterScenarioSteps.stream().map(step -> step.createStepUponOutcome(storyAndScenarioMeta)).collect(
  50.                 Collectors.toList());
  51.     }

  52.     @Override
  53.     public Map<Stage, List<Step>> collectLifecycleSteps(List<StepCandidate> stepCandidates, Lifecycle lifecycle,
  54.             Meta storyAndScenarioMeta, Scope scope, Map<String, String> parameters, StepMonitor stepMonitor) {
  55.         List<Step> beforeSteps = collectMatchedSteps(lifecycle.getBeforeSteps(scope), parameters, stepCandidates,
  56.                 null, stepMonitor);
  57.         List<Step> afterSteps = Stream.of(Outcome.values())
  58.                 .map(outcome -> collectMatchedSteps(lifecycle.getAfterSteps(scope, outcome, storyAndScenarioMeta),
  59.                         parameters, stepCandidates, outcome, stepMonitor))
  60.                 .flatMap(List::stream)
  61.                 .collect(Collectors.toList());

  62.         Map<Stage, List<Step>> steps = new EnumMap<>(Stage.class);
  63.         steps.put(Stage.BEFORE, beforeSteps);
  64.         steps.put(Stage.AFTER, afterSteps);
  65.         return steps;
  66.     }

  67.     @Override
  68.     public List<Step> collectScenarioSteps(List<StepCandidate> stepCandidates, Scenario scenario,
  69.             Map<String, String> parameters, StepMonitor stepMonitor) {
  70.         return collectMatchedSteps(scenario.getSteps(), parameters, stepCandidates, null, stepMonitor);
  71.     }

  72.     private List<Step> createSteps(List<BeforeOrAfterStep> beforeOrAfterSteps, Meta meta) {
  73.         return beforeOrAfterSteps.stream().map(step -> step.createStepWith(meta)).collect(Collectors.toList());
  74.     }

  75.     private List<Step> collectMatchedSteps(List<String> stepsAsString, Map<String, String> namedParameters,
  76.             List<StepCandidate> stepCandidates, Outcome outcome, StepMonitor stepMonitor) {
  77.         List<Step> steps = new ArrayList<>();
  78.         String previousNonAndStep = null;
  79.         for (String stepAsString : stepsAsString) {
  80.             // pending is default step, overridden below
  81.             Step step = StepCreator.createPendingStep(stepAsString, previousNonAndStep);
  82.             List<StepCandidate> prioritisedCandidates = stepFinder.prioritise(stepAsString,
  83.                     new ArrayList<>(stepCandidates));
  84.             for (StepCandidate candidate : prioritisedCandidates) {
  85.                 candidate.useStepMonitor(stepMonitor);
  86.                 if (candidate.ignore(stepAsString)) {
  87.                     // ignorable steps are added so they can be reported
  88.                     step = StepCreator.createIgnorableStep(stepAsString);
  89.                     break;
  90.                 }
  91.                 if (candidate.comment(stepAsString)) {
  92.                     // comments are added so they can be reported
  93.                     step = StepCreator.createComment(stepAsString);
  94.                     break;
  95.                 }
  96.                 if (candidate.matches(stepAsString, previousNonAndStep)) {
  97.                     // step matches candidate
  98.                     if (candidate.isPending()) {
  99.                         ((PendingStep) step).annotatedOn(candidate.getMethod());
  100.                     } else {
  101.                         List<Step> composedSteps = new ArrayList<>();
  102.                         if (candidate.isComposite()) {
  103.                             candidate.addComposedSteps(composedSteps, stepAsString, namedParameters,
  104.                                     prioritisedCandidates);
  105.                         }
  106.                         if (outcome != null) {
  107.                             step = candidate.createMatchedStepUponOutcome(stepAsString, namedParameters, composedSteps,
  108.                                     outcome);
  109.                         } else {
  110.                             step = candidate.createMatchedStep(stepAsString, namedParameters, composedSteps);
  111.                         }
  112.                     }
  113.                     if (!(keywords.isAndStep(stepAsString) || keywords.isIgnorableStep(stepAsString))) {
  114.                         // only update previous step if not AND or IGNORABLE step
  115.                         previousNonAndStep = stepAsString;
  116.                     }
  117.                     break;
  118.                 }
  119.             }
  120.             if (!(keywords.isAndStep(stepAsString) || keywords.isIgnorableStep(stepAsString))) {
  121.                 previousNonAndStep = stepAsString;
  122.             }
  123.             steps.add(step);
  124.         }
  125.         return steps;
  126.     }
  127. }