package de.asideas.crowdsource.testsupport.cucumber; import cucumber.api.java.Before; import cucumber.api.java.en.And; import cucumber.api.java.en.Then; import cucumber.api.java.en.When; import de.asideas.crowdsource.presentation.FinancingRound; import de.asideas.crowdsource.presentation.Pledge; import de.asideas.crowdsource.testsupport.CrowdSourceTestConfig; import de.asideas.crowdsource.testsupport.pageobjects.project.ProjectPledgingForm; import de.asideas.crowdsource.testsupport.selenium.SeleniumWait; import de.asideas.crowdsource.testsupport.selenium.WebDriverProvider; import de.asideas.crowdsource.testsupport.util.CrowdSourceClient; import org.joda.time.DateTime; import org.joda.time.Duration; import org.openqa.selenium.remote.RemoteWebDriver; import org.openqa.selenium.support.PageFactory; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.test.context.ContextConfiguration; import static org.hamcrest.MatcherAssert.assertThat; import static org.hamcrest.Matchers.greaterThan; import static org.hamcrest.Matchers.is; import static org.hamcrest.Matchers.lessThan; @ContextConfiguration(classes = CrowdSourceTestConfig.class) public class ProjectPledgingSteps { public static final int ROUND_BUDGET = 100000; @Autowired private WebDriverProvider webDriverProvider; @Autowired private ProjectPledgingForm pledgingForm; @Autowired private CrowdSourceClient crowdSourceClient; @Autowired private ProjectDetailSteps projectDetailSteps; @Autowired private SeleniumWait wait; private RemoteWebDriver webDriver; private int budgetBeforeChange; private int pledgedAmountBeforeChange; private int pledgeAmount; @Before public void init() { webDriver = webDriverProvider.provideDriver(); } @Then("^the notification message \"([^\"]*)\" is displayed on the project pledging form$") public void the_notification_message_is_displayed_on_the_project_pledging_form(String expectedNotification) { PageFactory.initElements(webDriver, pledgingForm); pledgingForm.waitUntilANotificationOrEerrorMessageIsDisplayed(); assertThat(pledgingForm.getNotificationMessage(), is(expectedNotification)); } @Then("^the error message \"([^\"]*)\" is displayed on the project pledging form$") public void the_error_message_is_displayed_on_the_project_pledging_form(String expectedErrorMessage) throws Throwable { PageFactory.initElements(webDriver, pledgingForm); assertThat(pledgingForm.getErrorMessage(), is(expectedErrorMessage)); } @And("^the project pledging form is (enabled|disabled)$") public void the_project_pledging_form_is_disabled(String enabledString) throws Throwable { boolean enabled = "enabled".equals(enabledString); assertThat(pledgingForm.isSliderEnabled(), is(enabled)); assertThat(pledgingForm.getAmountInputField().isEnabled(), is(enabled)); } @And("^the user budget (\\d+) is displayed$") public void the_user_budget_is_displayed(int budget) throws Throwable { assertThat(pledgingForm.getUserBudget(), is(budget)); } @Then("^there is no notification message$") public void there_is_no_notification_message() throws Throwable { PageFactory.initElements(webDriver, pledgingForm); assertThat(pledgingForm.getNotificationMessage(), is("")); } @When("^the user raises his desired pledge amount via the slider$") public void the_user_raises_desired_pledge_amount_via_the_slider() throws Throwable { PageFactory.initElements(webDriver, pledgingForm); keepAmountsBeforeChange(); int amountBeforeChange = pledgingForm.getAmountFromInputField(); pledgingForm.moveSliderBy(500); //pixels // Timing issue; After setting the slider it takes some millis until the input field is updated wait.until(d -> pledgingForm.getAmountFromInputField() > 0); int amountFromInputField = pledgingForm.getAmountFromInputField(); assertThat(amountBeforeChange, is(lessThan(amountFromInputField))); pledgeAmount = amountFromInputField; } @When("^the user reduces his desired pledge amount via the slider$") public void the_user_reduces_desired_pledge_amount_via_the_slider() throws Throwable { PageFactory.initElements(webDriver, pledgingForm); keepAmountsBeforeChange(); final int amountBeforeChange = pledgingForm.getAmountFromInputField(); pledgingForm.moveSliderBy(-50); //pixels pledgingForm.moveSliderBy(-40); //pixels wait.until(d -> { PageFactory.initElements(webDriver, pledgingForm); return amountBeforeChange > pledgingForm.getAmountFromInputField(); }, 10, 800); assertThat(amountBeforeChange, is(greaterThan(pledgingForm.getAmountFromInputField()))); pledgeAmount = pledgingForm.getAmountFromInputField() - amountBeforeChange; } @When("^the user sets his desired pledge amount as high as the remaining amount of the project goal$") public void the_user_sets_his_desired_pledge_amount_as_high_as_the_remaining_amount_of_the_project_goal() throws Throwable { PageFactory.initElements(webDriver, pledgingForm); keepAmountsBeforeChange(); pledgeAmount = pledgingForm.getPledgeGoalAmount() - pledgedAmountBeforeChange; if (pledgeAmount > budgetBeforeChange) { // if this happens, then the financing round was started with a too low budget throw new IllegalStateException("User budget (" + budgetBeforeChange + ") is too low to fully pledge the project"); } pledgingForm.setAmountInputValue(pledgeAmount); } @When("^the user enters (\\d+) as his desired pledge amount$") public void the_user_enters_as_his_desired_pledge_amount(int pledgeAmount) throws Throwable { keepAmountsBeforeChange(); PageFactory.initElements(webDriver, pledgingForm); pledgingForm.setAmountInputValue(pledgeAmount); this.pledgeAmount = pledgingForm.getPledgedAmount() - pledgedAmountBeforeChange; } @Then("^the displayed budget and financing infos are updated$") public void the_displayed_budget_and_financing_infos_are_updated() throws Throwable { final int expectedUsrBudget = budgetBeforeChange - pledgeAmount; assertThat(pledgingForm.getUserBudget(), is(expectedUsrBudget)); assertThat(pledgingForm.getPledgedAmount(), is(pledgedAmountBeforeChange + pledgeAmount)); } @When("^the user submits the pledging form$") public void the_user_submits_the_pledging_form() throws Throwable { pledgingForm.submitForm(); pledgingForm.waitUntilANotificationOrEerrorMessageIsDisplayed(); } @And("^there is (a|no) financing round active$") public void there_is_a_financing_round_active(String active) throws Throwable { boolean requireActiveFinancingRound = "a".equals(active); prepareFinancingRound(requireActiveFinancingRound); } @And("^we wait a second for the round to be post processed$") public void we_wait_a_second_for_the_round_to_be_post_processed(){ long start = System.currentTimeMillis(); wait.until(d -> System.currentTimeMillis() - start >= 2000); } @And("^there is (a|no) financing round active with a budget of (\\d+)$") public void there_is_a_financing_round_active(String active, int budget) throws Throwable { boolean requireActiveFinancingRound = "a".equals(active); prepareFinancingRound(requireActiveFinancingRound, Duration.standardHours(2).toStandardSeconds().getSeconds(), budget); } @And("^there is (a|no) financing round active for (\\d+) seconds$") public void there_is_a_financing_round_active_for_x_seconds(String active, int seconds) throws Throwable { boolean requireActiveFinancingRound = "a".equals(active); prepareFinancingRound(requireActiveFinancingRound, seconds); } @And("^the user waits for the end of the financing round$") public void the_user_waits_for_the_end_of_the_financing_round() throws Throwable { wait.until(d -> crowdSourceClient.getActiveFinanceRound() == null, 15, 1000); } @When("^a financing round is being activated in the meantime$") public void a_financing_round_is_being_activated_in_the_meantime() throws Throwable { prepareFinancingRound(true); } @When("^a financing round is being deactivated in the meantime$") public void a_financing_round_is_being_deactivated_in_the_meantime() throws Throwable { prepareFinancingRound(false); } @And("^another user pledges the same project with (\\d+) in the meantime$") public void another_user_pledges_the_project_with_in_the_meantime(int pledgeAmount) throws Throwable { pledgeProjectViaApi(pledgeAmount, true); } @And("^the project is pledged with and amount of (\\d+)$") public void the_project_is_pledged_with_and_amount_of(int amount) throws Throwable { the_user_enters_as_his_desired_pledge_amount(amount); the_user_submits_the_pledging_form(); the_notification_message_is_displayed_on_the_project_pledging_form("Deine Finanzierung war erfolgreich."); } private void prepareFinancingRound(boolean requireActiveFinancingRound) { prepareFinancingRound(requireActiveFinancingRound, 5 * 60 * 60 * 24); } private void prepareFinancingRound(boolean requireActiveFinancingRound, int activeForSeconds) { prepareFinancingRound(requireActiveFinancingRound, activeForSeconds, ROUND_BUDGET); } private void prepareFinancingRound(boolean requireActiveFinancingRound, int activeForSeconds, int budget) { CrowdSourceClient.AuthToken authToken = crowdSourceClient.authorizeWithAdminUser(); FinancingRound activeFinanceRound = crowdSourceClient.getActiveFinanceRound(); if (activeFinanceRound != null) { crowdSourceClient.stopFinancingRound(activeFinanceRound.getId(), authToken); } if (requireActiveFinancingRound) { FinancingRound financingRound = new FinancingRound(); financingRound.setEndDate(DateTime.now().plusSeconds(activeForSeconds)); financingRound.setBudget(budget); crowdSourceClient.startFinancingRound(financingRound, authToken); } } private void pledgeProjectViaApi(int pledgeAmount, boolean asAdmin) { CrowdSourceClient.AuthToken authToken = asAdmin ? crowdSourceClient.authorizeWithAdminUser() : crowdSourceClient.authorizeWithDefaultUser(); Pledge pledge = new Pledge(pledgeAmount); crowdSourceClient.pledgeProject(projectDetailSteps.getCreatedProject(), pledge, authToken); } private void keepAmountsBeforeChange() { budgetBeforeChange = pledgingForm.getUserBudget(); pledgedAmountBeforeChange = pledgingForm.getPledgedAmount(); } }