BAEL-4783 rename module and fix indents
This commit is contained in:
parent
c49ffcc3cd
commit
af9cc0deb9
|
@ -0,0 +1,182 @@
|
||||||
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
|
<project xmlns="http://maven.apache.org/POM/4.0.0"
|
||||||
|
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
|
||||||
|
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
|
||||||
|
|
||||||
|
|
||||||
|
<parent>
|
||||||
|
<groupId>com.baeldung</groupId>
|
||||||
|
<artifactId>parent-boot-2</artifactId>
|
||||||
|
<version>0.0.1-SNAPSHOT</version>
|
||||||
|
<relativePath>../../parent-boot-2</relativePath>
|
||||||
|
<!-- lookup parent from repository -->
|
||||||
|
</parent>
|
||||||
|
|
||||||
|
<modelVersion>4.0.0</modelVersion>
|
||||||
|
<artifactId>cucumber</artifactId>
|
||||||
|
<version>1.0-SNAPSHOT</version>
|
||||||
|
<name>cucumber</name>
|
||||||
|
|
||||||
|
<properties>
|
||||||
|
<maven.compiler.source>11</maven.compiler.source>
|
||||||
|
<maven.compiler.target>11</maven.compiler.target>
|
||||||
|
<cucumber.version>6.9.1</cucumber.version>
|
||||||
|
<cucumber-reporting.version>5.4.0</cucumber-reporting.version>
|
||||||
|
<selenium.version>3.141.59</selenium.version>
|
||||||
|
<webdrivermanager.version>4.3.1</webdrivermanager.version>
|
||||||
|
<webjars-locator.version>0.40</webjars-locator.version>
|
||||||
|
<jquery.version>3.0.0</jquery.version>
|
||||||
|
<bootstrap.version>4.5.3</bootstrap.version>
|
||||||
|
<spring-cloud-contract-wiremock.version>2.2.5.RELEASE</spring-cloud-contract-wiremock.version>
|
||||||
|
</properties>
|
||||||
|
|
||||||
|
<dependencies>
|
||||||
|
<dependency>
|
||||||
|
<groupId>org.springframework.boot</groupId>
|
||||||
|
<artifactId>spring-boot-starter-web</artifactId>
|
||||||
|
</dependency>
|
||||||
|
|
||||||
|
<dependency>
|
||||||
|
<groupId>org.springframework.boot</groupId>
|
||||||
|
<artifactId>spring-boot-starter-thymeleaf</artifactId>
|
||||||
|
</dependency>
|
||||||
|
<dependency>
|
||||||
|
<groupId>org.webjars</groupId>
|
||||||
|
<artifactId>webjars-locator</artifactId>
|
||||||
|
<version>${webjars-locator.version}</version>
|
||||||
|
</dependency>
|
||||||
|
<dependency>
|
||||||
|
<groupId>org.webjars.npm</groupId>
|
||||||
|
<artifactId>jquery-slim</artifactId>
|
||||||
|
<version>${jquery.version}</version>
|
||||||
|
</dependency>
|
||||||
|
<dependency>
|
||||||
|
<groupId>org.webjars</groupId>
|
||||||
|
<artifactId>bootstrap</artifactId>
|
||||||
|
<version>${bootstrap.version}</version>
|
||||||
|
</dependency>
|
||||||
|
|
||||||
|
|
||||||
|
<dependency>
|
||||||
|
<groupId>org.projectlombok</groupId>
|
||||||
|
<artifactId>lombok</artifactId>
|
||||||
|
<scope>provided</scope>
|
||||||
|
</dependency>
|
||||||
|
<dependency>
|
||||||
|
<groupId>io.cucumber</groupId>
|
||||||
|
<artifactId>cucumber-java</artifactId>
|
||||||
|
<version>${cucumber.version}</version>
|
||||||
|
</dependency>
|
||||||
|
<dependency>
|
||||||
|
<groupId>io.cucumber</groupId>
|
||||||
|
<artifactId>cucumber-junit-platform-engine</artifactId>
|
||||||
|
<version>${cucumber.version}</version>
|
||||||
|
</dependency>
|
||||||
|
<dependency>
|
||||||
|
<groupId>io.cucumber</groupId>
|
||||||
|
<artifactId>cucumber-spring</artifactId>
|
||||||
|
<version>${cucumber.version}</version>
|
||||||
|
</dependency>
|
||||||
|
<dependency>
|
||||||
|
<groupId>org.seleniumhq.selenium</groupId>
|
||||||
|
<artifactId>selenium-java</artifactId>
|
||||||
|
<version>${selenium.version}</version>
|
||||||
|
</dependency>
|
||||||
|
<dependency>
|
||||||
|
<groupId>org.seleniumhq.selenium</groupId>
|
||||||
|
<artifactId>selenium-support</artifactId>
|
||||||
|
<version>${selenium.version}</version>
|
||||||
|
</dependency>
|
||||||
|
<dependency>
|
||||||
|
<groupId>io.github.bonigarcia</groupId>
|
||||||
|
<artifactId>webdrivermanager</artifactId>
|
||||||
|
<version>${webdrivermanager.version}</version>
|
||||||
|
<scope>test</scope>
|
||||||
|
</dependency>
|
||||||
|
<dependency>
|
||||||
|
<groupId>io.rest-assured</groupId>
|
||||||
|
<artifactId>spring-mock-mvc</artifactId>
|
||||||
|
<version>${rest-assured.version}</version>
|
||||||
|
<scope>test</scope>
|
||||||
|
</dependency>
|
||||||
|
<dependency>
|
||||||
|
<groupId>io.rest-assured</groupId>
|
||||||
|
<artifactId>json-schema-validator</artifactId>
|
||||||
|
<version>${rest-assured.version}</version>
|
||||||
|
<scope>test</scope>
|
||||||
|
</dependency>
|
||||||
|
<dependency>
|
||||||
|
<groupId>org.springframework.cloud</groupId>
|
||||||
|
<artifactId>spring-cloud-contract-wiremock</artifactId>
|
||||||
|
<version>${spring-cloud-contract-wiremock.version}</version>
|
||||||
|
<scope>test</scope>
|
||||||
|
</dependency>
|
||||||
|
</dependencies>
|
||||||
|
|
||||||
|
<build>
|
||||||
|
<pluginManagement>
|
||||||
|
<plugins>
|
||||||
|
<plugin>
|
||||||
|
<groupId>net.masterthought</groupId>
|
||||||
|
<artifactId>maven-cucumber-reporting</artifactId>
|
||||||
|
<version>${cucumber-reporting.version}</version>
|
||||||
|
<configuration>
|
||||||
|
<projectName>randomnumbergenerator</projectName>
|
||||||
|
<outputDirectory>
|
||||||
|
${project.build.directory}
|
||||||
|
</outputDirectory>
|
||||||
|
<inputDirectory>
|
||||||
|
${project.build.directory}/cucumber
|
||||||
|
</inputDirectory>
|
||||||
|
<classificationFiles>**/*.properties</classificationFiles>
|
||||||
|
<jsonFiles>
|
||||||
|
<param>**/*.json</param>
|
||||||
|
</jsonFiles>
|
||||||
|
</configuration>
|
||||||
|
</plugin>
|
||||||
|
</plugins>
|
||||||
|
</pluginManagement>
|
||||||
|
</build>
|
||||||
|
|
||||||
|
<profiles>
|
||||||
|
<profile>
|
||||||
|
<id>acceptance</id>
|
||||||
|
<activation>
|
||||||
|
<activeByDefault>false</activeByDefault>
|
||||||
|
</activation>
|
||||||
|
<build>
|
||||||
|
<plugins>
|
||||||
|
<plugin>
|
||||||
|
<groupId>org.apache.maven.plugins</groupId>
|
||||||
|
<artifactId>maven-failsafe-plugin</artifactId>
|
||||||
|
<version>${maven-failsafe-plugin.version}</version>
|
||||||
|
<configuration>
|
||||||
|
<includes>
|
||||||
|
<include>**/*IT.java</include>
|
||||||
|
</includes>
|
||||||
|
</configuration>
|
||||||
|
<goals>
|
||||||
|
<goal>integration-test</goal>
|
||||||
|
<goal>verify</goal>
|
||||||
|
</goals>
|
||||||
|
</plugin>
|
||||||
|
<plugin>
|
||||||
|
<groupId>net.masterthought</groupId>
|
||||||
|
<artifactId>maven-cucumber-reporting</artifactId>
|
||||||
|
<executions>
|
||||||
|
<execution>
|
||||||
|
<id>execution</id>
|
||||||
|
<phase>post-integration-test</phase>
|
||||||
|
<goals>
|
||||||
|
<goal>generate</goal>
|
||||||
|
</goals>
|
||||||
|
</execution>
|
||||||
|
</executions>
|
||||||
|
</plugin>
|
||||||
|
</plugins>
|
||||||
|
</build>
|
||||||
|
</profile>
|
||||||
|
|
||||||
|
</profiles>
|
||||||
|
|
||||||
|
</project>
|
|
@ -0,0 +1,13 @@
|
||||||
|
package com.baeldung.cucumber_tags;
|
||||||
|
|
||||||
|
import org.springframework.boot.SpringApplication;
|
||||||
|
import org.springframework.boot.autoconfigure.SpringBootApplication;
|
||||||
|
|
||||||
|
@SpringBootApplication
|
||||||
|
public class Application {
|
||||||
|
|
||||||
|
public static void main(String[] args) {
|
||||||
|
SpringApplication.run(Application.class, args);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
|
@ -0,0 +1,17 @@
|
||||||
|
package com.baeldung.cucumber_tags.controller;
|
||||||
|
|
||||||
|
|
||||||
|
import org.springframework.http.HttpStatus;
|
||||||
|
import org.springframework.http.MediaType;
|
||||||
|
import org.springframework.http.ResponseEntity;
|
||||||
|
import org.springframework.web.bind.annotation.RequestMapping;
|
||||||
|
import org.springframework.web.bind.annotation.RestController;
|
||||||
|
|
||||||
|
@RestController
|
||||||
|
public class HealthController {
|
||||||
|
|
||||||
|
@RequestMapping(value="/status", produces= MediaType.APPLICATION_JSON_VALUE)
|
||||||
|
public HttpStatus statusCheck() {
|
||||||
|
return ResponseEntity.ok().build().getStatusCode();
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,36 @@
|
||||||
|
package com.baeldung.cucumber_tags.controller;
|
||||||
|
|
||||||
|
import com.baeldung.cucumber_tags.service.RandomNumberGeneratorService;
|
||||||
|
import lombok.Data;
|
||||||
|
import org.springframework.stereotype.Controller;
|
||||||
|
import org.springframework.ui.Model;
|
||||||
|
import org.springframework.web.bind.annotation.GetMapping;
|
||||||
|
import org.springframework.web.bind.annotation.ModelAttribute;
|
||||||
|
import org.springframework.web.bind.annotation.PostMapping;
|
||||||
|
|
||||||
|
|
||||||
|
@Controller
|
||||||
|
public class UiController {
|
||||||
|
|
||||||
|
@GetMapping("/random-number-generator")
|
||||||
|
public String showForm(Model model) {
|
||||||
|
RandomNumberQuery randomNumberQuery = new RandomNumberQuery();
|
||||||
|
model.addAttribute("randomNumberQuery", randomNumberQuery);
|
||||||
|
|
||||||
|
return "random-number-generator";
|
||||||
|
}
|
||||||
|
|
||||||
|
@PostMapping(value = "/random-number-generator")
|
||||||
|
public String generateRandomNumber(@ModelAttribute("randomNumberQuery") final RandomNumberQuery randomNumberQuery) {
|
||||||
|
RandomNumberGeneratorService service = new RandomNumberGeneratorService();
|
||||||
|
randomNumberQuery.randomNumber = service.generateRandomNumber(randomNumberQuery.min, randomNumberQuery.max);
|
||||||
|
return "random-number-generator";
|
||||||
|
}
|
||||||
|
|
||||||
|
@Data
|
||||||
|
private static class RandomNumberQuery {
|
||||||
|
Integer min = null;
|
||||||
|
Integer max = null;
|
||||||
|
Integer randomNumber = null;
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,10 @@
|
||||||
|
package com.baeldung.cucumber_tags.service;
|
||||||
|
|
||||||
|
import java.util.concurrent.ThreadLocalRandom;
|
||||||
|
|
||||||
|
public class RandomNumberGeneratorService {
|
||||||
|
|
||||||
|
public int generateRandomNumber(int min, int max) {
|
||||||
|
return ThreadLocalRandom.current().nextInt(min, max + 1);
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,53 @@
|
||||||
|
<!DOCTYPE HTML>
|
||||||
|
<html lang="en" xmlns:th="http://www.thymeleaf.org">
|
||||||
|
<head>
|
||||||
|
<meta charset="utf-8">
|
||||||
|
<meta name="viewport" content="width=device-width, initial-scale=1, shrink-to-fit=no">
|
||||||
|
<title>Random Number Generator</title>
|
||||||
|
|
||||||
|
<link rel="stylesheet" th:href="@{webjars/bootstrap/css/bootstrap.min.css}"/>
|
||||||
|
</head>
|
||||||
|
<body>
|
||||||
|
<nav class="navbar navbar-light bg-light">
|
||||||
|
<div class="container">
|
||||||
|
<h1 class="navbar-brand mb-10 h1">Random Number Generator</h1>
|
||||||
|
</div>
|
||||||
|
</nav>
|
||||||
|
<div role="main" class="container">
|
||||||
|
<div>
|
||||||
|
<form id="random" name="random" action="#" th:action="@{/random-number-generator}"
|
||||||
|
th:object="${randomNumberQuery}" method="post">
|
||||||
|
|
||||||
|
<div class="row mt-10">
|
||||||
|
<label for="min" class="col-sm-1 control-label">Min:</label>
|
||||||
|
<div class="col-sm-3">
|
||||||
|
<input type="text" id="min" class="form-control" th:field="*{min}" placeholder="min" required
|
||||||
|
autofocus>
|
||||||
|
</div>
|
||||||
|
<label for="max" class="col-sm-1 control-label">Max:</label>
|
||||||
|
<div class="col-sm-3">
|
||||||
|
<input type="text" id="max" class="form-control" th:field="*{max}" placeholder="max" required
|
||||||
|
autofocus>
|
||||||
|
</div>
|
||||||
|
<div class="col-sm-3">
|
||||||
|
<button id="generate" type="submit" class="btn btn-primary">Generate</button>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
</form>
|
||||||
|
|
||||||
|
<div class="row mt-10">
|
||||||
|
<p>Result: </p>
|
||||||
|
<p id="result" class="display-1 font-weight-bold" th:text="${randomNumberQuery.randomNumber}"></p>
|
||||||
|
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<script type="text/javascript" th:src="@{webjars/bootstrap/js/bootstrap.min.js}"></script>
|
||||||
|
|
||||||
|
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
|
||||||
|
</body>
|
||||||
|
</html>
|
|
@ -0,0 +1,9 @@
|
||||||
|
package com.baeldung.cucumber_tags.acceptance;
|
||||||
|
|
||||||
|
|
||||||
|
import io.cucumber.junit.platform.engine.Cucumber;
|
||||||
|
|
||||||
|
@Cucumber()
|
||||||
|
public class AcceptanceTestRunnerIT {
|
||||||
|
|
||||||
|
}
|
|
@ -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());
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
}
|
|
@ -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");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -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;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
|
@ -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;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
|
@ -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);
|
||||||
|
}
|
||||||
|
}
|
|
@ -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());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -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);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
|
@ -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();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
|
@ -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);
|
||||||
|
}
|
||||||
|
}
|
|
@ -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);
|
||||||
|
}
|
||||||
|
}
|
|
@ -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
|
|
@ -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
|
|
@ -42,6 +42,7 @@
|
||||||
<module>junit-4</module>
|
<module>junit-4</module>
|
||||||
<module>testing-libraries</module>
|
<module>testing-libraries</module>
|
||||||
<module>powermock</module>
|
<module>powermock</module>
|
||||||
|
<module>spring-junit5-cucumber</module>
|
||||||
</modules>
|
</modules>
|
||||||
|
|
||||||
</project>
|
</project>
|
||||||
|
|
Loading…
Reference in New Issue