package org.jbehave.core.steps;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import org.jbehave.core.annotations.Composite;
import org.jbehave.core.annotations.Given;
import org.jbehave.core.annotations.Named;
import org.jbehave.core.annotations.Then;
import org.jbehave.core.annotations.When;
import org.junit.Ignore;
import org.junit.Test;
import com.thoughtworks.paranamer.BytecodeReadingParanamer;
import static org.hamcrest.MatcherAssert.assertThat;
import static org.hamcrest.Matchers.equalTo;
import static org.hamcrest.Matchers.is;
import static org.jbehave.core.steps.StepCandidateBehaviour.candidateMatchingStep;
import static org.junit.Assert.assertNotNull;
import static org.junit.Assert.assertTrue;
public class CompositeStepCandidateBehaviour {
@Test
public void shouldMatchCompositeStepsAndCreateComposedStepsUsingMatchedParameters() {
CompositeSteps steps = new CompositeSteps();
List<StepCandidate> candidates = steps.listCandidates();
StepCandidate candidate = candidateMatchingStep(candidates, "Given $customer has previously bought a $product");
assertThat(candidate.isComposite(), is(true));
Map<String, String> noNamedParameters = new HashMap<String, String>();
List<Step> composedSteps = new ArrayList<Step>();
candidate.addComposedSteps(composedSteps, "Given Mr Jones has previously bought a ticket", noNamedParameters, candidates);
assertThat(composedSteps.size(), equalTo(2));
for (Step step : composedSteps) {
step.perform(null);
}
assertThat(steps.loggedIn, equalTo("Mr Jones"));
assertThat(steps.added, equalTo("ticket"));
}
static class CompositeSteps extends Steps {
private String loggedIn;
private String added;
@Given("$customer has previously bought a $product")
@Composite(steps = { "Given <customer> is logged in",
"When a <product> is added to the cart" })
public void aCompositeStep(@Named("customer") String customer, @Named("product") String product) {
}
@Given("<customer> is logged in")
public void aCustomerIsLoggedIn(@Named("customer") String customer) {
loggedIn = customer;
}
@When("a <product> is added to the cart")
public void aProductIsAddedToCart(@Named("product") String product) {
added = product;
}
}
@Test
public void shouldMatchCompositeStepsAndCreateComposedStepsUsingNamedParameters() {
CompositeStepsUsingNamedParameters steps = new CompositeStepsUsingNamedParameters();
List<StepCandidate> candidates = steps.listCandidates();
StepCandidate candidate = candidateMatchingStep(candidates, "Given <customer> has previously bough a <product>");
assertThat(candidate.isComposite(), is(true));
Map<String, String> namedParameters = new HashMap<String, String>();
namedParameters.put("customer", "Mr Jones");
namedParameters.put("product", "ticket");
List<Step> composedSteps = new ArrayList<Step>();
candidate.addComposedSteps(composedSteps, "Given <customer> has previously bought a <product>", namedParameters, candidates);
assertThat(composedSteps.size(), equalTo(2));
for (Step step : composedSteps) {
step.perform(null);
}
assertThat(steps.loggedIn, equalTo("Mr Jones"));
assertThat(steps.added, equalTo("ticket"));
}
static class CompositeStepsUsingNamedParameters extends Steps {
private String loggedIn;
private String added;
@Given("<customer> has previously bough a <product>")
@Composite(steps = { "Given <customer> is logged in",
"When a <product> is added to the cart" })
public void aCompositeStep(@Named("customer") String customer, @Named("product") String product) {
}
@Given("<customer> is logged in")
public void aCustomerIsLoggedIn(@Named("customer") String customer) {
loggedIn = customer;
}
@When("a <product> is added to the cart")
public void aProductIsAddedToCart(@Named("product") String product) {
added = product;
}
}
@Test
@Ignore("fails as perhaps Paranamer not peer of @named in respect of @composite")
public void shouldMatchCompositeStepsAndCreateComposedStepsUsingParanamerNamedParameters() {
CompositeStepsWithoutNamedAnnotation steps = new CompositeStepsWithoutNamedAnnotation();
List<StepCandidate> candidates = steps.listCandidates();
StepCandidate candidate = candidates.get(0);
candidate.useParanamer(new BytecodeReadingParanamer());
assertThat(candidate.isComposite(), is(true));
Map<String, String> namedParameters = new HashMap<String, String>();
namedParameters.put("customer", "Mr Jones");
namedParameters.put("product", "ticket");
List<Step> composedSteps = new ArrayList<Step>();
candidate.addComposedSteps(composedSteps, "Given <customer> has previously bought a <product>", namedParameters, candidates);
assertThat(composedSteps.size(), equalTo(2));
for (Step step : composedSteps) {
step.perform(null);
}
assertThat(steps.loggedIn, equalTo("Mr Jones"));
assertThat(steps.added, equalTo("ticket"));
}
static class CompositeStepsWithoutNamedAnnotation extends Steps {
private String loggedIn;
private String added;
@Given("<customer> has previously bough a <product>")
@Composite(steps = {"Given <customer> is logged in",
"When a <product> is added to the cart"})
public void aCompositeStep(String customer, String product) {
}
@Given("<customer> is logged in")
public void aCustomerIsLoggedIn(String customer) {
loggedIn = customer;
}
@When("a <product> is added to the cart")
public void aProductIsAddedToCart(String product) {
added = product;
}
}
@Test
public void shouldMatchCompositeStepsAndCreateComposedNestedSteps() {
CompositeNestedSteps steps = new CompositeNestedSteps();
List<StepCandidate> candidates = steps.listCandidates();
// find main step
StepCandidate candidate = null;
for(StepCandidate cand: candidates) {
if(cand.getPatternAsString().equals("all buttons are enabled")) {
candidate = cand;
break;
}
}
assertNotNull(candidate);
assertThat(candidate.isComposite(), is(true));
Map<String, String> noNamedParameters = new HashMap<String, String>();
List<Step> composedSteps = new ArrayList<Step>();
candidate.addComposedSteps(composedSteps, "Then all buttons are enabled", noNamedParameters, candidates);
assertThat(composedSteps.size(), equalTo(6));
for (Step step : composedSteps) {
step.perform(null);
}
assertThat(steps.trail.toString(), equalTo("l>l1>l2>t>t1>t2>"));
}
static class CompositeNestedSteps extends Steps {
private StringBuffer trail = new StringBuffer();
@Then("all buttons are enabled")
@Composite(steps = {
"Then all left buttons are enabled",
"Then all top buttons are enabled" }
)
public void all() {
trail.append("a>");
}
@Then("all left buttons are enabled")
@Composite(steps = {
"Then first left button is enabled",
"Then second left button is enabled" }
)
public void leftAll() {
trail.append("l>");
}
@Then("first left button is enabled")
public void leftOne(){
trail.append("l1>");
}
@Then("second left button is enabled")
public void leftTwo(){
trail.append("l2>");
}
@Then("all top buttons are enabled")
@Composite(steps = {
"Then first top button is enabled",
"Then second top button is enabled" }
)
public void topAll() {
trail.append("t>");
}
@Then("first top button is enabled")
public void topOne() {
trail.append("t1>");
}
@Then("second top button is enabled")
public void topTwo() {
trail.append("t2>");
}
}
@Test
public void shouldMatchCompositeStepsWhenStepParameterIsProvided(){
CompositeStepsParameterMatching steps = new CompositeStepsParameterMatching();
List<StepCandidate> candidates = steps.listCandidates();
StepCandidate candidate = candidateMatchingStep(candidates, "When I login");
assertThat(candidate.isComposite(), is(true));
Map<String, String> noNamedParameters = new HashMap<String, String>();
List<Step> composedSteps = new ArrayList<Step>();
candidate.addComposedSteps(composedSteps, "When I login", noNamedParameters, candidates);
assertThat(composedSteps.size(), equalTo(1));
for (Step step : composedSteps) {
step.perform(null);
}
assertThat(steps.button, equalTo("Login"));
}
static class CompositeStepsParameterMatching extends Steps {
private String button;
@When("I login")
@Composite(steps={"When I click the Login button"})
public void whenILogin(){}
@When("I click the $button button")
public void whenIClickTheButton(@Named("button") String button){
this.button = button;
}
}
@Test
public void recursiveCompositeStepsShouldWorkWithSomeMissingParameters(){
String userName = "someUserName";
CompositeStepParametersWithMissingParameters steps = new CompositeStepParametersWithMissingParameters();
List<StepCandidate> candidates = steps.listCandidates();
StepCandidate candidate = candidateMatchingStep(candidates, "Given I am logged in as " + userName);
assertThat(candidate.isComposite(), is(true));
Map<String, String> noNamedParameters = new HashMap<String, String>();
List<Step> composedSteps = new ArrayList<Step>();
candidate.addComposedSteps(composedSteps, "Given I am logged in as someUserName", noNamedParameters, candidates);
for (Step step : composedSteps) {
step.perform(null);
}
assertThat("Was unable to set the username", steps.username, equalTo(userName));
assertTrue("Didn't reach the login step", steps.isLoggedIn);
}
static class CompositeStepParametersWithMissingParameters extends Steps {
private String username;
private boolean isLoggedIn;
@Given("I am logged in as $name")
@Composite(steps = {
"Given my user name is <name>",
"Given I log in"
})
public void logInAsUser(@Named("name")String name){}
@Given("my user name is $name")
public void setUsername(@Named("name")String name){
this.username = name;
}
@Given("I log in")
@Composite(steps = {
"Given I am on the Login page",
"When I type my user name into the Username field",
"When I type my password into the Password field",
"When I click the Login button"} )
public void logIn(){
this.isLoggedIn = true;
}
@Given("Given I am on the Login page")
public void onLoginPage(){}
@Given("When I type my user name into the Username field")
public void typeUsername(){}
@Given("When I type my password into the Password field")
public void typePassword(){}
@Given("When I click the Login button")
public void clickLogin(){}
}
}