tw.teddysoft.ezspec.keyword.Feature Maven / Gradle / Ivy
package tw.teddysoft.ezspec.keyword;
import tw.teddysoft.ezspec.keyword.visitor.SpecificationElement;
import tw.teddysoft.ezspec.keyword.visitor.SpecificationElementVisitor;
import java.util.*;
import static tw.teddysoft.ezspec.keyword.Scenario.getEnclosingMethodInfo;
/**
* {@code Feature} is a class for representing Gherkin feature file.
*
* @author Teddy Chen
* @since 1.0
*/
public class Feature implements SpecificationElement {
public static final String KEYWORD = "Feature";
private final String name;
private final String description;
private final List rules;
private Rule defaultRule;
public Background newBackground() {
defaultRule.newBackground(Scenario.getEnclosingMethodName());
return defaultRule.getBackground();
}
public Background newBackground(String name) {
defaultRule.newBackground(name);
return defaultRule.getBackground();
}
public Optional getRule(String ruleName){
Objects.requireNonNull(ruleName);
return rules.stream().filter( x-> x.getName().equals(ruleName)).findAny();
}
public void applyRule(String ruleName, Scenario scenario){
var optRule = getRule(ruleName);
if (optRule.isPresent()){
defaultRule.removeScenario(scenario);
optRule.get().addScenario(scenario);
}
else
throw new IllegalArgumentException("Rule not found: " + ruleName);
}
public void initialize() {
rules.clear();
newDefaultRule();
}
/**
* A static factory to create a feature.
*
* @param name the name of feature
* @return a new feature instance
*/
public static Feature New(String name) {
Objects.requireNonNull(name, "name");
return new Feature(name);
}
/**
* A static factory to create a feature.
*
* @param name the name of feature
* @param description the description of feature
* @return a new feature instance
*/
public static Feature New(String name, String description) {
Objects.requireNonNull(name, "name");
Objects.requireNonNull(description, "description");
return new Feature(name, description);
}
private Feature(String name) {
this(name, "");
}
/**
* Instantiates a new Feature.
*
* @param name the name
* @param description the description
*/
private Feature(String name, String description) {
this.name = name;
this.description = description;
rules = new ArrayList<>();
newDefaultRule();
}
/**
* Gets rules.
*
* @return the rules
*/
public List getRules() {
return Collections.unmodifiableList(rules);
}
/**
* Gets name.
*
* @return the name
*/
public String getName() {
return name;
}
/**
* Gets description.
*
* @return the description
*/
public String getDescription() {
return description;
}
/**
* Create a new default rule in the feature. A default rule can only be
* created when there is no any rule in the list {@code rules}. If there
* is a default rule exist, it will be replaced by the new default rule.
*
* @return the rule
*/
private Rule newDefaultRule() {
defaultRule = new Rule("", this);
return defaultRule;
}
public Scenario newScenario() {
var methodInfo = getEnclosingMethodInfo();
return newScenarioWithRule(methodInfo.cookedMethodName(), methodInfo.ruleName());
}
public Scenario newScenario(String scenarioName) {
return newScenarioWithRule(scenarioName, getEnclosingMethodInfo().ruleName());
}
private Scenario newScenarioWithRule(String scenarioName, String ruleName){
Objects.requireNonNull(scenarioName);
Objects.requireNonNull(ruleName);
var scenario = defaultRule.newScenario(scenarioName);
if (!ruleName.isEmpty())
scenario.withRule(ruleName);
return scenario;
}
public ScenarioOutline newScenarioOutline() {
var methodInfo = getEnclosingMethodInfo();
return newScenarioOutlineWithRule(methodInfo.cookedMethodName(), "", methodInfo.ruleName());
}
public ScenarioOutline newScenarioOutline(String name) {
return newScenarioOutlineWithRule(name, "", getEnclosingMethodInfo().ruleName());
}
public ScenarioOutline newScenarioOutline(String name, String description) {
return newScenarioOutlineWithRule(name, description, getEnclosingMethodInfo().ruleName());
}
private ScenarioOutline newScenarioOutlineWithRule(String scenarioOutlineName, String description, String ruleName){
Objects.requireNonNull(scenarioOutlineName);
Objects.requireNonNull(description);
Objects.requireNonNull(ruleName);
var scenarioOutline = defaultRule.newScenarioOutline(scenarioOutlineName, description);
if (!ruleName.isEmpty())
scenarioOutline.withRule(ruleName);
return scenarioOutline;
}
/**
* Gets default rule.
*
* @return the default rule
*/
public Rule getDefaultRule() {
return defaultRule;
}
/**
* Clear rule.
*/
public void clearRule() {
rules.clear();
}
@Override
public void accept(SpecificationElementVisitor visitor) {
visitor.visit(this);
defaultRule.accept(visitor);
rules.forEach(rule -> {
rule.accept(visitor);
});
}
/**
* Feature text string including feature name and feature description.
*
* @return the string
*/
public String featureText() {
StringBuilder sb = new StringBuilder();
sb.append(KEYWORD).append(": ").append(name);
if (!description.isEmpty())
sb.append("\n\n").append(description);
return sb.toString();
}
/**
* The text string including feature name, feature description and
* contents of all rules.
*
* @return the string
*/
@Override
public String toString() {
StringBuilder sb = new StringBuilder();
sb.append(featureText());
sb.append("\n\n");
sb.append(rulesText());
return sb.toString();
}
private String rulesText() {
StringBuilder sb = new StringBuilder();
sb.append(defaultRule.toString()).append("\n");
for (var each : rules) {
sb.append(each.toString()).append("\n");
}
return sb.toString();
}
/**
* Add a rule to the feature
*
* @since 1.0.6
*/
public Rule NewRule(String ruleName) {
Objects.requireNonNull(ruleName);
return NewRule(ruleName, "");
}
/**
* Add a rule to the feature
*
* @since 1.0.6
*/
public Rule NewRule(String ruleName, String description) {
Objects.requireNonNull(ruleName);
if (rules.stream().anyMatch( x-> x.getName().equals(ruleName)))
throw new IllegalArgumentException("Rule name cannot be duplicated: " + ruleName);
Rule rule = new Rule(ruleName, description, this);
rules.add(rule);
return rule;
}
}
© 2015 - 2025 Weber Informatics LLC | Privacy Policy