BAEL-4783 rename module and fix indents
This commit is contained in:
+9
@@ -0,0 +1,9 @@
|
||||
package com.baeldung.cucumber_tags.acceptance;
|
||||
|
||||
|
||||
import io.cucumber.junit.platform.engine.Cucumber;
|
||||
|
||||
@Cucumber()
|
||||
public class AcceptanceTestRunnerIT {
|
||||
|
||||
}
|
||||
+37
@@ -0,0 +1,37 @@
|
||||
package com.baeldung.cucumber_tags.acceptance.api.steps;
|
||||
|
||||
|
||||
import com.baeldung.cucumber_tags.acceptance.commonutil.ScenarioContextApi;
|
||||
import io.cucumber.java.en.Then;
|
||||
import io.cucumber.java.en.When;
|
||||
import org.hamcrest.Matchers;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
|
||||
public class HealthSteps {
|
||||
|
||||
@Autowired
|
||||
private ScenarioContextApi context;
|
||||
|
||||
|
||||
@When("^I make a GET call on ([^\"]*)$")
|
||||
public void iMakeAGETCallOn(String path) {
|
||||
context.invokeHttpGet(path);
|
||||
}
|
||||
|
||||
@When("^I make a POST call on ([^\"]*)$")
|
||||
public void iMakeAPOSTCallOn(String path) {
|
||||
context.invokeHttpPost(path, context.postBody);
|
||||
}
|
||||
|
||||
@Then("^I should receive (\\d+) response status code$")
|
||||
public void iShouldReceiveStatusCodeResponse(int code) {
|
||||
context.response.then().statusCode(code);
|
||||
}
|
||||
|
||||
@Then("^should receive a non-empty body$")
|
||||
public void shouldReceiveANonEmptyBody() {
|
||||
context.response.then().body(Matchers.notNullValue());
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
+44
@@ -0,0 +1,44 @@
|
||||
package com.baeldung.cucumber_tags.acceptance.commonutil;
|
||||
|
||||
import org.openqa.selenium.InvalidArgumentException;
|
||||
|
||||
import java.net.MalformedURLException;
|
||||
import java.net.URL;
|
||||
import java.util.Optional;
|
||||
|
||||
public final class CucumberEnvironment {
|
||||
|
||||
private static final String SELENIUM_GRID_URL_ENV_VAR = "SELENIUM_GRID_URL";
|
||||
private static final String SERVICE_HOSTNAME = "SERVICE_HOSTNAME";
|
||||
private static final String LOCALHOST = "localhost";
|
||||
|
||||
private CucumberEnvironment() {
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the network host where the service is running. When running while developing, this is going to be
|
||||
* localhost because webdriver and the test runner are going to be on the same machine. On gitlab-ci /
|
||||
* docker-compose though, they are going to be on separate hosts so webdriver needs to hit the
|
||||
* machine where the test runner is starting the service, not localhost.
|
||||
*/
|
||||
public static String getServiceHost() {
|
||||
final Optional<String> serviceHostname = Optional.ofNullable(System.getenv(SERVICE_HOSTNAME));
|
||||
return serviceHostname.orElse(LOCALHOST);
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the url where the selenium grid instance is. This is used for gitlab-ci / docker-compose setups.
|
||||
*/
|
||||
public static Optional<URL> getSeleniumGridUrl() {
|
||||
final Optional<String> seleniumGridUrlString = Optional.ofNullable(System.getenv(SELENIUM_GRID_URL_ENV_VAR));
|
||||
return seleniumGridUrlString.map(CucumberEnvironment::parseSeleniumGridUrl);
|
||||
}
|
||||
|
||||
private static URL parseSeleniumGridUrl(String seleniumGridUrlString) {
|
||||
try {
|
||||
return new URL(seleniumGridUrlString);
|
||||
} catch (MalformedURLException e) {
|
||||
throw new InvalidArgumentException(SELENIUM_GRID_URL_ENV_VAR + "env var is not a valid URL");
|
||||
}
|
||||
}
|
||||
}
|
||||
+57
@@ -0,0 +1,57 @@
|
||||
package com.baeldung.cucumber_tags.acceptance.commonutil;
|
||||
|
||||
import io.restassured.http.ContentType;
|
||||
import io.restassured.module.mockmvc.response.MockMvcResponse;
|
||||
import io.restassured.module.mockmvc.specification.MockMvcRequestSpecification;
|
||||
import org.springframework.boot.web.server.LocalServerPort;
|
||||
import org.springframework.context.annotation.Scope;
|
||||
import org.springframework.stereotype.Component;
|
||||
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
|
||||
import static io.restassured.module.mockmvc.RestAssuredMockMvc.given;
|
||||
|
||||
@Component
|
||||
@Scope(scopeName = "cucumber-glue")
|
||||
public class ScenarioContextApi {
|
||||
|
||||
@LocalServerPort
|
||||
int port;
|
||||
|
||||
private ScenarioReport report;
|
||||
public MockMvcRequestSpecification request;
|
||||
public MockMvcResponse response;
|
||||
public Map<String, Object> postBody = new HashMap<>();
|
||||
public Map<String, Object> queryParams = new HashMap<>();
|
||||
|
||||
public ScenarioContextApi() {
|
||||
reset();
|
||||
}
|
||||
|
||||
private void reset() {
|
||||
report = new ScenarioReport();
|
||||
request = null;
|
||||
response = null;
|
||||
postBody.clear();
|
||||
queryParams.clear();
|
||||
}
|
||||
|
||||
public void invokeHttpGet(String path, Object... pathParams) {
|
||||
request = given().log().all();
|
||||
response = request.when().get(path, pathParams);
|
||||
response.then().log().all();
|
||||
}
|
||||
|
||||
public void invokeHttpPost(String path, Map<String, ?> data) {
|
||||
request = given().log().all().body(data).queryParams(queryParams).contentType(ContentType.JSON);
|
||||
response = request.post(path);
|
||||
response.then().log().all();
|
||||
}
|
||||
|
||||
|
||||
public ScenarioReport getReport() {
|
||||
return report;
|
||||
}
|
||||
|
||||
}
|
||||
+77
@@ -0,0 +1,77 @@
|
||||
package com.baeldung.cucumber_tags.acceptance.commonutil;
|
||||
|
||||
import org.openqa.selenium.WebDriver;
|
||||
import org.openqa.selenium.chrome.ChromeDriver;
|
||||
import org.openqa.selenium.remote.DesiredCapabilities;
|
||||
import org.openqa.selenium.remote.RemoteWebDriver;
|
||||
import org.springframework.boot.web.server.LocalServerPort;
|
||||
import org.springframework.context.annotation.Scope;
|
||||
import org.springframework.stereotype.Component;
|
||||
|
||||
import java.net.URL;
|
||||
|
||||
import static io.github.bonigarcia.wdm.WebDriverManager.getInstance;
|
||||
import static io.github.bonigarcia.wdm.config.DriverManagerType.CHROME;
|
||||
|
||||
@Component
|
||||
@Scope(scopeName = "cucumber-glue")
|
||||
public class ScenarioContextUI {
|
||||
|
||||
protected static final String RANDOM_NUMBER_URL = "/random-number-generator";
|
||||
|
||||
@LocalServerPort
|
||||
int port;
|
||||
private WebDriver driver;
|
||||
private ScenarioReport report;
|
||||
|
||||
public ScenarioContextUI() {
|
||||
reset();
|
||||
}
|
||||
|
||||
private void reset() {
|
||||
report = new ScenarioReport();
|
||||
driver = null;
|
||||
}
|
||||
|
||||
private static WebDriver getRemoteWebDriver(URL url) {
|
||||
return new RemoteWebDriver(url, DesiredCapabilities.chrome());
|
||||
}
|
||||
|
||||
private static WebDriver getLocalChromeDriver() {
|
||||
getInstance(CHROME).setup();
|
||||
return new ChromeDriver();
|
||||
}
|
||||
|
||||
public ScenarioReport getReport() {
|
||||
return report;
|
||||
}
|
||||
|
||||
public String getRandomNumberUrl() {
|
||||
return "http://" + getServiceBaseUrl() + RANDOM_NUMBER_URL;
|
||||
}
|
||||
|
||||
private String getServiceBaseUrl() {
|
||||
return CucumberEnvironment.getServiceHost() + ":" + Integer.toString(port);
|
||||
}
|
||||
|
||||
/**
|
||||
* If we are running inside docker (mostly for gitlab ci purposes), we expect a selenium grid setup.
|
||||
* If that environment variable isn't set, we assume we're in "dev mode" and ChromeDriverManager will
|
||||
* provide the local instance of chromedriver (no need to have chromedriver installed).
|
||||
*/
|
||||
public WebDriver getWebDriver() {
|
||||
if (driver == null) {
|
||||
return getFreshWebdriver();
|
||||
} else {
|
||||
return driver;
|
||||
}
|
||||
}
|
||||
|
||||
private WebDriver getFreshWebdriver() {
|
||||
driver = CucumberEnvironment.getSeleniumGridUrl()
|
||||
.map(ScenarioContextUI::getRemoteWebDriver)
|
||||
.orElseGet(ScenarioContextUI::getLocalChromeDriver);
|
||||
return driver;
|
||||
}
|
||||
|
||||
}
|
||||
+58
@@ -0,0 +1,58 @@
|
||||
package com.baeldung.cucumber_tags.acceptance.commonutil;
|
||||
|
||||
|
||||
import io.cucumber.java.After;
|
||||
import io.cucumber.java.Before;
|
||||
import io.cucumber.java.Scenario;
|
||||
import io.cucumber.spring.CucumberContextConfiguration;
|
||||
import io.restassured.config.LogConfig;
|
||||
import io.restassured.module.mockmvc.RestAssuredMockMvc;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.boot.test.autoconfigure.web.servlet.AutoConfigureMockMvc;
|
||||
import org.springframework.boot.test.context.SpringBootTest;
|
||||
import org.springframework.test.context.ActiveProfiles;
|
||||
import org.springframework.test.web.servlet.MockMvc;
|
||||
|
||||
import java.io.IOException;
|
||||
|
||||
@SpringBootTest(webEnvironment = SpringBootTest.WebEnvironment.RANDOM_PORT)
|
||||
@ActiveProfiles(profiles = {"acceptance-test"})
|
||||
@AutoConfigureMockMvc
|
||||
@CucumberContextConfiguration
|
||||
public class ScenarioHooks {
|
||||
|
||||
@Autowired
|
||||
private ScenarioContextUI uiContext;
|
||||
|
||||
@Autowired
|
||||
private ScenarioContextApi apiContext;
|
||||
|
||||
@Autowired
|
||||
private MockMvc mvc;
|
||||
|
||||
@Before("@ui")
|
||||
public void setupForUI() {
|
||||
uiContext.getWebDriver();
|
||||
}
|
||||
|
||||
@After("@ui")
|
||||
public void tearDownForUi(Scenario scenario) throws IOException {
|
||||
uiContext.getReport().write(scenario);
|
||||
uiContext.getReport().captureScreenShot(scenario, uiContext.getWebDriver());
|
||||
uiContext.getWebDriver().quit();
|
||||
}
|
||||
|
||||
@Before("@api")
|
||||
public void setupForApi() {
|
||||
RestAssuredMockMvc.mockMvc(mvc);
|
||||
RestAssuredMockMvc.config = RestAssuredMockMvc.config()
|
||||
.logConfig(new LogConfig(
|
||||
apiContext.getReport().getRestLogPrintStream(),
|
||||
true));
|
||||
}
|
||||
|
||||
@After("@api")
|
||||
public void tearDownForApi(Scenario scenario) throws IOException {
|
||||
apiContext.getReport().write(scenario);
|
||||
}
|
||||
}
|
||||
+44
@@ -0,0 +1,44 @@
|
||||
package com.baeldung.cucumber_tags.acceptance.commonutil;
|
||||
|
||||
|
||||
import io.cucumber.java.Scenario;
|
||||
import org.openqa.selenium.OutputType;
|
||||
import org.openqa.selenium.TakesScreenshot;
|
||||
import org.openqa.selenium.WebDriver;
|
||||
|
||||
import java.io.ByteArrayOutputStream;
|
||||
import java.io.IOException;
|
||||
import java.io.PrintStream;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
public class ScenarioReport {
|
||||
|
||||
private List<String> messages = new ArrayList<>();
|
||||
private ByteArrayOutputStream restLogOutputStream = new ByteArrayOutputStream();
|
||||
|
||||
public void addMessage(String message) {
|
||||
messages.add(message);
|
||||
}
|
||||
|
||||
public PrintStream getRestLogPrintStream() {
|
||||
return new PrintStream(restLogOutputStream);
|
||||
}
|
||||
|
||||
public void write(Scenario scenario) throws IOException {
|
||||
for (String msg : messages) {
|
||||
scenario.log(msg);
|
||||
}
|
||||
scenario.log(restLogOutputStream.toString());
|
||||
restLogOutputStream.close();
|
||||
}
|
||||
|
||||
public void captureScreenShot(Scenario scenario, WebDriver driver) {
|
||||
try {
|
||||
final byte[] screenshot = ((TakesScreenshot) driver).getScreenshotAs(OutputType.BYTES);
|
||||
scenario.attach(screenshot, "image/png", "test");
|
||||
} catch (Exception exception) {
|
||||
scenario.log(exception.toString());
|
||||
}
|
||||
}
|
||||
}
|
||||
+28
@@ -0,0 +1,28 @@
|
||||
package com.baeldung.cucumber_tags.acceptance.ui.pages;
|
||||
|
||||
import org.openqa.selenium.WebDriver;
|
||||
import org.openqa.selenium.support.ui.WebDriverWait;
|
||||
|
||||
import static com.google.common.base.Preconditions.checkNotNull;
|
||||
import static org.openqa.selenium.support.ui.ExpectedConditions.titleIs;
|
||||
|
||||
public class Page {
|
||||
private static final long DEFAULT_WAIT_SECONDS = 5;
|
||||
private static Page currentPage;
|
||||
final WebDriver driver;
|
||||
|
||||
Page(WebDriver driver, String title) {
|
||||
currentPage = this;
|
||||
this.driver = driver;
|
||||
getWait().until(titleIs(title));
|
||||
}
|
||||
|
||||
public static <T extends Page> T getPage(Class<T> pageClass) {
|
||||
return pageClass.cast(checkNotNull(currentPage));
|
||||
}
|
||||
|
||||
WebDriverWait getWait() {
|
||||
return new WebDriverWait(driver, DEFAULT_WAIT_SECONDS);
|
||||
}
|
||||
|
||||
}
|
||||
+41
@@ -0,0 +1,41 @@
|
||||
package com.baeldung.cucumber_tags.acceptance.ui.pages;
|
||||
|
||||
import org.openqa.selenium.WebDriver;
|
||||
import org.openqa.selenium.WebElement;
|
||||
import org.openqa.selenium.support.FindBy;
|
||||
|
||||
public class RandomNumberGeneratorPage extends Page {
|
||||
|
||||
@FindBy(id = "min")
|
||||
private WebElement minField;
|
||||
|
||||
@FindBy(id = "max")
|
||||
private WebElement maxField;
|
||||
|
||||
@FindBy(id = "generate")
|
||||
private WebElement generateButton;
|
||||
|
||||
@FindBy(id = "result")
|
||||
private WebElement result;
|
||||
|
||||
public RandomNumberGeneratorPage(WebDriver driver) {
|
||||
super(driver, "Random Number Generator");
|
||||
}
|
||||
|
||||
public void enterMinField(String min) {
|
||||
minField.sendKeys(min);
|
||||
}
|
||||
|
||||
public void enterMaxField(String max) {
|
||||
maxField.sendKeys(max);
|
||||
}
|
||||
|
||||
public void pressGenerateButton() {
|
||||
generateButton.click();
|
||||
}
|
||||
|
||||
public String getResult() {
|
||||
return result.getText();
|
||||
}
|
||||
}
|
||||
|
||||
+49
@@ -0,0 +1,49 @@
|
||||
package com.baeldung.cucumber_tags.acceptance.ui.steps;
|
||||
|
||||
import com.baeldung.cucumber_tags.acceptance.commonutil.ScenarioContextUI;
|
||||
import com.baeldung.cucumber_tags.acceptance.ui.pages.RandomNumberGeneratorPage;
|
||||
import io.cucumber.java.en.And;
|
||||
import io.cucumber.java.en.Given;
|
||||
import io.cucumber.java.en.Then;
|
||||
import io.cucumber.java.en.When;
|
||||
import org.openqa.selenium.support.PageFactory;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
|
||||
import static com.baeldung.cucumber_tags.acceptance.ui.pages.Page.getPage;
|
||||
import static org.junit.Assert.assertTrue;
|
||||
|
||||
public class RandomNumberGeneratorSteps {
|
||||
|
||||
@Autowired
|
||||
private ScenarioContextUI context;
|
||||
|
||||
@Given("we are expecting a random number between min and max")
|
||||
public void expectingRandomNumberBetweenMinAndMax() {
|
||||
}
|
||||
|
||||
@And("I am on random-number-generator page")
|
||||
public void iAmOnRandomNumberGeneratorPage() {
|
||||
context.getWebDriver().get(context.getRandomNumberUrl());
|
||||
PageFactory.initElements(context.getWebDriver(), RandomNumberGeneratorPage.class);
|
||||
}
|
||||
|
||||
@When("^I enter min ([^\"]*)$")
|
||||
public void whenIenterMin(String min) {
|
||||
getPage(RandomNumberGeneratorPage.class).enterMinField(min);
|
||||
}
|
||||
|
||||
@When("^I enter max ([^\"]*)$")
|
||||
public void whenIenterMax(String max) {
|
||||
getPage(RandomNumberGeneratorPage.class).enterMaxField(max);
|
||||
}
|
||||
|
||||
@And("^I press Generate button")
|
||||
public void pressScanButton() {
|
||||
getPage(RandomNumberGeneratorPage.class).pressGenerateButton();
|
||||
}
|
||||
|
||||
@Then("I should receive a random number between {int} and {int}")
|
||||
public void iShouldReceiveARandomNumberBetweenAnd(int min, int max) {
|
||||
assertTrue(Integer.parseInt(getPage(RandomNumberGeneratorPage.class).getResult()) >= min && Integer.parseInt(getPage(RandomNumberGeneratorPage.class).getResult()) <= max);
|
||||
}
|
||||
}
|
||||
+18
@@ -0,0 +1,18 @@
|
||||
package com.baeldung.cucumber_tags.service;
|
||||
|
||||
import org.junit.jupiter.api.Test;
|
||||
|
||||
|
||||
import static org.junit.jupiter.api.Assertions.assertTrue;
|
||||
|
||||
public class RandomNumberGeneratorServiceUnitTest {
|
||||
|
||||
private final RandomNumberGeneratorService tested = new RandomNumberGeneratorService();
|
||||
|
||||
@Test
|
||||
public void generateRandomNumberReturnsOK() {
|
||||
|
||||
int actual = tested.generateRandomNumber(1,5);
|
||||
assertTrue(actual>=1 && actual<=5);
|
||||
}
|
||||
}
|
||||
+7
@@ -0,0 +1,7 @@
|
||||
@api
|
||||
Feature: Health check
|
||||
|
||||
Scenario: Should have a working health check
|
||||
When I make a GET call on /status
|
||||
Then I should receive 200 response status code
|
||||
And should receive a non-empty body
|
||||
+10
@@ -0,0 +1,10 @@
|
||||
@ui
|
||||
Feature: UI - Random Number Generator
|
||||
|
||||
Scenario: Successfully generate a random number
|
||||
Given we are expecting a random number between min and max
|
||||
And I am on random-number-generator page
|
||||
When I enter min 1
|
||||
And I enter max 10
|
||||
And I press Generate button
|
||||
Then I should receive a random number between 1 and 10
|
||||
@@ -0,0 +1 @@
|
||||
cucumber.plugin=pretty, json:target/cucumber/cucumber.json
|
||||
Reference in New Issue
Block a user