Coverage Report - org.jbehave.core.reporters.TemplateableOutput
 
Classes in this File Line Coverage Branch Coverage Complexity
TemplateableOutput
0%
0/75
0%
0/10
1.28
TemplateableOutput$OutputKeywords
0%
0/25
N/A
1.28
TemplateableOutput$OutputMeta
0%
0/7
0%
0/2
1.28
TemplateableOutput$OutputNarrative
0%
0/6
N/A
1.28
TemplateableOutput$OutputParameter
0%
0/7
N/A
1.28
TemplateableOutput$OutputRestart
0%
0/2
N/A
1.28
TemplateableOutput$OutputScenario
0%
0/21
0%
0/4
1.28
TemplateableOutput$OutputStep
0%
0/50
0%
0/20
1.28
TemplateableOutput$OutputStep$StepFormattingFailed
0%
0/2
N/A
1.28
TemplateableOutput$OutputStory
0%
0/9
N/A
1.28
 
 1  
 package org.jbehave.core.reporters;
 2  
 
 3  
 import java.io.File;
 4  
 import java.io.FileWriter;
 5  
 import java.io.Writer;
 6  
 import java.text.MessageFormat;
 7  
 import java.util.ArrayList;
 8  
 import java.util.HashMap;
 9  
 import java.util.List;
 10  
 import java.util.Map;
 11  
 import java.util.regex.Matcher;
 12  
 import java.util.regex.Pattern;
 13  
 import org.apache.commons.lang.StringUtils;
 14  
 import org.jbehave.core.configuration.Keywords;
 15  
 import org.jbehave.core.model.ExamplesTable;
 16  
 import org.jbehave.core.model.GivenStories;
 17  
 import org.jbehave.core.model.Meta;
 18  
 import org.jbehave.core.model.Narrative;
 19  
 import org.jbehave.core.model.OutcomesTable;
 20  
 import org.jbehave.core.model.Scenario;
 21  
 import org.jbehave.core.model.Story;
 22  
 
 23  
 import static org.jbehave.core.steps.StepCreator.PARAMETER_TABLE_END;
 24  
 import static org.jbehave.core.steps.StepCreator.PARAMETER_TABLE_START;
 25  
 import static org.jbehave.core.steps.StepCreator.PARAMETER_VALUE_END;
 26  
 import static org.jbehave.core.steps.StepCreator.PARAMETER_VALUE_START;
 27  
 
 28  
 /**
 29  
  * <p>
 30  
  * Story reporter that outputs to a template.
 31  
  * </p>
 32  
  */
 33  
 public class TemplateableOutput implements StoryReporter {
 34  
 
 35  
     private final File file;
 36  
     private final Keywords keywords;
 37  
     private final TemplateProcessor processor;
 38  
     private final String templatePath;
 39  0
     private OutputStory outputStory = new OutputStory();
 40  0
     private OutputScenario outputScenario = new OutputScenario();
 41  
     private OutputStep failedStep;
 42  
 
 43  0
     public TemplateableOutput(File file, Keywords keywords, TemplateProcessor processor, String templatePath) {
 44  0
         this.file = file;
 45  0
         this.keywords = keywords;
 46  0
         this.processor = processor;
 47  0
         this.templatePath = templatePath;
 48  0
     }
 49  
 
 50  
     public void storyNotAllowed(Story story, String filter) {
 51  0
         this.outputStory.notAllowedBy = filter;
 52  0
     }
 53  
 
 54  
     public void beforeStory(Story story, boolean givenStory) {
 55  0
         this.outputStory = new OutputStory();
 56  0
         this.outputStory.description = story.getDescription().asString();
 57  0
         this.outputStory.path = story.getPath();
 58  0
         if (!story.getMeta().isEmpty()) {
 59  0
             this.outputStory.meta = new OutputMeta(story.getMeta());
 60  
         }
 61  0
     }
 62  
 
 63  
     public void narrative(Narrative narrative) {
 64  0
         if (!narrative.isEmpty()) {
 65  0
             this.outputStory.narrative = new OutputNarrative(narrative);
 66  
         }
 67  0
     }
 68  
 
 69  
     public void scenarioNotAllowed(Scenario scenario, String filter) {
 70  0
         this.outputScenario.notAllowedBy = filter;
 71  0
     }
 72  
 
 73  
     public void beforeScenario(String title) {
 74  0
         this.outputScenario = new OutputScenario();
 75  0
         this.outputScenario.title = title;
 76  0
     }
 77  
 
 78  
     public void successful(String step) {
 79  0
         this.outputScenario.addStep(new OutputStep(step, "successful"));
 80  0
     }
 81  
 
 82  
     public void ignorable(String step) {
 83  0
         this.outputScenario.addStep(new OutputStep(step, "ignorable"));
 84  0
     }
 85  
 
 86  
     public void pending(String step) {
 87  0
         this.outputScenario.addStep(new OutputStep(step, "pending"));
 88  0
     }
 89  
 
 90  
     public void notPerformed(String step) {
 91  0
         this.outputScenario.addStep(new OutputStep(step, "notPerformed"));
 92  0
     }
 93  
 
 94  
     public void failed(String step, Throwable storyFailure) {
 95  0
         this.failedStep = new OutputStep(step, "failed");
 96  0
         failedStep.failure = storyFailure;
 97  0
         this.outputScenario.addStep(failedStep);
 98  0
     }
 99  
 
 100  
     public void failedOutcomes(String step, OutcomesTable table) {
 101  0
         failed(step, table.failureCause());
 102  0
         this.failedStep.outcomes = table;
 103  0
     }
 104  
 
 105  
     public void givenStories(GivenStories givenStories) {
 106  0
         if (!givenStories.getStories().isEmpty()) {
 107  0
             this.outputScenario.givenStories = givenStories;
 108  
         }
 109  0
     }
 110  
 
 111  
     public void givenStories(List<String> storyPaths) {
 112  0
         givenStories(new GivenStories(StringUtils.join(storyPaths, ",")));
 113  0
     }
 114  
 
 115  
     public void scenarioMeta(Meta meta) {
 116  0
         if (!meta.isEmpty()) {
 117  0
             this.outputScenario.meta = new OutputMeta(meta);
 118  
         }
 119  0
     }
 120  
 
 121  
     public void beforeExamples(List<String> steps, ExamplesTable table) {
 122  0
         this.outputScenario.examplesSteps = steps;
 123  0
         this.outputScenario.examplesTable = table;
 124  0
     }
 125  
 
 126  
     public void example(Map<String, String> parameters) {
 127  0
         this.outputScenario.examples.add(parameters);
 128  0
         this.outputScenario.currentExample = parameters;
 129  0
     }
 130  
 
 131  
     public void afterExamples() {
 132  0
     }
 133  
 
 134  
     public void dryRun() {
 135  0
     }
 136  
 
 137  
     public void afterScenario() {
 138  0
         this.outputStory.scenarios.add(outputScenario);
 139  0
     }
 140  
 
 141  
     public void pendingMethods(List<String> methods) {
 142  0
         this.outputStory.pendingMethods = methods;
 143  0
     }
 144  
 
 145  
     public void restarted(String step, Throwable cause) {
 146  0
         this.outputScenario.addStep(new OutputRestart(step, cause.getMessage()));
 147  0
     }
 148  
 
 149  
     public void cancelled() {
 150  0
     }
 151  
 
 152  
     public void afterStory(boolean givenStory) {
 153  0
         if (!givenStory) {
 154  0
             Map<String, Object> model = newDataModel();
 155  0
             model.put("story", outputStory);
 156  0
             model.put("keywords", new OutputKeywords(keywords));
 157  0
             write(file, templatePath, model);
 158  
         }
 159  0
     }
 160  
 
 161  
     private File write(File file, String resource, Map<String, Object> dataModel) {
 162  
         try {
 163  0
             file.getParentFile().mkdirs();
 164  0
             Writer writer = new FileWriter(file);
 165  0
             processor.process(resource, dataModel, writer);
 166  0
             return file;
 167  0
         } catch (Exception e) {
 168  0
             throw new RuntimeException(resource, e);
 169  
         }
 170  
     }
 171  
 
 172  
     private Map<String, Object> newDataModel() {
 173  0
         return new HashMap<String, Object>();
 174  
     }
 175  
 
 176  
     public static class OutputKeywords {
 177  
 
 178  
         private final Keywords keywords;
 179  
 
 180  0
         public OutputKeywords(Keywords keywords) {
 181  0
             this.keywords = keywords;
 182  0
         }
 183  
 
 184  
         public String getMeta() {
 185  0
             return keywords.meta();
 186  
         }
 187  
 
 188  
         public String getMetaProperty() {
 189  0
             return keywords.metaProperty();
 190  
         }
 191  
 
 192  
         public String getNarrative() {
 193  0
             return keywords.narrative();
 194  
         }
 195  
 
 196  
         public String getInOrderTo() {
 197  0
             return keywords.inOrderTo();
 198  
         }
 199  
 
 200  
         public String getAsA() {
 201  0
             return keywords.asA();
 202  
         }
 203  
 
 204  
         public String getiWantTo() {
 205  0
             return keywords.iWantTo();
 206  
         }
 207  
 
 208  
         public String getScenario() {
 209  0
             return keywords.scenario();
 210  
         }
 211  
 
 212  
         public String getGivenStories() {
 213  0
             return keywords.givenStories();
 214  
         }
 215  
 
 216  
         public String getExamplesTable() {
 217  0
             return keywords.examplesTable();
 218  
         }
 219  
 
 220  
         public String getExamplesTableRow() {
 221  0
             return keywords.examplesTableRow();
 222  
         }
 223  
 
 224  
         public String getExamplesTableHeaderSeparator() {
 225  0
             return keywords.examplesTableHeaderSeparator();
 226  
         }
 227  
 
 228  
         public String getExamplesTableValueSeparator() {
 229  0
             return keywords.examplesTableValueSeparator();
 230  
         }
 231  
 
 232  
         public String getExamplesTableIgnorableSeparator() {
 233  0
             return keywords.examplesTableIgnorableSeparator();
 234  
         }
 235  
 
 236  
         public String getGiven() {
 237  0
             return keywords.given();
 238  
         }
 239  
 
 240  
         public String getWhen() {
 241  0
             return keywords.when();
 242  
         }
 243  
 
 244  
         public String getThen() {
 245  0
             return keywords.then();
 246  
         }
 247  
 
 248  
         public String getAnd() {
 249  0
             return keywords.and();
 250  
         }
 251  
 
 252  
         public String getIgnorable() {
 253  0
             return keywords.ignorable();
 254  
         }
 255  
 
 256  
         public String getPending() {
 257  0
             return keywords.pending();
 258  
         }
 259  
 
 260  
         public String getNotPerformed() {
 261  0
             return keywords.notPerformed();
 262  
         }
 263  
 
 264  
         public String getFailed() {
 265  0
             return keywords.failed();
 266  
         }
 267  
 
 268  
         public String getDryRun() {
 269  0
             return keywords.dryRun();
 270  
         }
 271  
 
 272  
     }
 273  
 
 274  0
     public static class OutputStory {
 275  
         private String description;
 276  
         private String path;
 277  
         private OutputMeta meta;
 278  
         private OutputNarrative narrative;
 279  
         private String notAllowedBy;
 280  
         private List<String> pendingMethods;
 281  0
         private List<OutputScenario> scenarios = new ArrayList<OutputScenario>();
 282  
 
 283  
         public String getDescription() {
 284  0
             return description;
 285  
         }
 286  
 
 287  
         public String getPath() {
 288  0
             return path;
 289  
         }
 290  
 
 291  
         public OutputMeta getMeta() {
 292  0
             return meta;
 293  
         }
 294  
 
 295  
         public OutputNarrative getNarrative() {
 296  0
             return narrative;
 297  
         }
 298  
 
 299  
         public String getNotAllowedBy() {
 300  0
             return notAllowedBy;
 301  
         }
 302  
 
 303  
         public List<String> getPendingMethods() {
 304  0
             return pendingMethods;
 305  
         }
 306  
 
 307  
         public List<OutputScenario> getScenarios() {
 308  0
             return scenarios;
 309  
         }
 310  
     }
 311  
 
 312  
     public static class OutputMeta {
 313  
 
 314  
         private final Meta meta;
 315  
 
 316  0
         public OutputMeta(Meta meta) {
 317  0
             this.meta = meta;
 318  0
         }
 319  
 
 320  
         public Map<String, String> getProperties() {
 321  0
             Map<String, String> properties = new HashMap<String, String>();
 322  0
             for (String name : meta.getPropertyNames()) {
 323  0
                 properties.put(name, meta.getProperty(name));
 324  
             }
 325  0
             return properties;
 326  
         }
 327  
 
 328  
     }
 329  
 
 330  
     public static class OutputNarrative {
 331  
         private final Narrative narrative;
 332  
 
 333  0
         public OutputNarrative(Narrative narrative) {
 334  0
             this.narrative = narrative;
 335  0
         }
 336  
 
 337  
         public String getInOrderTo() {
 338  0
             return narrative.inOrderTo();
 339  
         }
 340  
 
 341  
         public String getAsA() {
 342  0
             return narrative.asA();
 343  
         }
 344  
 
 345  
         public String getiWantTo() {
 346  0
             return narrative.iWantTo();
 347  
         }
 348  
 
 349  
     }
 350  
 
 351  0
     public static class OutputScenario {
 352  
         private String title;
 353  0
         private List<OutputStep> steps = new ArrayList<OutputStep>();
 354  
         private OutputMeta meta;
 355  
         private GivenStories givenStories;
 356  
         private String notAllowedBy;
 357  
         private List<String> examplesSteps;
 358  
         private ExamplesTable examplesTable;
 359  
         private Map<String, String> currentExample;
 360  0
         private List<Map<String, String>> examples = new ArrayList<Map<String, String>>();
 361  0
         private Map<Map<String, String>, List<OutputStep>> stepsByExample = new HashMap<Map<String, String>, List<OutputStep>>();
 362  
 
 363  
         public String getTitle() {
 364  0
             return title;
 365  
         }
 366  
 
 367  
         public void addStep(OutputStep outputStep) {
 368  0
             if (examplesTable == null) {
 369  0
                 steps.add(outputStep);
 370  
             } else {
 371  0
                 List<OutputStep> currentExampleSteps = stepsByExample.get(currentExample);
 372  0
                 if (currentExampleSteps == null) {
 373  0
                     currentExampleSteps = new ArrayList<OutputStep>();
 374  0
                     stepsByExample.put(currentExample, currentExampleSteps);
 375  
                 }
 376  0
                 currentExampleSteps.add(outputStep);
 377  
             }
 378  0
         }
 379  
 
 380  
         public List<OutputStep> getSteps() {
 381  0
             return steps;
 382  
         }
 383  
 
 384  
         public List<OutputStep> getStepsByExample(Map<String, String> example) {
 385  0
             return stepsByExample.get(example);
 386  
         }
 387  
 
 388  
         public OutputMeta getMeta() {
 389  0
             return meta;
 390  
         }
 391  
 
 392  
         public GivenStories getGivenStories() {
 393  0
             return givenStories;
 394  
         }
 395  
 
 396  
         public String getNotAllowedBy() {
 397  0
             return notAllowedBy;
 398  
         }
 399  
 
 400  
         public List<String> getExamplesSteps() {
 401  0
             return examplesSteps;
 402  
         }
 403  
 
 404  
         public ExamplesTable getExamplesTable() {
 405  0
             return examplesTable;
 406  
         }
 407  
 
 408  
         public List<Map<String, String>> getExamples() {
 409  0
             return examples;
 410  
         }
 411  
     }
 412  
 
 413  
     public static class OutputRestart extends OutputStep {
 414  
 
 415  
         public OutputRestart(String step, String outcome) {
 416  0
             super(step, outcome);
 417  0
         }
 418  
 
 419  
     }
 420  
 
 421  0
     public static class OutputStep {
 422  
         private final String step;
 423  
         private final String outcome;
 424  
         private Throwable failure;
 425  
         private OutcomesTable outcomes;
 426  
         private ExamplesTable table;
 427  
         private List<OutputParameter> parameters;
 428  
         private String stepPattern;
 429  
 
 430  0
         public OutputStep(String step, String outcome) {
 431  0
             this.step = step;
 432  0
             this.outcome = outcome;
 433  0
             parseTable();
 434  0
             parseParameters();
 435  0
             createStepPattern();
 436  0
         }
 437  
 
 438  
         public String getStep() {
 439  0
             return step;
 440  
         }
 441  
 
 442  
         public String getStepPattern() {
 443  0
             return stepPattern;
 444  
         }
 445  
 
 446  
         public List<OutputParameter> getParameters() {
 447  0
             return parameters;
 448  
         }
 449  
 
 450  
         public String getOutcome() {
 451  0
             return outcome;
 452  
         }
 453  
 
 454  
         public Throwable getFailure() {
 455  0
             return failure;
 456  
         }
 457  
 
 458  
         public String getFailureCause() {
 459  0
             if (failure != null) {
 460  0
                 return new StackTraceFormatter(true).stackTrace(failure);
 461  
             }
 462  0
             return "";
 463  
         }
 464  
 
 465  
         public ExamplesTable getTable() {
 466  0
             return table;
 467  
         }
 468  
 
 469  
         public OutcomesTable getOutcomes() {
 470  0
             return outcomes;
 471  
         }
 472  
 
 473  
         public String getOutcomesFailureCause() {
 474  0
             if (outcomes.failureCause() != null) {
 475  0
                 return new StackTraceFormatter(true).stackTrace(outcomes.failureCause());
 476  
             }
 477  0
             return "";
 478  
         }
 479  
 
 480  
         public String getFormattedStep(String parameterPattern) {
 481  0
             if (!parameters.isEmpty()) {
 482  
                 try {
 483  0
                     return MessageFormat.format(stepPattern, formatParameters(parameterPattern));
 484  0
                 } catch (RuntimeException e) {
 485  0
                     throw new StepFormattingFailed(stepPattern, parameterPattern, parameters, e);
 486  
                 }
 487  
             }
 488  0
             return stepPattern;
 489  
         }
 490  
 
 491  
         private Object[] formatParameters(String parameterPattern) {
 492  0
             Object[] arguments = new Object[parameters.size()];
 493  0
             for (int a = 0; a < parameters.size(); a++) {
 494  0
                 arguments[a] = MessageFormat.format(parameterPattern, parameters.get(a).getValue());
 495  
             }
 496  0
             return arguments;
 497  
         }
 498  
 
 499  
         private void parseParameters() {
 500  
             // first, look for parametrised scenarios
 501  0
             parameters = findParameters(PARAMETER_VALUE_START + PARAMETER_VALUE_START, PARAMETER_VALUE_END
 502  
                     + PARAMETER_VALUE_END);
 503  
             // second, look for normal scenarios
 504  0
             if (parameters.isEmpty()) {
 505  0
                 parameters = findParameters(PARAMETER_VALUE_START, PARAMETER_VALUE_END);
 506  
             }
 507  0
         }
 508  
 
 509  
         private List<OutputParameter> findParameters(String start, String end) {
 510  0
             List<OutputParameter> parameters = new ArrayList<OutputParameter>();
 511  0
             Matcher matcher = Pattern.compile("(" + start + "[\\w\\s\\.\\-\\_\\*]*" + end + ")(\\W|\\Z)",
 512  
                     Pattern.DOTALL).matcher(step);
 513  0
             while (matcher.find()) {
 514  0
                 parameters.add(new OutputParameter(step, matcher.start(), matcher.end()));
 515  
             }
 516  0
             return parameters;
 517  
         }
 518  
 
 519  
         private void createStepPattern() {
 520  0
             this.stepPattern = step;
 521  0
             if (table != null) {
 522  0
                 this.stepPattern = StringUtils.replaceOnce(stepPattern, PARAMETER_TABLE_START + table.asString()
 523  
                         + PARAMETER_TABLE_END, "");
 524  
             }
 525  0
             for (int count = 0; count < parameters.size(); count++) {
 526  0
                 String value = parameters.get(count).toString();
 527  0
                 this.stepPattern = stepPattern.replace(value, "{" + count + "}");
 528  
             }
 529  0
         }
 530  
 
 531  
         private void parseTable() {
 532  0
             if (step.contains(PARAMETER_TABLE_START) && step.contains(PARAMETER_TABLE_END)) {
 533  0
                 String tableAsString = StringUtils.substringBetween(step, PARAMETER_TABLE_START, PARAMETER_TABLE_END);
 534  0
                 table = new ExamplesTable(tableAsString);
 535  
             }
 536  0
         }
 537  
 
 538  
         @SuppressWarnings("serial")
 539  
         public static class StepFormattingFailed extends RuntimeException {
 540  
 
 541  
             public StepFormattingFailed(String stepPattern, String parameterPattern, List<OutputParameter> parameters,
 542  
                     RuntimeException cause) {
 543  0
                 super("Failed to format step '" + stepPattern + "' with parameter pattern '" + parameterPattern
 544  
                         + "' and parameters: " + parameters, cause);
 545  0
             }
 546  
 
 547  
         }
 548  
 
 549  
     }
 550  
 
 551  
     public static class OutputParameter {
 552  
         private final String parameter;
 553  
 
 554  0
         public OutputParameter(String pattern, int start, int end) {
 555  0
             this.parameter = pattern.substring(start, end).trim();
 556  0
         }
 557  
 
 558  
         public String getValue() {
 559  0
             String value = StringUtils.remove(parameter, PARAMETER_VALUE_START);
 560  0
             value = StringUtils.remove(value, PARAMETER_VALUE_END);
 561  0
             return value;
 562  
         }
 563  
 
 564  
         @Override
 565  
         public String toString() {
 566  0
             return parameter;
 567  
         }
 568  
     }
 569  
 
 570  
 }