├── .github └── workflows │ └── maven.yml ├── .gitignore ├── README.md ├── config.properties ├── pom.xml └── src ├── main ├── java │ └── com │ │ └── api │ │ ├── model │ │ ├── BookingDTO.java │ │ ├── BookingDates.java │ │ ├── BookingDetailsDTO.java │ │ └── BookingID.java │ │ ├── stepdefinition │ │ ├── CreateBookingStepdefinition.java │ │ ├── DeleteBookingStepdefinition.java │ │ ├── Hooks.java │ │ ├── UpdateBookingStepdefinition.java │ │ └── ViewBookingDetailsStepdefinition.java │ │ └── utils │ │ ├── ExcelUtils.java │ │ ├── JsonReader.java │ │ ├── MyTestListener.java │ │ ├── PropertiesFile.java │ │ ├── ResponseHandler.java │ │ ├── RestAssuredRequestFilter.java │ │ └── TestContext.java └── resources │ ├── extent-config.xml │ └── log4j.properties └── test ├── java └── com │ └── api │ └── test │ └── TestRunner.java └── resources ├── cucumber.properties ├── data ├── bookingBody.json └── testData.xlsx ├── extent.properties ├── features ├── CreateBooking.feature ├── DeleteBooking.feature ├── UpdateBooking.feature └── ViewBookingDetails.feature └── schemas ├── bookSchema.json ├── bookingDetailsSchema.json ├── createBookingSchema.json └── userSchema.json /.github/workflows/maven.yml: -------------------------------------------------------------------------------- 1 | # This workflow will build a Java project with Maven, and cache/restore any dependencies to improve the workflow execution time 2 | # For more information see: https://help.github.com/actions/language-and-framework-guides/building-and-testing-java-with-maven 3 | 4 | name: API Cucumber Workflow 5 | 6 | on: 7 | push: 8 | branches: [ "master" ] 9 | 10 | jobs: 11 | build: 12 | 13 | runs-on: windows-latest 14 | 15 | steps: 16 | - uses: actions/checkout@v3 17 | - name: Set up JDK 11 18 | uses: actions/setup-java@v3 19 | with: 20 | java-version: '11' 21 | distribution: 'temurin' 22 | cache: maven 23 | - name: Test execution 24 | run: mvn clean test 25 | - name: Upload execution report 26 | if: always() 27 | uses: actions/upload-artifact@v3 28 | with: 29 | name: report 30 | path: target/report 31 | - name: Upload execution logs 32 | if: always() 33 | uses: actions/upload-artifact@v3 34 | with: 35 | name: logs 36 | path: target/logs 37 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | # Compiled class file 2 | *.class 3 | 4 | # Log file 5 | *.log 6 | 7 | # BlueJ files 8 | *.ctxt 9 | 10 | # Mobile Tools for Java (J2ME) 11 | .mtj.tmp/ 12 | 13 | # Package Files # 14 | *.jar 15 | *.war 16 | *.nar 17 | *.ear 18 | *.zip 19 | *.tar.gz 20 | *.rar 21 | 22 | # virtual machine crash logs, see http://www.java.com/en/download/help/error_hotspot.xml 23 | hs_err_pid* 24 | 25 | /test-output/ 26 | /target/ 27 | /.classpath 28 | /.project 29 | /.settings 30 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # API-Cucumber 2 | 3 | ## **Overview:** 4 | API is the acronym for Application Programming Interface, which is a software intermediary that allows two applications to talk to each other. This API framework is developed using REST Assured and Cucumber. REST Assured is a Java library that provides a domain-specific language (DSL) for writing powerful, maintainable tests for RESTful APIs. Cucumber is an open source library, which supports behavior driven development. To be more precise, Cucumber can be defined as a testing framework, driven by plain English text. It serves as documentation, automated tests, and a development aid – all in one. 5 | 6 | For Demo purpose all the test cases are done on [Restful-booker](https://restful-booker.herokuapp.com/apidoc/index.html). 7 | 8 | ### **Some of the key features of this framework:** 9 | 10 | 1. It generates Extent report with all the step details. Report will be generated both HTML & PDF file format. 11 | 2. Generates execution logs, with detailed request and response details. 12 | 3. Feature file has examples of reading request details from json and excel file. 13 | 4. This also has an example to validate response body using json schema and java pojo classes. 14 | 5. Test execution can be triggered form command line. 15 | 6. Easy integration to CI/CD pipeline. 16 | 17 | ## **Required Setup :** 18 | 19 | - [Java](https://www.guru99.com/install-java.html) should be installed and configured. 20 | - [Maven](https://mkyong.com/maven/how-to-install-maven-in-windows/) should be installed and configured. 21 | - Download the files from Git repository either as zip file OR using [Git](https://phoenixnap.com/kb/how-to-install-git-windows). 22 | 23 | ## **Running Test:** 24 | 25 | Open the command prompt and navigate to the folder in which pom.xml file is present. 26 | Run the below Maven command. 27 | 28 | mvn clean test 29 | 30 | 31 | Once the execution completes report & log will be generated in below folder. 32 | 33 | **Report:** *target/report*
34 | **Log:** *target/logs* -------------------------------------------------------------------------------- /config.properties: -------------------------------------------------------------------------------- 1 | username = vinay 2 | password = 1111 3 | baseURL = https://restful-booker.herokuapp.com 4 | test.data.path = src/test/resources/data/ 5 | excel.name = testData.xlsx 6 | sheet.name = testData 7 | content.type = application/json -------------------------------------------------------------------------------- /pom.xml: -------------------------------------------------------------------------------- 1 | 3 | 4.0.0 4 | 5 | Cucumber 6 | APITesting 7 | 0.0.1-SNAPSHOT 8 | jar 9 | 10 | APITesting 11 | http://maven.apache.org 12 | 13 | 14 | 1.8 15 | 1.8 16 | UTF-8 17 | 6.9.1 18 | 5.2.2 19 | 2.0.0 20 | 21 | 22 | 23 | 24 | 25 | io.cucumber 26 | cucumber-java 27 | ${cucumber.version} 28 | 29 | 30 | io.cucumber 31 | cucumber-core 32 | ${cucumber.version} 33 | 34 | 35 | 36 | io.cucumber 37 | cucumber-junit 38 | ${cucumber.version} 39 | 40 | 41 | 42 | io.cucumber 43 | cucumber-picocontainer 44 | ${cucumber.version} 45 | 46 | 47 | 48 | io.cucumber 49 | cucumber-jvm-deps 50 | 1.0.6 51 | 52 | 53 | 54 | io.cucumber 55 | gherkin 56 | 5.0.0 57 | 58 | 59 | 60 | io.rest-assured 61 | rest-assured 62 | 3.3.0 63 | 64 | 65 | 66 | io.rest-assured 67 | json-schema-validator 68 | 3.3.0 69 | 70 | 71 | 72 | com.googlecode.json-simple 73 | json-simple 74 | 1.1.1 75 | 76 | 77 | 78 | org.apache.poi 79 | poi 80 | ${poi.version} 81 | 82 | 83 | 84 | org.apache.poi 85 | poi-ooxml 86 | ${poi.version} 87 | 88 | 89 | 90 | org.json 91 | json 92 | 20230227 93 | 94 | 95 | 96 | com.google.guava 97 | guava 98 | 32.0.0-jre 99 | 100 | 101 | 102 | com.fasterxml.jackson.core 103 | jackson-databind 104 | 2.13.4.2 105 | 106 | 107 | 108 | com.github.dzieciou.testing 109 | curl-logger 110 | 2.0.1 111 | 112 | 113 | org.slf4j 114 | slf4j-simple 115 | ${logger.version} 116 | 117 | 118 | org.slf4j 119 | slf4j-api 120 | ${logger.version} 121 | 122 | 123 | org.slf4j 124 | slf4j-reload4j 125 | ${logger.version} 126 | 127 | 128 | 129 | tech.grasshopper 130 | extentreports-cucumber6-adapter 131 | 2.13.0 132 | 133 | 134 | 135 | 136 | 137 | org.apache.maven.plugins 138 | maven-surefire-plugin 139 | 3.0.0-M3 140 | 141 | 142 | test 143 | 144 | 145 | com.api.test.TestRunner.java 146 | 147 | true 148 | true 149 | 150 | 151 | 152 | 153 | 154 | org.apache.maven.plugins 155 | maven-compiler-plugin 156 | 3.7.0 157 | 158 | 1.8 159 | 1.8 160 | 161 | 162 | 163 | 164 | -------------------------------------------------------------------------------- /src/main/java/com/api/model/BookingDTO.java: -------------------------------------------------------------------------------- 1 | package com.api.model; 2 | 3 | public class BookingDTO 4 | { 5 | private BookingDetailsDTO booking; 6 | 7 | private String bookingid; 8 | 9 | public BookingDetailsDTO getBooking () 10 | { 11 | return booking; 12 | } 13 | 14 | public void setBooking (BookingDetailsDTO booking) 15 | { 16 | this.booking = booking; 17 | } 18 | 19 | public String getBookingid () 20 | { 21 | return bookingid; 22 | } 23 | 24 | public void setBookingid (String bookingid) 25 | { 26 | this.bookingid = bookingid; 27 | } 28 | 29 | @Override 30 | public String toString() 31 | { 32 | return "ClassPojo [booking = "+booking+", bookingid = "+bookingid+"]"; 33 | } 34 | } -------------------------------------------------------------------------------- /src/main/java/com/api/model/BookingDates.java: -------------------------------------------------------------------------------- 1 | package com.api.model; 2 | 3 | public class BookingDates { 4 | private String checkin; 5 | 6 | private String checkout; 7 | 8 | public String getCheckin () 9 | { 10 | return checkin; 11 | } 12 | 13 | public void setCheckin (String checkin) 14 | { 15 | this.checkin = checkin; 16 | } 17 | 18 | public String getCheckout () 19 | { 20 | return checkout; 21 | } 22 | 23 | public void setCheckout (String checkout) 24 | { 25 | this.checkout = checkout; 26 | } 27 | 28 | @Override 29 | public String toString() 30 | { 31 | return "ClassPojo [checkin = "+checkin+", checkout = "+checkout+"]"; 32 | } 33 | } -------------------------------------------------------------------------------- /src/main/java/com/api/model/BookingDetailsDTO.java: -------------------------------------------------------------------------------- 1 | package com.api.model; 2 | 3 | public class BookingDetailsDTO 4 | { 5 | private String firstname; 6 | 7 | private String additionalneeds; 8 | 9 | private BookingDates bookingdates; 10 | 11 | private String totalprice; 12 | 13 | private String depositpaid; 14 | 15 | private String lastname; 16 | 17 | public String getFirstname () 18 | { 19 | return firstname; 20 | } 21 | 22 | public void setFirstname (String firstname) 23 | { 24 | this.firstname = firstname; 25 | } 26 | 27 | public String getAdditionalneeds () 28 | { 29 | return additionalneeds; 30 | } 31 | 32 | public void setAdditionalneeds (String additionalneeds) 33 | { 34 | this.additionalneeds = additionalneeds; 35 | } 36 | 37 | public BookingDates getBookingdates () 38 | { 39 | return bookingdates; 40 | } 41 | 42 | public void setBookingdates (BookingDates bookingdates) 43 | { 44 | this.bookingdates = bookingdates; 45 | } 46 | 47 | public String getTotalprice () 48 | { 49 | return totalprice; 50 | } 51 | 52 | public void setTotalprice (String totalprice) 53 | { 54 | this.totalprice = totalprice; 55 | } 56 | 57 | public String getDepositpaid () 58 | { 59 | return depositpaid; 60 | } 61 | 62 | public void setDepositpaid (String depositpaid) 63 | { 64 | this.depositpaid = depositpaid; 65 | } 66 | 67 | public String getLastname () 68 | { 69 | return lastname; 70 | } 71 | 72 | public void setLastname (String lastname) 73 | { 74 | this.lastname = lastname; 75 | } 76 | 77 | @Override 78 | public String toString() 79 | { 80 | return "ClassPojo [firstname = "+firstname+", additionalneeds = "+additionalneeds+", bookingdates = "+bookingdates+", totalprice = "+totalprice+", depositpaid = "+depositpaid+", lastname = "+lastname+"]"; 81 | } 82 | } -------------------------------------------------------------------------------- /src/main/java/com/api/model/BookingID.java: -------------------------------------------------------------------------------- 1 | package com.api.model; 2 | 3 | public class BookingID { 4 | private String bookingid; 5 | 6 | public String getBookingid () 7 | { 8 | return bookingid; 9 | } 10 | 11 | public void setBookingid (String bookingid) 12 | { 13 | this.bookingid = bookingid; 14 | } 15 | 16 | @Override 17 | public String toString() 18 | { 19 | return "ClassPojo [bookingid = "+bookingid+"]"; 20 | } 21 | } 22 | -------------------------------------------------------------------------------- /src/main/java/com/api/stepdefinition/CreateBookingStepdefinition.java: -------------------------------------------------------------------------------- 1 | package com.api.stepdefinition; 2 | 3 | import static org.junit.Assert.*; 4 | 5 | import java.util.Map; 6 | 7 | import org.apache.log4j.LogManager; 8 | import org.apache.log4j.Logger; 9 | import org.json.JSONObject; 10 | 11 | import com.api.model.BookingDTO; 12 | import com.api.utils.ExcelUtils; 13 | import com.api.utils.JsonReader; 14 | import com.api.utils.ResponseHandler; 15 | import com.api.utils.TestContext; 16 | 17 | import io.cucumber.datatable.DataTable; 18 | import io.cucumber.java.en.Then; 19 | import io.cucumber.java.en.When; 20 | import io.restassured.module.jsv.JsonSchemaValidator; 21 | 22 | public class CreateBookingStepdefinition { 23 | private TestContext context; 24 | private static final Logger LOG = LogManager.getLogger(CreateBookingStepdefinition.class); 25 | 26 | public CreateBookingStepdefinition(TestContext context) { 27 | this.context = context; 28 | } 29 | 30 | @When("user creates a booking") 31 | public void userCreatesABooking(DataTable dataTable) { 32 | Map bookingData = dataTable.asMaps().get(0); 33 | JSONObject bookingBody = new JSONObject(); 34 | bookingBody.put("firstname", bookingData.get("firstname")); 35 | bookingBody.put("lastname", bookingData.get("lastname")); 36 | bookingBody.put("totalprice", Integer.valueOf(bookingData.get("totalprice"))); 37 | bookingBody.put("depositpaid", Boolean.valueOf(bookingData.get("depositpaid"))); 38 | JSONObject bookingDates = new JSONObject(); 39 | bookingDates.put("checkin", (bookingData.get("checkin"))); 40 | bookingDates.put("checkout", (bookingData.get("checkout"))); 41 | bookingBody.put("bookingdates", bookingDates); 42 | bookingBody.put("additionalneeds", bookingData.get("additionalneeds")); 43 | 44 | context.response = context.requestSetup().body(bookingBody.toString()) 45 | .when().post(context.session.get("endpoint").toString()); 46 | 47 | BookingDTO bookingDTO = ResponseHandler.deserializedResponse(context.response, BookingDTO.class); 48 | assertNotNull("Booking not created", bookingDTO); 49 | LOG.info("Newly created booking ID: "+bookingDTO.getBookingid()); 50 | context.session.put("bookingID", bookingDTO.getBookingid()); 51 | validateBookingData(new JSONObject(bookingData), bookingDTO); 52 | } 53 | 54 | private void validateBookingData(JSONObject bookingData, BookingDTO bookingDTO) { 55 | LOG.info(bookingData); 56 | assertNotNull("Booking ID missing", bookingDTO.getBookingid()); 57 | assertEquals("First Name did not match", bookingData.get("firstname"), bookingDTO.getBooking().getFirstname()); 58 | assertEquals("Last Name did not match", bookingData.get("lastname"), bookingDTO.getBooking().getLastname()); 59 | assertEquals("Total Price did not match", bookingData.get("totalprice"), bookingDTO.getBooking().getTotalprice()); 60 | assertEquals("Deposit Paid did not match", bookingData.get("depositpaid"), bookingDTO.getBooking().getDepositpaid()); 61 | assertEquals("Additional Needs did not match", bookingData.get("additionalneeds"), bookingDTO.getBooking().getAdditionalneeds()); 62 | assertEquals("Check in Date did not match", bookingData.get("checkin"), bookingDTO.getBooking().getBookingdates().getCheckin()); 63 | assertEquals("Check out Date did not match", bookingData.get("checkout"), bookingDTO.getBooking().getBookingdates().getCheckout()); 64 | } 65 | 66 | @When("user creates a booking using data {string} from Excel") 67 | public void userCreatesABookingUsingDataFromExcel(String dataKey) throws Exception { 68 | Map excelDataMap = ExcelUtils.getData(dataKey); 69 | context.response = context.requestSetup().body(excelDataMap.get("requestBody")) 70 | .when().post(context.session.get("endpoint").toString()); 71 | 72 | BookingDTO bookingDTO = ResponseHandler.deserializedResponse(context.response, BookingDTO.class); 73 | assertNotNull("Booking not created", bookingDTO); 74 | LOG.info("Newly created booking ID: "+bookingDTO.getBookingid()); 75 | context.session.put("bookingID", bookingDTO.getBookingid()); 76 | validateBookingData(new JSONObject(excelDataMap.get("responseBody")), bookingDTO); 77 | context.session.put("excelDataMap", excelDataMap); 78 | } 79 | 80 | @Then("user validates the response with JSON schema from Excel") 81 | public void userValidatesTheResponseWithJSONSchemaFromExcel() { 82 | context.response.then().assertThat().body(JsonSchemaValidator.matchesJsonSchema(((Map) context.session.get("excelDataMap")).get("responseSchema"))); 83 | LOG.info("Successfully Validated schema from Excel"); 84 | } 85 | 86 | @When("user creates a booking using data {string} from JSON file {string}") 87 | public void userCreatesABookingUsingDataFromJSONFile(String dataKey, String JSONFile) { 88 | context.response = context.requestSetup().body(JsonReader.getRequestBody(JSONFile,dataKey)) 89 | .when().post(context.session.get("endpoint").toString()); 90 | 91 | BookingDTO bookingDTO = ResponseHandler.deserializedResponse(context.response, BookingDTO.class); 92 | assertNotNull("Booking not created", bookingDTO); 93 | LOG.info("Newly created booking ID: "+bookingDTO.getBookingid()); 94 | context.session.put("bookingID", bookingDTO.getBookingid()); 95 | } 96 | } 97 | -------------------------------------------------------------------------------- /src/main/java/com/api/stepdefinition/DeleteBookingStepdefinition.java: -------------------------------------------------------------------------------- 1 | package com.api.stepdefinition; 2 | 3 | import com.api.utils.TestContext; 4 | 5 | import io.cucumber.java.en.When; 6 | 7 | public class DeleteBookingStepdefinition { 8 | private TestContext context; 9 | 10 | public DeleteBookingStepdefinition(TestContext context) { 11 | this.context = context; 12 | } 13 | 14 | @When("user makes a request to delete booking with basic auth {string} & {string}") 15 | public void userMakesARequestToDeleteBookingWithBasicAuth(String username, String password) { 16 | context.response = context.requestSetup() 17 | .auth().preemptive().basic(username, password) 18 | .pathParam("bookingID", context.session.get("bookingID")) 19 | .when().delete(context.session.get("endpoint")+"/{bookingID}"); 20 | } 21 | } 22 | -------------------------------------------------------------------------------- /src/main/java/com/api/stepdefinition/Hooks.java: -------------------------------------------------------------------------------- 1 | package com.api.stepdefinition; 2 | 3 | import org.apache.log4j.LogManager; 4 | import org.apache.log4j.Logger; 5 | 6 | import io.cucumber.java.Before; 7 | import io.cucumber.java.Scenario; 8 | 9 | public class Hooks { 10 | 11 | private static final Logger LOG = LogManager.getLogger(Hooks.class); 12 | 13 | @Before 14 | public void testStart(Scenario scenario) { 15 | LOG.info("*****************************************************************************************"); 16 | LOG.info(" Scenario: "+scenario.getName()); 17 | LOG.info("*****************************************************************************************"); 18 | } 19 | } 20 | -------------------------------------------------------------------------------- /src/main/java/com/api/stepdefinition/UpdateBookingStepdefinition.java: -------------------------------------------------------------------------------- 1 | package com.api.stepdefinition; 2 | 3 | import static org.junit.Assert.*; 4 | 5 | import java.util.Map; 6 | 7 | import org.apache.log4j.LogManager; 8 | import org.apache.log4j.Logger; 9 | import org.json.JSONObject; 10 | 11 | import com.api.model.BookingDetailsDTO; 12 | import com.api.utils.ExcelUtils; 13 | import com.api.utils.JsonReader; 14 | import com.api.utils.ResponseHandler; 15 | import com.api.utils.TestContext; 16 | 17 | import io.cucumber.java.en.When; 18 | import io.cucumber.datatable.DataTable; 19 | 20 | public class UpdateBookingStepdefinition { 21 | private TestContext context; 22 | private static final Logger LOG = LogManager.getLogger(UpdateBookingStepdefinition.class); 23 | 24 | public UpdateBookingStepdefinition(TestContext context) { 25 | this.context = context; 26 | } 27 | 28 | @When("user creates a auth token with credential {string} & {string}") 29 | public void userCreatesAAuthTokenWithCredential(String username, String password) { 30 | JSONObject credentials = new JSONObject(); 31 | credentials.put("username", username); 32 | credentials.put("password", password); 33 | context.response = context.requestSetup().body(credentials.toString()) 34 | .when().post(context.session.get("endpoint").toString()); 35 | String token = context.response.path("token"); 36 | LOG.info("Auth Token: "+token); 37 | context.session.put("token", "token="+token); 38 | } 39 | 40 | @When("user updates the details of a booking") 41 | public void userUpdatesABooking(DataTable dataTable) { 42 | Map bookingData = dataTable.asMaps().get(0); 43 | JSONObject bookingBody = new JSONObject(); 44 | bookingBody.put("firstname", bookingData.get("firstname")); 45 | bookingBody.put("lastname", bookingData.get("lastname")); 46 | bookingBody.put("totalprice", Integer.valueOf(bookingData.get("totalprice"))); 47 | bookingBody.put("depositpaid", Boolean.valueOf(bookingData.get("depositpaid"))); 48 | JSONObject bookingDates = new JSONObject(); 49 | bookingDates.put("checkin", (bookingData.get("checkin"))); 50 | bookingDates.put("checkout", (bookingData.get("checkout"))); 51 | bookingBody.put("bookingdates", bookingDates); 52 | bookingBody.put("additionalneeds", bookingData.get("additionalneeds")); 53 | 54 | context.response = context.requestSetup() 55 | .header("Cookie", context.session.get("token").toString()) 56 | .pathParam("bookingID", context.session.get("bookingID")) 57 | .body(bookingBody.toString()) 58 | .when().put(context.session.get("endpoint")+"/{bookingID}"); 59 | 60 | BookingDetailsDTO bookingDetailsDTO = ResponseHandler.deserializedResponse(context.response, BookingDetailsDTO.class); 61 | assertNotNull("Booking not created", bookingDetailsDTO); 62 | } 63 | 64 | @When("user updates the booking details using data {string} from Excel") 65 | public void userUpdatesTheBookingDetailsUsingDataFromExcel(String dataKey) throws Exception { 66 | Map excelDataMap = ExcelUtils.getData(dataKey); 67 | context.response = context.requestSetup() 68 | .header("Cookie", context.session.get("token").toString()) 69 | .pathParam("bookingID", context.session.get("bookingID")) 70 | .body(excelDataMap.get("requestBody")) 71 | .when().put(context.session.get("endpoint")+"/{bookingID}"); 72 | 73 | BookingDetailsDTO bookingDetailsDTO = ResponseHandler.deserializedResponse(context.response, BookingDetailsDTO.class); 74 | assertNotNull("Booking not created", bookingDetailsDTO); 75 | context.session.put("excelDataMap", excelDataMap); 76 | } 77 | 78 | @When("user updates the booking details using data {string} from JSON file {string}") 79 | public void userUpdatesTheBookingDetailsUsingDataFromJSONFile(String dataKey, String JSONFile) { 80 | context.response = context.requestSetup() 81 | .header("Cookie", context.session.get("token").toString()) 82 | .pathParam("bookingID", context.session.get("bookingID")) 83 | .body(JsonReader.getRequestBody(JSONFile,dataKey)) 84 | .when().put(context.session.get("endpoint")+"/{bookingID}"); 85 | 86 | BookingDetailsDTO bookingDetailsDTO = ResponseHandler.deserializedResponse(context.response, BookingDetailsDTO.class); 87 | assertNotNull("Booking not created", bookingDetailsDTO); 88 | } 89 | 90 | @When("user makes a request to update first name {string} & Last name {string}") 91 | public void userMakesARequestToUpdateFirstNameLastName(String firstName, String lastName) { 92 | JSONObject body = new JSONObject(); 93 | body.put("firstname", firstName); 94 | body.put("lastname", lastName); 95 | 96 | context.response = context.requestSetup() 97 | .header("Cookie", context.session.get("token").toString()) 98 | .pathParam("bookingID", context.session.get("bookingID")) 99 | .body(body.toString()) 100 | .when().patch(context.session.get("endpoint")+"/{bookingID}"); 101 | 102 | BookingDetailsDTO bookingDetailsDTO = ResponseHandler.deserializedResponse(context.response, BookingDetailsDTO.class); 103 | assertNotNull("Booking not created", bookingDetailsDTO); 104 | assertEquals("First Name did not match", firstName, bookingDetailsDTO.getFirstname()); 105 | assertEquals("Last Name did not match", lastName, bookingDetailsDTO.getLastname()); 106 | } 107 | } 108 | -------------------------------------------------------------------------------- /src/main/java/com/api/stepdefinition/ViewBookingDetailsStepdefinition.java: -------------------------------------------------------------------------------- 1 | package com.api.stepdefinition; 2 | 3 | import static org.junit.Assert.*; 4 | 5 | import org.apache.log4j.LogManager; 6 | import org.apache.log4j.Logger; 7 | 8 | import com.api.model.BookingDetailsDTO; 9 | import com.api.model.BookingID; 10 | import com.api.utils.ResponseHandler; 11 | import com.api.utils.TestContext; 12 | 13 | import io.cucumber.java.en.*; 14 | import io.restassured.module.jsv.JsonSchemaValidator; 15 | 16 | public class ViewBookingDetailsStepdefinition { 17 | private TestContext context; 18 | private static final Logger LOG = LogManager.getLogger(ViewBookingDetailsStepdefinition.class); 19 | 20 | public ViewBookingDetailsStepdefinition(TestContext context) { 21 | this.context = context; 22 | } 23 | 24 | @Given("user has access to endpoint {string}") 25 | public void userHasAccessToEndpoint(String endpoint) { 26 | context.session.put("endpoint", endpoint); 27 | } 28 | 29 | @When("user makes a request to view booking IDs") 30 | public void userMakesARequestToViewBookingIDs() { 31 | context.response = context.requestSetup().when().get(context.session.get("endpoint").toString()); 32 | int bookingID = context.response.getBody().jsonPath().getInt("[0].bookingid"); 33 | LOG.info("Booking ID: "+bookingID); 34 | assertNotNull("Booking ID not found!", bookingID); 35 | context.session.put("bookingID", bookingID); 36 | } 37 | 38 | @Then("user should get the response code {int}") 39 | public void userShpuldGetTheResponseCode(Integer statusCode) { 40 | assertEquals(Long.valueOf(statusCode), Long.valueOf(context.response.getStatusCode())); 41 | } 42 | 43 | @Then("user should see all the booking IDs") 44 | public void userShouldSeeAllTheBookingIDS() { 45 | BookingID[] bookingIDs = ResponseHandler.deserializedResponse(context.response, BookingID[].class); 46 | assertNotNull("Booking ID not found!!", bookingIDs); 47 | } 48 | 49 | @Then("user makes a request to view details of a booking ID") 50 | public void userMakesARequestToViewDetailsOfBookingID() { 51 | LOG.info("Session BookingID: "+context.session.get("bookingID")); 52 | context.response = context.requestSetup().pathParam("bookingID", context.session.get("bookingID")) 53 | .when().get(context.session.get("endpoint")+"/{bookingID}"); 54 | BookingDetailsDTO bookingDetails = ResponseHandler.deserializedResponse(context.response, BookingDetailsDTO.class); 55 | assertNotNull("Booking Details not found!!", bookingDetails); 56 | context.session.put("firstname", bookingDetails.getFirstname()); 57 | context.session.put("lastname", bookingDetails.getLastname()); 58 | } 59 | 60 | @Given("user makes a request to view booking IDs from {string} to {string}") 61 | public void userMakesARequestToViewBookingFromTo(String checkin, String checkout) { 62 | context.response = context.requestSetup() 63 | .queryParams("checkin",checkin, "checkout", checkout) 64 | .when().get(context.session.get("endpoint").toString()); 65 | } 66 | 67 | @Then("user makes a request to view all the booking IDs of that user name") 68 | public void userMakesARequestToViewBookingIDByUserName() { 69 | LOG.info("Session firstname: "+context.session.get("firstname")); 70 | LOG.info("Session lastname: "+context.session.get("lastname")); 71 | context.response = context.requestSetup() 72 | .queryParams("firstname", context.session.get("firstname"), "lastname", context.session.get("lastname")) 73 | .when().get(context.session.get("endpoint").toString()); 74 | BookingID[] bookingIDs = ResponseHandler.deserializedResponse(context.response, BookingID[].class); 75 | assertNotNull("Booking ID not found!!", bookingIDs); 76 | } 77 | 78 | @Then("user validates the response with JSON schema {string}") 79 | public void userValidatesResponseWithJSONSchema(String schemaFileName) { 80 | context.response.then().assertThat().body(JsonSchemaValidator.matchesJsonSchemaInClasspath("schemas/"+schemaFileName)); 81 | LOG.info("Successfully Validated schema from "+schemaFileName); 82 | } 83 | 84 | @When("user makes a request to check the health of booking service") 85 | public void userMakesARequestToCheckTheHealthOfBookingService() { 86 | context.response = context.requestSetup().get(context.session.get("endpoint").toString()); 87 | } 88 | } 89 | -------------------------------------------------------------------------------- /src/main/java/com/api/utils/ExcelUtils.java: -------------------------------------------------------------------------------- 1 | package com.api.utils; 2 | 3 | import java.io.File; 4 | import java.io.FileInputStream; 5 | import java.io.FileOutputStream; 6 | import java.io.IOException; 7 | import java.util.HashMap; 8 | import java.util.Map; 9 | 10 | import org.apache.log4j.LogManager; 11 | import org.apache.log4j.Logger; 12 | import org.apache.poi.ss.usermodel.CellType; 13 | import org.apache.poi.xssf.usermodel.XSSFCell; 14 | import org.apache.poi.xssf.usermodel.XSSFRow; 15 | import org.apache.poi.xssf.usermodel.XSSFSheet; 16 | import org.apache.poi.xssf.usermodel.XSSFWorkbook; 17 | 18 | public class ExcelUtils { 19 | private static XSSFSheet excelSheet; 20 | private static XSSFWorkbook excelWorkbook; 21 | private static XSSFCell cell; 22 | private static XSSFRow row; 23 | private static String sheetPath = PropertiesFile.getProperty("test.data.path")+PropertiesFile.getProperty("excel.name"); 24 | private static String sheetName = PropertiesFile.getProperty("sheet.name"); 25 | private static final Logger LOG = LogManager.getLogger(ExcelUtils.class); 26 | 27 | private static void setExcelFile() throws IOException { 28 | LOG.info("Getting sheets from the workbook."); 29 | FileInputStream excelFile = new FileInputStream(new File(sheetPath).getAbsolutePath()); 30 | excelWorkbook = new XSSFWorkbook(excelFile); 31 | excelSheet = excelWorkbook.getSheet(sheetName); 32 | } 33 | 34 | private static int getDataRow(String dataKey, int dataColumn) { 35 | int rowCount = excelSheet.getLastRowNum(); 36 | for(int row=0; row<= rowCount; row++){ 37 | if(ExcelUtils.getCellData(row, dataColumn).equalsIgnoreCase(dataKey)){ 38 | return row; 39 | } 40 | } 41 | return 0; 42 | } 43 | 44 | private static String getCellData(int rowNumb, int colNumb) { 45 | cell = excelSheet.getRow(rowNumb).getCell(colNumb); 46 | //LOG.info("Getting cell data."); 47 | if(cell.getCellType() == CellType.NUMERIC) { 48 | cell.setCellType(CellType.STRING); 49 | } 50 | String cellData = cell.getStringCellValue(); 51 | return cellData; 52 | } 53 | 54 | public static void setCellData(String result, int rowNumb, int colNumb, String sheetPath,String sheetName) throws Exception{ 55 | try{ 56 | row = excelSheet.getRow(rowNumb); 57 | cell = row.getCell(colNumb); 58 | LOG.info("Setting results into the excel sheet."); 59 | if(cell==null){ 60 | cell = row.createCell(colNumb); 61 | cell.setCellValue(result); 62 | } 63 | else{ 64 | cell.setCellValue(result); 65 | } 66 | 67 | LOG.info("Creating file output stream."); 68 | FileOutputStream fileOut = new FileOutputStream(sheetPath + sheetName); 69 | excelWorkbook.write(fileOut); 70 | fileOut.flush(); 71 | fileOut.close(); 72 | 73 | }catch(Exception exp){ 74 | LOG.info("Exception occured in setCellData: "+exp); 75 | } 76 | } 77 | 78 | public static Map getData(String dataKey) throws Exception { 79 | Map dataMap = new HashMap(); 80 | setExcelFile(); 81 | int dataRow = getDataRow(dataKey.trim(), 0); 82 | LOG.info("Test Data Found in Row: "+dataRow); 83 | if (dataRow == 0) { 84 | throw new Exception("NO DATA FOUND for dataKey: "+dataKey); 85 | } 86 | int columnCount = excelSheet.getRow(dataRow).getLastCellNum(); 87 | for(int i=0;i dataMap = new HashMap(); 103 | dataMap = getData("updateBooking21"); 104 | for(Map.Entry data: dataMap.entrySet()) { 105 | LOG.info(data.getKey()+ " ==> " + data.getValue()); 106 | } 107 | } 108 | } 109 | -------------------------------------------------------------------------------- /src/main/java/com/api/utils/JsonReader.java: -------------------------------------------------------------------------------- 1 | package com.api.utils; 2 | 3 | import java.io.File; 4 | import java.io.FileNotFoundException; 5 | import java.io.FileReader; 6 | import java.io.IOException; 7 | 8 | import org.json.simple.JSONObject; 9 | import org.json.simple.parser.JSONParser; 10 | import org.json.simple.parser.ParseException; 11 | 12 | public class JsonReader { 13 | 14 | private static String dataPath = new File(PropertiesFile.getProperty("test.data.path")).getAbsolutePath()+File.separator; 15 | private static JSONParser parser = new JSONParser(); 16 | private static Object body; 17 | 18 | public static String getRequestBody(String jsonFileName, String jsonKey) { 19 | try { 20 | body = ((JSONObject)parser.parse(new FileReader(dataPath+jsonFileName))).get(jsonKey); 21 | if (body == null) { 22 | throw new RuntimeException("NO DATA FOUND in JSON file '" + jsonFileName +"' for key '"+jsonKey+"'"); 23 | } 24 | } catch (FileNotFoundException e) { 25 | throw new RuntimeException("JSON file not found at path: " + dataPath+jsonFileName); 26 | } catch (IOException e) { 27 | throw new RuntimeException("IOException while reading file: " + jsonFileName); 28 | } catch (ParseException e) { 29 | throw new RuntimeException("Parse Exception occured while Parsing: " + jsonFileName); 30 | } 31 | return body.toString(); 32 | } 33 | } 34 | -------------------------------------------------------------------------------- /src/main/java/com/api/utils/MyTestListener.java: -------------------------------------------------------------------------------- 1 | package com.api.utils; 2 | 3 | import org.apache.log4j.LogManager; 4 | import org.apache.log4j.Logger; 5 | 6 | import io.cucumber.plugin.ConcurrentEventListener; 7 | import io.cucumber.plugin.event.EventPublisher; 8 | import io.cucumber.plugin.event.Result; 9 | import io.cucumber.plugin.event.Status; 10 | import io.cucumber.plugin.event.TestCase; 11 | import io.cucumber.plugin.event.TestCaseFinished; 12 | 13 | public class MyTestListener implements ConcurrentEventListener { 14 | private static final Logger LOG = LogManager.getLogger(MyTestListener.class); 15 | 16 | @Override 17 | public void setEventPublisher(EventPublisher publisher) { 18 | publisher.registerHandlerFor(TestCaseFinished.class, this::handleTestCaseFinished); 19 | } 20 | 21 | private void handleTestCaseFinished(TestCaseFinished event) { 22 | TestCase testCase = event.getTestCase(); 23 | Result result = event.getResult(); 24 | Status status = result.getStatus(); 25 | Throwable error = result.getError(); 26 | String scenarioName = testCase.getName(); 27 | if(error != null) { 28 | LOG.info(error); 29 | } 30 | LOG.info("*****************************************************************************************"); 31 | LOG.info(" Scenario: "+scenarioName+" --> "+status.name()); 32 | LOG.info("*****************************************************************************************"); 33 | } 34 | } -------------------------------------------------------------------------------- /src/main/java/com/api/utils/PropertiesFile.java: -------------------------------------------------------------------------------- 1 | package com.api.utils; 2 | 3 | import java.io.File; 4 | import java.io.FileInputStream; 5 | import java.io.FileNotFoundException; 6 | import java.io.IOException; 7 | import java.util.Properties; 8 | 9 | import org.apache.log4j.LogManager; 10 | import org.apache.log4j.Logger; 11 | 12 | public class PropertiesFile { 13 | 14 | private static final Logger LOG = LogManager.getLogger(PropertiesFile.class); 15 | private static FileInputStream fis; 16 | private static Properties prop = null; 17 | 18 | public static String getProperty(String property) { 19 | 20 | try { 21 | fis = new FileInputStream(new File("config.properties")); 22 | prop = new Properties(); 23 | prop.load(fis); 24 | } catch(FileNotFoundException fnfe) { 25 | LOG.error("Properties File Not Found", fnfe); 26 | } catch(IOException ioe) { 27 | LOG.error("IO Exception while loading Properties File", ioe); 28 | } finally { 29 | try { 30 | fis.close(); 31 | } catch (IOException e) { 32 | LOG.error("IO Exception while closing file input stream", e); 33 | } 34 | } 35 | return prop.getProperty(property).trim(); 36 | } 37 | } 38 | -------------------------------------------------------------------------------- /src/main/java/com/api/utils/ResponseHandler.java: -------------------------------------------------------------------------------- 1 | package com.api.utils; 2 | 3 | import java.io.IOException; 4 | 5 | import com.fasterxml.jackson.databind.ObjectMapper; 6 | 7 | import io.restassured.response.Response; 8 | 9 | public class ResponseHandler { 10 | 11 | public static T deserializedResponse(Response response, Class T ){ 12 | ObjectMapper mapper = new ObjectMapper(); 13 | T responseDeserialized = null; 14 | try { 15 | responseDeserialized = (T) mapper.readValue(response.asString(), T); 16 | String jsonStr = mapper.writerWithDefaultPrettyPrinter().writeValueAsString(responseDeserialized); // Pretty print JSON 17 | System.out.println("Handling Response: \n"+responseDeserialized.toString()); 18 | } catch (IOException e) { 19 | e.printStackTrace(System.out); 20 | } 21 | return responseDeserialized; 22 | } 23 | 24 | } 25 | -------------------------------------------------------------------------------- /src/main/java/com/api/utils/RestAssuredRequestFilter.java: -------------------------------------------------------------------------------- 1 | package com.api.utils; 2 | 3 | import org.apache.log4j.LogManager; 4 | import org.apache.log4j.Logger; 5 | 6 | import io.restassured.filter.Filter; 7 | import io.restassured.filter.FilterContext; 8 | import io.restassured.response.Response; 9 | import io.restassured.specification.FilterableRequestSpecification; 10 | import io.restassured.specification.FilterableResponseSpecification; 11 | 12 | public class RestAssuredRequestFilter implements Filter { 13 | private static final Logger LOG = LogManager.getLogger(RestAssuredRequestFilter.class); 14 | 15 | @Override 16 | public Response filter(FilterableRequestSpecification requestSpec, FilterableResponseSpecification responseSpec, FilterContext ctx) { 17 | Response response = ctx.next(requestSpec, responseSpec); 18 | LOG.info("-----------------------------------------------------------------------------------------"); 19 | LOG.info(" Request Method => " + requestSpec.getMethod() + 20 | "\n Request URI => " + requestSpec.getURI() + 21 | "\n Request Header =>\n" + requestSpec.getHeaders() + 22 | "\n Request Body => " + requestSpec.getBody() + 23 | "\n\n Response Status => "+ response.getStatusLine() + 24 | "\n Response Header =>\n"+ response.getHeaders() + 25 | "\n Response Body => " + response.getBody().prettyPrint()); 26 | LOG.info("-----------------------------------------------------------------------------------------"); 27 | return response; 28 | } 29 | } -------------------------------------------------------------------------------- /src/main/java/com/api/utils/TestContext.java: -------------------------------------------------------------------------------- 1 | package com.api.utils; 2 | 3 | import java.util.HashMap; 4 | import java.util.Map; 5 | 6 | import com.github.dzieciou.testing.curl.CurlRestAssuredConfigFactory; 7 | import com.github.dzieciou.testing.curl.Options; 8 | 9 | import io.restassured.RestAssured; 10 | import io.restassured.config.RestAssuredConfig; 11 | import io.restassured.response.Response; 12 | import io.restassured.specification.RequestSpecification; 13 | 14 | public class TestContext { 15 | 16 | public Response response; 17 | public Map session = new HashMap(); 18 | private static final String CONTENT_TYPE = PropertiesFile.getProperty("content.type"); 19 | 20 | public RequestSpecification requestSetup() { 21 | RestAssured.reset(); 22 | Options options = Options.builder().logStacktrace().build(); 23 | RestAssuredConfig config = CurlRestAssuredConfigFactory.createConfig(options); 24 | RestAssured.baseURI = PropertiesFile.getProperty("baseURL"); 25 | return RestAssured.given() 26 | .config(config) 27 | .filter(new RestAssuredRequestFilter()) 28 | .contentType(CONTENT_TYPE) 29 | .accept(CONTENT_TYPE); 30 | } 31 | } 32 | -------------------------------------------------------------------------------- /src/main/resources/extent-config.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | dark 7 | 8 | 9 | UTF-8 10 | 11 | 12 | http 13 | 14 | Booker API Report 15 | 16 | Execution Report 17 | 18 | 19 | top 20 | 21 | 22 | 23 | 27 | 28 | 29 | 30 | 32 | 33 | 34 | -------------------------------------------------------------------------------- /src/main/resources/log4j.properties: -------------------------------------------------------------------------------- 1 | log4j.rootLogger=INFO, STDOUT, file, HTML 2 | 3 | log4j.appender.STDOUT=org.apache.log4j.ConsoleAppender 4 | log4j.appender.STDOUT.layout=org.apache.log4j.PatternLayout 5 | log4j.appender.STDOUT.layout.ConversionPattern=%d{dd-MM-yyyy HH:mm:ss} %-5p %c{1}:%L - %m%n 6 | 7 | log4j.appender.file=org.apache.log4j.RollingFileAppender 8 | log4j.appender.file.File=target/logs/execution.log 9 | log4j.appender.file.layout=org.apache.log4j.PatternLayout 10 | log4j.appender.file.layout.ConversionPattern=%d{dd-MM-yyyy HH:mm:ss} %-5p %c{1}:%L - %m%n -------------------------------------------------------------------------------- /src/test/java/com/api/test/TestRunner.java: -------------------------------------------------------------------------------- 1 | package com.api.test; 2 | 3 | import org.junit.runner.RunWith; 4 | 5 | import io.cucumber.junit.Cucumber; 6 | import io.cucumber.junit.CucumberOptions; 7 | import io.cucumber.junit.CucumberOptions.SnippetType; 8 | 9 | @RunWith(Cucumber.class) 10 | @CucumberOptions( 11 | plugin = {"pretty:target/cucumber/cucumber.txt", 12 | "com.aventstack.extentreports.cucumber.adapter.ExtentCucumberAdapter:", 13 | //"html:target/cucumber/report", 14 | "json:target/cucumber/cucumber.json", 15 | "com.api.utils.MyTestListener" 16 | } 17 | ,features= {"src/test/resources/features"} 18 | ,glue = {"com.api.stepdefinition"} 19 | //,dryRun = true 20 | ,monochrome = true 21 | ,snippets = SnippetType.CAMELCASE 22 | ,tags = "@bookerAPI" 23 | //,publish = true 24 | ) 25 | public class TestRunner { 26 | 27 | } -------------------------------------------------------------------------------- /src/test/resources/cucumber.properties: -------------------------------------------------------------------------------- 1 | cucumber.publish.quiet=true -------------------------------------------------------------------------------- /src/test/resources/data/bookingBody.json: -------------------------------------------------------------------------------- 1 | { 2 | "createBooking1": { 3 | "firstname": "Sherlock", 4 | "lastname": "Holmes", 5 | "totalprice": "2500", 6 | "depositpaid": "true", 7 | "bookingdates": { 8 | "checkin":"2021-05-15", 9 | "checkout":"2021-06-02" 10 | }, 11 | "additionalneeds":"Snacks" 12 | }, 13 | "createBooking2": { 14 | "firstname": "James", 15 | "lastname": "Bond", 16 | "totalprice": "70007", 17 | "depositpaid": "false", 18 | "bookingdates": { 19 | "checkin":"2020-11-10", 20 | "checkout":"2020-11-20" 21 | }, 22 | "additionalneeds":"High Tea" 23 | }, 24 | "updateBooking1": { 25 | "firstname": "Clark", 26 | "lastname": "Kent", 27 | "totalprice": "12321", 28 | "depositpaid": "true", 29 | "bookingdates": { 30 | "checkin":"2021-11-10", 31 | "checkout":"2021-11-20" 32 | }, 33 | "additionalneeds":"Super Tea" 34 | }, 35 | "updateBooking2": { 36 | "firstname": "Bruce", 37 | "lastname": "Wayne", 38 | "totalprice": "35007", 39 | "depositpaid": "false", 40 | "bookingdates": { 41 | "checkin":"2021-09-10", 42 | "checkout":"2021-10-20" 43 | }, 44 | "additionalneeds":"Bat Dish" 45 | } 46 | } -------------------------------------------------------------------------------- /src/test/resources/data/testData.xlsx: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/VinayKumarBM/API-Cucumber/c689d37a71f907d1b14b128f2aa02fd1b38896d1/src/test/resources/data/testData.xlsx -------------------------------------------------------------------------------- /src/test/resources/extent.properties: -------------------------------------------------------------------------------- 1 | extent.reporter.spark.class=com.aventstack.extentreports.reporter.ExtentSparkReporter 2 | extent.reporter.json.class=com.aventstack.extentreports.reporter.JsonFormatter 3 | extent.reporter.pdf.class=tech.grasshopper.pdf.extent.ExtentPDFCucumberReporter 4 | 5 | extent.reporter.spark.start=true 6 | extent.reporter.json.start=false 7 | extent.reporter.pdf.start=true 8 | 9 | extent.reporter.spark.out=target/report/ExtentSpark.html 10 | extent.reporter.json.out=target/report/ExtentJson.json 11 | extent.reporter.pdf.out=target/report/ExtentPdf.pdf 12 | 13 | extent.reporter.spark.config=src/main/resources/extent-config.xml 14 | extent.reporter.logger.config=src/main/resources/extent-config.xml 15 | 16 | extent.reporter.spark.vieworder=dashboard,test,category,exception,author,device,log 17 | 18 | systeminfo.OS=Windows 19 | systeminfo.URL=https://restful-booker.herokuapp.com 20 | systeminfo.Owner=Vinay Kumar B M 21 | systeminfo.Role=Automation Tester -------------------------------------------------------------------------------- /src/test/resources/features/CreateBooking.feature: -------------------------------------------------------------------------------- 1 | @bookerAPI @createBooking 2 | Feature: To create a new booking in restful-booker 3 | 4 | @createBookingDataTable 5 | Scenario Outline: To create new booking using cucumber Data Table 6 | Given user has access to endpoint "/booking" 7 | When user creates a booking 8 | | firstname | lastname | totalprice | depositpaid | checkin | checkout | additionalneeds | 9 | | | | | | | | | 10 | Then user should get the response code 200 11 | And user validates the response with JSON schema "createBookingSchema.json" 12 | 13 | Examples: 14 | | firstname | lastname | totalprice | depositpaid | checkin | checkout | additionalneeds | 15 | | John | Doe | 1200 | true | 2021-05-05 | 2021-05-15 | Breakfast | 16 | | Jane | Doe | 2400 | false | 2021-06-01 | 2021-07-10 | Dinner | 17 | 18 | @createBookingFromExcel 19 | Scenario Outline: To create new booking using Excel data 20 | Given user has access to endpoint "/booking" 21 | When user creates a booking using data "" from Excel 22 | Then user should get the response code 200 23 | And user validates the response with JSON schema from Excel 24 | 25 | Examples: 26 | | dataKey | 27 | | createBooking1 | 28 | | createBooking2 | 29 | 30 | @createBookingFromJSON 31 | Scenario Outline: To create new booking using JSON data 32 | Given user has access to endpoint "/booking" 33 | When user creates a booking using data "" from JSON file "" 34 | Then user should get the response code 200 35 | And user validates the response with JSON schema "createBookingSchema.json" 36 | 37 | Examples: 38 | | dataKey | JSONFile | 39 | | createBooking1 | bookingBody.json | 40 | | createBooking2 | bookingBody.json | 41 | -------------------------------------------------------------------------------- /src/test/resources/features/DeleteBooking.feature: -------------------------------------------------------------------------------- 1 | @bookerAPI @deleteBooking 2 | Feature: To delete a booking in restful-booker 3 | 4 | Background: create an auth token 5 | Given user has access to endpoint "/auth" 6 | When user creates a auth token with credential "admin" & "password123" 7 | Then user should get the response code 200 8 | 9 | @deleteBookingIDs 10 | Scenario: To delete a booking 11 | Given user has access to endpoint "/booking" 12 | And user makes a request to view booking IDs 13 | When user makes a request to delete booking with basic auth "admin" & "password123" 14 | Then user should get the response code 201 15 | 16 | @e2eTest 17 | Scenario Outline: To perform a CURD operation on restful-booker 18 | Given user has access to endpoint "/booking" 19 | When user creates a booking 20 | | firstname | lastname | totalprice | depositpaid | checkin | checkout | additionalneeds | 21 | | | | | | | | | 22 | Then user should get the response code 200 23 | And user validates the response with JSON schema "createBookingSchema.json" 24 | And user updates the details of a booking 25 | | firstname | lastname | totalprice | depositpaid | checkin | checkout | additionalneeds | 26 | | | | | | | | | 27 | And user should get the response code 200 28 | And user validates the response with JSON schema "bookingDetailsSchema.json" 29 | And user makes a request to view details of a booking ID 30 | And user should get the response code 200 31 | And user validates the response with JSON schema "bookingDetailsSchema.json" 32 | And user makes a request to delete booking with basic auth "admin" & "password123" 33 | And user should get the response code 201 34 | 35 | Examples: 36 | | firstname | lastname | totalprice | depositpaid | checkin | checkout | additionalneeds | 37 | | John | Doe | 1200 | true | 2021-05-05 | 2021-05-15 | Breakfast | 38 | -------------------------------------------------------------------------------- /src/test/resources/features/UpdateBooking.feature: -------------------------------------------------------------------------------- 1 | @bookerAPI @updateBooking 2 | Feature: To update a booking in restful-booker 3 | 4 | Background: create an auth token 5 | Given user has access to endpoint "/auth" 6 | When user creates a auth token with credential "admin" & "password123" 7 | Then user should get the response code 200 8 | 9 | @updateBookingDataTable 10 | Scenario Outline: To update a booking using cucumber Data Table 11 | Given user has access to endpoint "/booking" 12 | When user makes a request to view booking IDs 13 | And user updates the details of a booking 14 | | firstname | lastname | totalprice | depositpaid | checkin | checkout | additionalneeds | 15 | | | | | | | | | 16 | Then user should get the response code 200 17 | And user validates the response with JSON schema "bookingDetailsSchema.json" 18 | 19 | Examples: 20 | | firstname | lastname | totalprice | depositpaid | checkin | checkout | additionalneeds | 21 | | John | Rambo | 10000 | true | 2021-05-15 | 2021-06-11 | Breakfast | 22 | | Rocky | Balboa | 2006 | false | 2021-06-01 | 2021-07-10 | Dinner | 23 | 24 | @updateBookingFromExcel 25 | Scenario Outline: To create and update a new booking using Excel data 26 | Given user has access to endpoint "/booking" 27 | And user creates a booking using data "" from Excel 28 | When user updates the booking details using data "" from Excel 29 | Then user should get the response code 200 30 | And user validates the response with JSON schema from Excel 31 | 32 | Examples: 33 | | createKey | updateKey | 34 | | createBooking1 | updateBooking1 | 35 | | createBooking2 | updateBooking2 | 36 | 37 | @updateBookingFromJSON 38 | Scenario Outline: To update a booking using JSON data 39 | Given user has access to endpoint "/booking" 40 | When user makes a request to view booking IDs 41 | And user updates the booking details using data "" from JSON file "" 42 | Then user should get the response code 200 43 | And user validates the response with JSON schema "bookingDetailsSchema.json" 44 | 45 | Examples: 46 | | dataKey | JSONFile | 47 | | updateBooking1 | bookingBody.json | 48 | | updateBooking2 | bookingBody.json | 49 | 50 | @partialUpdateBooking 51 | Scenario: To partially update a booking 52 | Given user has access to endpoint "/booking" 53 | When user makes a request to view booking IDs 54 | And user makes a request to update first name "John" & Last name "Wick" 55 | Then user should get the response code 200 56 | And user validates the response with JSON schema "bookingDetailsSchema.json" -------------------------------------------------------------------------------- /src/test/resources/features/ViewBookingDetails.feature: -------------------------------------------------------------------------------- 1 | @bookerAPI @viewBooking 2 | Feature: To view the restful-booker booking details 3 | 4 | @viewAllBookingIDs 5 | Scenario: To view all the booking IDs 6 | Given user has access to endpoint "/booking" 7 | When user makes a request to view booking IDs 8 | Then user should get the response code 200 9 | And user should see all the booking IDs 10 | 11 | @viewBookingDetails 12 | Scenario: To view booking details 13 | Given user has access to endpoint "/booking" 14 | When user makes a request to view booking IDs 15 | And user makes a request to view details of a booking ID 16 | Then user should get the response code 200 17 | And user validates the response with JSON schema "bookingDetailsSchema.json" 18 | 19 | @viewByBookingDates 20 | Scenario Outline: To view all the booking IDs by booking dates 21 | Given user has access to endpoint "/booking" 22 | When user makes a request to view booking IDs from "" to "" 23 | Then user should get the response code 200 24 | And user should see all the booking IDs 25 | 26 | Examples: 27 | | checkin | checkout | 28 | | 2018-01-01 | 2021-12-31 | 29 | | 2010-01-01 | 2020-12-31 | 30 | 31 | @viewBookingByName 32 | Scenario: To view all the booking IDs by booking names 33 | Given user has access to endpoint "/booking" 34 | When user makes a request to view booking IDs 35 | Then user should see all the booking IDs 36 | And user makes a request to view details of a booking ID 37 | And user makes a request to view all the booking IDs of that user name 38 | And user should get the response code 200 39 | And user should see all the booking IDs 40 | 41 | @healthCheck 42 | Scenario: To confirm whether the API is up and running 43 | Given user has access to endpoint "/ping" 44 | When user makes a request to check the health of booking service 45 | Then user should get the response code 201 46 | -------------------------------------------------------------------------------- /src/test/resources/schemas/bookSchema.json: -------------------------------------------------------------------------------- 1 | { 2 | "definitions": {}, 3 | "$schema": "http://json-schema.org/draft-07/schema#", 4 | "$id": "http://example.com/root.json", 5 | "type": "object", 6 | "title": "The Root Schema", 7 | "required": [ 8 | "title", 9 | "body", 10 | "userId", 11 | "id" 12 | ], 13 | "properties": { 14 | "title": { 15 | "$id": "#/properties/title", 16 | "type": "string", 17 | "title": "The Title Schema", 18 | "default": "", 19 | "examples": [ 20 | "Game of Throne" 21 | ], 22 | "pattern": "^(.*)$" 23 | }, 24 | "body": { 25 | "$id": "#/properties/body", 26 | "type": "string", 27 | "title": "The Body Schema", 28 | "default": "", 29 | "examples": [ 30 | "Here will be description of the Book" 31 | ], 32 | "pattern": "^(.*)$" 33 | }, 34 | "userId": { 35 | "$id": "#/properties/userId", 36 | "type": "string", 37 | "title": "The Userid Schema", 38 | "default": "", 39 | "examples": [ 40 | "911" 41 | ], 42 | "pattern": "^(.*)$" 43 | }, 44 | "id": { 45 | "$id": "#/properties/id", 46 | "type": "integer", 47 | "title": "The Id Schema", 48 | "default": 0, 49 | "examples": [ 50 | 101 51 | ] 52 | } 53 | } 54 | } -------------------------------------------------------------------------------- /src/test/resources/schemas/bookingDetailsSchema.json: -------------------------------------------------------------------------------- 1 | { 2 | "definitions": {}, 3 | "$schema": "http://json-schema.org/draft-07/schema#", 4 | "$id": "https://example.com/object1617469812.json", 5 | "title": "Root", 6 | "type": "object", 7 | "required": [ 8 | "firstname", 9 | "lastname", 10 | "totalprice", 11 | "depositpaid", 12 | "bookingdates" 13 | ], 14 | "properties": { 15 | "firstname": { 16 | "$id": "#root/firstname", 17 | "title": "Firstname", 18 | "type": "string", 19 | "default": "", 20 | "pattern": "^.*$" 21 | }, 22 | "lastname": { 23 | "$id": "#root/lastname", 24 | "title": "Lastname", 25 | "type": "string", 26 | "default": "", 27 | "pattern": "^.*$" 28 | }, 29 | "totalprice": { 30 | "$id": "#root/totalprice", 31 | "title": "Totalprice", 32 | "type": "integer", 33 | "default": 0 34 | }, 35 | "depositpaid": { 36 | "$id": "#root/depositpaid", 37 | "title": "Depositpaid", 38 | "type": "boolean", 39 | "default": true 40 | }, 41 | "bookingdates": { 42 | "$id": "#root/bookingdates", 43 | "title": "Bookingdates", 44 | "type": "object", 45 | "required": [ 46 | "checkin", 47 | "checkout" 48 | ], 49 | "properties": { 50 | "checkin": { 51 | "$id": "#root/bookingdates/checkin", 52 | "title": "Checkin", 53 | "type": "string", 54 | "default": "", 55 | "pattern": "^.*$" 56 | }, 57 | "checkout": { 58 | "$id": "#root/bookingdates/checkout", 59 | "title": "Checkout", 60 | "type": "string", 61 | "default": "", 62 | "pattern": "^.*$" 63 | } 64 | } 65 | } 66 | , 67 | "additionalneeds": { 68 | "$id": "#root/additionalneeds", 69 | "title": "Additionalneeds", 70 | "type": "string", 71 | "default": "", 72 | "pattern": "^.*$" 73 | } 74 | } 75 | } -------------------------------------------------------------------------------- /src/test/resources/schemas/createBookingSchema.json: -------------------------------------------------------------------------------- 1 | { 2 | "definitions": {}, 3 | "$schema": "http://json-schema.org/draft-07/schema#", 4 | "$id": "https://example.com/object1617473424.json", 5 | "title": "Root", 6 | "type": "object", 7 | "required": [ 8 | "bookingid", 9 | "booking" 10 | ], 11 | "properties": { 12 | "bookingid": { 13 | "$id": "#root/bookingid", 14 | "title": "Bookingid", 15 | "type": "integer", 16 | "default": 0 17 | }, 18 | "booking": { 19 | "$id": "#root/booking", 20 | "title": "Booking", 21 | "type": "object", 22 | "required": [ 23 | "firstname", 24 | "lastname", 25 | "totalprice", 26 | "depositpaid", 27 | "bookingdates", 28 | "additionalneeds" 29 | ], 30 | "properties": { 31 | "firstname": { 32 | "$id": "#root/booking/firstname", 33 | "title": "Firstname", 34 | "type": "string", 35 | "default": "", 36 | "pattern": "^.*$" 37 | }, 38 | "lastname": { 39 | "$id": "#root/booking/lastname", 40 | "title": "Lastname", 41 | "type": "string", 42 | "default": "", 43 | "pattern": "^.*$" 44 | }, 45 | "totalprice": { 46 | "$id": "#root/booking/totalprice", 47 | "title": "Totalprice", 48 | "type": "integer", 49 | "default": 0 50 | }, 51 | "depositpaid": { 52 | "$id": "#root/booking/depositpaid", 53 | "title": "Depositpaid", 54 | "type": "boolean", 55 | "default": true 56 | }, 57 | "bookingdates": { 58 | "$id": "#root/booking/bookingdates", 59 | "title": "Bookingdates", 60 | "type": "object", 61 | "required": [ 62 | "checkin", 63 | "checkout" 64 | ], 65 | "properties": { 66 | "checkin": { 67 | "$id": "#root/booking/bookingdates/checkin", 68 | "title": "Checkin", 69 | "type": "string", 70 | "default": "", 71 | "pattern": "^.*$" 72 | }, 73 | "checkout": { 74 | "$id": "#root/booking/bookingdates/checkout", 75 | "title": "Checkout", 76 | "type": "string", 77 | "default": "", 78 | "pattern": "^.*$" 79 | } 80 | } 81 | } 82 | , 83 | "additionalneeds": { 84 | "$id": "#root/booking/additionalneeds", 85 | "title": "Additionalneeds", 86 | "type": "string", 87 | "default": "", 88 | "pattern": "^.*$" 89 | } 90 | } 91 | } 92 | 93 | } 94 | } -------------------------------------------------------------------------------- /src/test/resources/schemas/userSchema.json: -------------------------------------------------------------------------------- 1 | { 2 | "definitions": {}, 3 | "$schema": "http://json-schema.org/draft-07/schema#", 4 | "$id": "http://example.com/root.json", 5 | "type": "object", 6 | "title": "The Root Schema", 7 | "required": [ 8 | "name", 9 | "job", 10 | "id", 11 | "createdAt" 12 | ], 13 | "properties": { 14 | "name": { 15 | "$id": "#/properties/name", 16 | "type": "string", 17 | "title": "The Name Schema", 18 | "default": "", 19 | "examples": [ 20 | "Tester" 21 | ], 22 | "pattern": "^(.*)$" 23 | }, 24 | "job": { 25 | "$id": "#/properties/job", 26 | "type": "string", 27 | "title": "The Job Schema", 28 | "default": "", 29 | "examples": [ 30 | "Automation" 31 | ], 32 | "pattern": "^(.*)$" 33 | }, 34 | "id": { 35 | "$id": "#/properties/id", 36 | "type": "string", 37 | "title": "The Id Schema", 38 | "default": "", 39 | "examples": [ 40 | "624" 41 | ], 42 | "pattern": "^(.*)$" 43 | }, 44 | "createdAt": { 45 | "$id": "#/properties/createdAt", 46 | "type": "string", 47 | "title": "The Createdat Schema", 48 | "default": "", 49 | "examples": [ 50 | "2019-03-08T16:34:10.744Z" 51 | ], 52 | "pattern": "^(.*)$" 53 | } 54 | } 55 | } --------------------------------------------------------------------------------