mirror of
https://github.com/hmalik144/api-testing-automation-framework.git
synced 2025-12-10 02:55:21 +00:00
Initial commit
- Retrofit used to call API
This commit is contained in:
38
.gitignore
vendored
Normal file
38
.gitignore
vendored
Normal file
@@ -0,0 +1,38 @@
|
||||
target/
|
||||
!.mvn/wrapper/maven-wrapper.jar
|
||||
!**/src/main/**/target/
|
||||
!**/src/test/**/target/
|
||||
|
||||
### IntelliJ IDEA ###
|
||||
.idea/modules.xml
|
||||
.idea/jarRepositories.xml
|
||||
.idea/compiler.xml
|
||||
.idea/libraries/
|
||||
*.iws
|
||||
*.iml
|
||||
*.ipr
|
||||
|
||||
### Eclipse ###
|
||||
.apt_generated
|
||||
.classpath
|
||||
.factorypath
|
||||
.project
|
||||
.settings
|
||||
.springBeans
|
||||
.sts4-cache
|
||||
|
||||
### NetBeans ###
|
||||
/nbproject/private/
|
||||
/nbbuild/
|
||||
/dist/
|
||||
/nbdist/
|
||||
/.nb-gradle/
|
||||
build/
|
||||
!**/src/main/**/build/
|
||||
!**/src/test/**/build/
|
||||
|
||||
### VS Code ###
|
||||
.vscode/
|
||||
|
||||
### Mac OS ###
|
||||
.DS_Store
|
||||
3
.idea/.gitignore
generated
vendored
Normal file
3
.idea/.gitignore
generated
vendored
Normal file
@@ -0,0 +1,3 @@
|
||||
# Default ignored files
|
||||
/shelf/
|
||||
/workspace.xml
|
||||
7
.idea/encodings.xml
generated
Normal file
7
.idea/encodings.xml
generated
Normal file
@@ -0,0 +1,7 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<project version="4">
|
||||
<component name="Encoding">
|
||||
<file url="file://$PROJECT_DIR$/src/main/kotlin" charset="UTF-8" />
|
||||
<file url="file://$PROJECT_DIR$/src/main/resources" charset="UTF-8" />
|
||||
</component>
|
||||
</project>
|
||||
6
.idea/inspectionProfiles/Project_Default.xml
generated
Normal file
6
.idea/inspectionProfiles/Project_Default.xml
generated
Normal file
@@ -0,0 +1,6 @@
|
||||
<component name="InspectionProjectProfileManager">
|
||||
<profile version="1.0">
|
||||
<option name="myName" value="Project Default" />
|
||||
<inspection_tool class="ReplaceUntilWithRangeUntil" enabled="true" level="WEAK WARNING" enabled_by_default="true" />
|
||||
</profile>
|
||||
</component>
|
||||
6
.idea/kotlinc.xml
generated
Normal file
6
.idea/kotlinc.xml
generated
Normal file
@@ -0,0 +1,6 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<project version="4">
|
||||
<component name="KotlinJpsPluginSettings">
|
||||
<option name="version" value="1.9.0" />
|
||||
</component>
|
||||
</project>
|
||||
14
.idea/misc.xml
generated
Normal file
14
.idea/misc.xml
generated
Normal file
@@ -0,0 +1,14 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<project version="4">
|
||||
<component name="ExternalStorageConfigurationManager" enabled="true" />
|
||||
<component name="MavenProjectsManager">
|
||||
<option name="originalFiles">
|
||||
<list>
|
||||
<option value="$PROJECT_DIR$/pom.xml" />
|
||||
</list>
|
||||
</option>
|
||||
</component>
|
||||
<component name="ProjectRootManager" version="2" languageLevel="JDK_20" default="true" project-jdk-name="20" project-jdk-type="JavaSDK">
|
||||
<output url="file://$PROJECT_DIR$/out" />
|
||||
</component>
|
||||
</project>
|
||||
149
pom.xml
Normal file
149
pom.xml
Normal file
@@ -0,0 +1,149 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<project xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
|
||||
xmlns="http://maven.apache.org/POM/4.0.0"
|
||||
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
|
||||
<modelVersion>4.0.0</modelVersion>
|
||||
|
||||
<artifactId>api-testing-automation-framework</artifactId>
|
||||
<groupId>org.example</groupId>
|
||||
<version>1.0-SNAPSHOT</version>
|
||||
<packaging>jar</packaging>
|
||||
|
||||
<name>consoleApp</name>
|
||||
|
||||
<properties>
|
||||
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
|
||||
<kotlin.code.style>official</kotlin.code.style>
|
||||
<kotlin.compiler.jvmTarget>1.8</kotlin.compiler.jvmTarget>
|
||||
</properties>
|
||||
|
||||
<repositories>
|
||||
<repository>
|
||||
<id>mavenCentral</id>
|
||||
<url>https://repo1.maven.org/maven2/</url>
|
||||
</repository>
|
||||
</repositories>
|
||||
|
||||
<build>
|
||||
<sourceDirectory>src/main/kotlin</sourceDirectory>
|
||||
<testSourceDirectory>src/test/kotlin</testSourceDirectory>
|
||||
<plugins>
|
||||
<plugin>
|
||||
<groupId>org.jetbrains.kotlin</groupId>
|
||||
<artifactId>kotlin-maven-plugin</artifactId>
|
||||
<version>1.9.0</version>
|
||||
<executions>
|
||||
<execution>
|
||||
<id>compile</id>
|
||||
<phase>compile</phase>
|
||||
<goals>
|
||||
<goal>compile</goal>
|
||||
</goals>
|
||||
</execution>
|
||||
<execution>
|
||||
<id>test-compile</id>
|
||||
<phase>test-compile</phase>
|
||||
<goals>
|
||||
<goal>test-compile</goal>
|
||||
</goals>
|
||||
</execution>
|
||||
</executions>
|
||||
</plugin>
|
||||
<plugin>
|
||||
<artifactId>maven-surefire-plugin</artifactId>
|
||||
<version>2.22.2</version>
|
||||
</plugin>
|
||||
<plugin>
|
||||
<artifactId>maven-failsafe-plugin</artifactId>
|
||||
<version>2.22.2</version>
|
||||
</plugin>
|
||||
<plugin>
|
||||
<groupId>org.codehaus.mojo</groupId>
|
||||
<artifactId>exec-maven-plugin</artifactId>
|
||||
<version>1.6.0</version>
|
||||
<configuration>
|
||||
<mainClass>MainKt</mainClass>
|
||||
</configuration>
|
||||
</plugin>
|
||||
</plugins>
|
||||
</build>
|
||||
|
||||
<dependencies>
|
||||
<dependency>
|
||||
<groupId>org.jetbrains.kotlin</groupId>
|
||||
<artifactId>kotlin-test-junit5</artifactId>
|
||||
<version>1.9.0</version>
|
||||
<scope>test</scope>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.junit.jupiter</groupId>
|
||||
<artifactId>junit-jupiter-engine</artifactId>
|
||||
<version>5.10.0</version>
|
||||
<scope>test</scope>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.jetbrains.kotlin</groupId>
|
||||
<artifactId>kotlin-stdlib</artifactId>
|
||||
<version>1.9.0</version>
|
||||
</dependency>
|
||||
<!-- https://mvnrepository.com/artifact/io.rest-assured/rest-assured -->
|
||||
<dependency>
|
||||
<groupId>io.rest-assured</groupId>
|
||||
<artifactId>rest-assured</artifactId>
|
||||
<version>5.5.0</version>
|
||||
<scope>test</scope>
|
||||
</dependency>
|
||||
<!-- jUnit -->
|
||||
<dependency>
|
||||
<groupId>org.junit.jupiter</groupId>
|
||||
<artifactId>junit-jupiter-params</artifactId>
|
||||
<version>5.0.0</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>junit</groupId>
|
||||
<artifactId>junit</artifactId>
|
||||
<version>4.12</version>
|
||||
<scope>compile</scope>
|
||||
</dependency>
|
||||
<!-- https://mvnrepository.com/artifact/com.squareup.retrofit2/retrofit -->
|
||||
<dependency>
|
||||
<groupId>com.squareup.retrofit2</groupId>
|
||||
<artifactId>retrofit</artifactId>
|
||||
<version>2.11.0</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>com.squareup.okhttp3</groupId>
|
||||
<artifactId>logging-interceptor</artifactId>
|
||||
<version>4.12.0</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.example</groupId>
|
||||
<artifactId>api-testing-automation-framework</artifactId>
|
||||
<version>1.0-SNAPSHOT</version>
|
||||
</dependency>
|
||||
<!-- https://mvnrepository.com/artifact/com.squareup.retrofit2/converter-gson -->
|
||||
<dependency>
|
||||
<groupId>com.squareup.retrofit2</groupId>
|
||||
<artifactId>converter-gson</artifactId>
|
||||
<version>2.11.0</version>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>org.jetbrains.kotlinx</groupId>
|
||||
<artifactId>kotlinx-coroutines-core</artifactId>
|
||||
<version>1.6.2</version>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>org.apache.logging.log4j</groupId>
|
||||
<artifactId>log4j-core</artifactId>
|
||||
<version>2.19.0</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.apache.logging.log4j</groupId>
|
||||
<artifactId>log4j-api</artifactId>
|
||||
<version>2.19.0</version>
|
||||
</dependency>
|
||||
</dependencies>
|
||||
|
||||
</project>
|
||||
37
src/main/kotlin/api/BookerApi.kt
Normal file
37
src/main/kotlin/api/BookerApi.kt
Normal file
@@ -0,0 +1,37 @@
|
||||
package api
|
||||
|
||||
import okhttp3.OkHttpClient
|
||||
import java.util.concurrent.TimeUnit
|
||||
import okhttp3.logging.HttpLoggingInterceptor
|
||||
import retrofit2.Retrofit
|
||||
import retrofit2.converter.gson.GsonConverterFactory
|
||||
|
||||
class BookerApi {
|
||||
private val baseUrl = "https://restful-booker.herokuapp.com/"
|
||||
|
||||
private val loggingInterceptor = HttpLoggingInterceptor().apply {
|
||||
level = HttpLoggingInterceptor.Level.BODY
|
||||
}
|
||||
|
||||
private fun buildOkHttpClient(timeoutSeconds: Long = 30L): OkHttpClient {
|
||||
val builder = OkHttpClient.Builder()
|
||||
|
||||
builder
|
||||
.addInterceptor(loggingInterceptor)
|
||||
.connectTimeout(timeoutSeconds, TimeUnit.SECONDS)
|
||||
.writeTimeout(timeoutSeconds, TimeUnit.SECONDS)
|
||||
.readTimeout(timeoutSeconds, TimeUnit.SECONDS)
|
||||
|
||||
return builder.build()
|
||||
}
|
||||
|
||||
fun invoke(): RestfulBookerApi {
|
||||
val okHttpClient = buildOkHttpClient()
|
||||
return Retrofit.Builder()
|
||||
.client(okHttpClient)
|
||||
.baseUrl(baseUrl)
|
||||
.addConverterFactory(GsonConverterFactory.create())
|
||||
.build()
|
||||
.create(RestfulBookerApi::class.java)
|
||||
}
|
||||
}
|
||||
61
src/main/kotlin/api/RestfulBookerApi.kt
Normal file
61
src/main/kotlin/api/RestfulBookerApi.kt
Normal file
@@ -0,0 +1,61 @@
|
||||
package api
|
||||
|
||||
import model.*
|
||||
import retrofit2.Response
|
||||
import retrofit2.http.*
|
||||
|
||||
interface RestfulBookerApi {
|
||||
|
||||
@Headers("Content-Type:application/json")
|
||||
@POST("auth")
|
||||
suspend fun createAuthToken(
|
||||
@Field("username") username: String,
|
||||
@Field("password") password: String,
|
||||
): Response<AuthResponse>
|
||||
|
||||
@GET("booking")
|
||||
suspend fun getBookingIds(
|
||||
@Field("firstname") firstname: String? = null,
|
||||
@Field("lastname") lastname: String? = null,
|
||||
@Field("checkin") checkin: String? = null,
|
||||
@Field("checkout") checkout: String? = null,
|
||||
): Response<List<BookingIdResponse>>
|
||||
|
||||
@GET("booking/{id}")
|
||||
suspend fun getSingleBooking(
|
||||
@Path("id") id: String
|
||||
): Response<BookingResponse>
|
||||
|
||||
@Headers("Content-Type:application/json")
|
||||
@POST("booking")
|
||||
suspend fun createBooking(
|
||||
@Body booking: BookingRequest,
|
||||
): Response<CreateBookingResponse>
|
||||
|
||||
@Headers("Content-Type:application/json", "Accept: application/json")
|
||||
@PUT("booking/{id}")
|
||||
suspend fun updateBooking(
|
||||
@Path("id") id: String,
|
||||
@Body booking: BookingRequest,
|
||||
@Header("Authorization") token: String
|
||||
): Response<BookingResponse>
|
||||
|
||||
@Headers("Content-Type:application/json", "Accept: application/json")
|
||||
@PATCH("booking/{id}")
|
||||
suspend fun partialUpdateBooking(
|
||||
@Path("id") id: String,
|
||||
@Header("Authorization") token: String,
|
||||
@Field("firstname") firstname: String? = null,
|
||||
@Field("lastname") lastname: String? = null,
|
||||
@Field("totalprice") totalprice: Float? = null,
|
||||
@Field("depositpaid") depositpaid: Boolean? = null,
|
||||
@Field("checkin") checkin: String? = null,
|
||||
@Field("checkout") checkout: String? = null,
|
||||
@Field("additionalneeds") additionalneeds: String? = null
|
||||
): Response<BookingResponse>
|
||||
|
||||
@DELETE("booking/{id}")
|
||||
suspend fun deleteBooking(
|
||||
@Path("id") id: String
|
||||
): Response<Any>
|
||||
}
|
||||
5
src/main/kotlin/model/AuthResponse.kt
Normal file
5
src/main/kotlin/model/AuthResponse.kt
Normal file
@@ -0,0 +1,5 @@
|
||||
package model
|
||||
|
||||
class AuthResponse {
|
||||
var token: String? = null
|
||||
}
|
||||
5
src/main/kotlin/model/BookingIdResponse.kt
Normal file
5
src/main/kotlin/model/BookingIdResponse.kt
Normal file
@@ -0,0 +1,5 @@
|
||||
package model
|
||||
|
||||
class BookingIdResponse {
|
||||
var bookingid = 0
|
||||
}
|
||||
12
src/main/kotlin/model/BookingRequest.kt
Normal file
12
src/main/kotlin/model/BookingRequest.kt
Normal file
@@ -0,0 +1,12 @@
|
||||
package model
|
||||
|
||||
data class BookingRequest (
|
||||
var firstname: String? = null,
|
||||
var lastname: String? = null,
|
||||
var totalprice: Int = 0,
|
||||
var depositpaid: Boolean = false,
|
||||
var bookingdates: Bookingdates? = null,
|
||||
var additionalneeds: String? = null,
|
||||
)
|
||||
|
||||
|
||||
11
src/main/kotlin/model/BookingResponse.kt
Normal file
11
src/main/kotlin/model/BookingResponse.kt
Normal file
@@ -0,0 +1,11 @@
|
||||
package model
|
||||
|
||||
|
||||
data class BookingResponse (
|
||||
var firstname: String? = null,
|
||||
var lastname: String? = null,
|
||||
var totalprice: Int = 0,
|
||||
var depositpaid: Boolean = false,
|
||||
var bookingdates: Bookingdates? = null,
|
||||
var additionalneeds: String? = null
|
||||
)
|
||||
6
src/main/kotlin/model/Bookingdates.kt
Normal file
6
src/main/kotlin/model/Bookingdates.kt
Normal file
@@ -0,0 +1,6 @@
|
||||
package model
|
||||
|
||||
data class Bookingdates (
|
||||
var checkin: String? = null,
|
||||
var checkout: String? = null,
|
||||
)
|
||||
6
src/main/kotlin/model/CreateBookingResponse.kt
Normal file
6
src/main/kotlin/model/CreateBookingResponse.kt
Normal file
@@ -0,0 +1,6 @@
|
||||
package model
|
||||
|
||||
class CreateBookingResponse {
|
||||
var bookingid = 0
|
||||
var booking: BookingResponse? = null
|
||||
}
|
||||
20
src/test/kotlin/NetworkTests.kt
Normal file
20
src/test/kotlin/NetworkTests.kt
Normal file
@@ -0,0 +1,20 @@
|
||||
import kotlinx.coroutines.runBlocking
|
||||
import retrofit2.Response
|
||||
import java.io.IOException
|
||||
|
||||
abstract class NetworkTests {
|
||||
|
||||
fun <T : Any> responseUnwrap(
|
||||
call: suspend () -> Response<T>
|
||||
): T {
|
||||
|
||||
val response = runBlocking { call.invoke() }
|
||||
if (response.isSuccessful) {
|
||||
return response.body()!!
|
||||
} else {
|
||||
val error = response.errorBody()?.string()
|
||||
|
||||
throw IOException(error ?: "Unable to handle end point")
|
||||
}
|
||||
}
|
||||
}
|
||||
105
src/test/kotlin/Tests.kt
Normal file
105
src/test/kotlin/Tests.kt
Normal file
@@ -0,0 +1,105 @@
|
||||
import api.BookerApi
|
||||
import api.RestfulBookerApi
|
||||
import io.restassured.RestAssured.given
|
||||
import kotlinx.coroutines.runBlocking
|
||||
import model.BookingRequest
|
||||
import model.Bookingdates
|
||||
import org.apache.logging.log4j.LogManager
|
||||
import org.junit.FixMethodOrder
|
||||
import org.junit.jupiter.api.AfterAll
|
||||
import org.junit.jupiter.api.BeforeAll
|
||||
import org.junit.jupiter.api.Test
|
||||
import org.junit.runners.MethodSorters
|
||||
import utils.FileReader
|
||||
|
||||
@FixMethodOrder(MethodSorters.DEFAULT)
|
||||
class Tests : NetworkTests(){
|
||||
|
||||
companion object {
|
||||
private lateinit var bookerApi: RestfulBookerApi
|
||||
private lateinit var fileReader: FileReader
|
||||
private val logger = LogManager.getLogger(Tests::class.java)
|
||||
|
||||
@BeforeAll
|
||||
@JvmStatic
|
||||
internal fun beforeAll() {
|
||||
bookerApi = BookerApi().invoke()
|
||||
}
|
||||
|
||||
@AfterAll
|
||||
@JvmStatic
|
||||
internal fun afterAll() {
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* 1. Generate 3 new bookings --> Log below scenarios to a log file
|
||||
* o All available booking ID's
|
||||
* o Above added 3 new booking details
|
||||
*/
|
||||
@Test()
|
||||
fun testScenarioOne() {
|
||||
// Given
|
||||
val bookingRequestOne = fileReader.readJsonFileFromResources<BookingRequest>("test1")
|
||||
val bookingRequestTwo = fileReader.readJsonFileFromResources<BookingRequest>("test2")
|
||||
val bookingRequestThree = BookingRequest(
|
||||
firstname = "Mark",
|
||||
lastname = "Wahlberg",
|
||||
totalprice = 750,
|
||||
depositpaid = true,
|
||||
bookingdates = Bookingdates(
|
||||
checkin = "2025-01-01",
|
||||
checkout = "2025-01-10"
|
||||
),
|
||||
additionalneeds = "Breakfast"
|
||||
)
|
||||
|
||||
// When
|
||||
val createBookingOneResponse = responseUnwrap { bookerApi.createBooking(bookingRequestOne) }
|
||||
val createBookingTwoResponse = responseUnwrap { bookerApi.createBooking(bookingRequestTwo) }
|
||||
val createBookingThreeResponse = responseUnwrap { bookerApi.createBooking(bookingRequestThree) }
|
||||
|
||||
// Then
|
||||
val bookingIds = responseUnwrap { bookerApi.getBookingIds() }
|
||||
logger.trace("Available booking IDs: ${bookingIds.joinToString()}")
|
||||
bookingIds.forEach {
|
||||
val currentBookingResponse = responseUnwrap { bookerApi.getSingleBooking("$it") }
|
||||
logger.trace(currentBookingResponse)
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 2. Modify total price for test1 to 1000 and test2 to 1500. Log this data to same log file.
|
||||
* Test data :
|
||||
* • Test1 with total price 500 who deposit is paid with random check in and checkout dates and having preference of lunch as additional need.
|
||||
*
|
||||
*/
|
||||
@Test()
|
||||
fun testScenarioTwo() {
|
||||
// Given
|
||||
|
||||
// When
|
||||
|
||||
// Then
|
||||
}
|
||||
|
||||
@Test()
|
||||
fun testScenarioThree() {
|
||||
// Given
|
||||
|
||||
// When
|
||||
|
||||
// Then
|
||||
}
|
||||
|
||||
@Test()
|
||||
fun testScenarioFour() {
|
||||
// Given
|
||||
|
||||
// When
|
||||
|
||||
// Then
|
||||
}
|
||||
}
|
||||
21
src/test/kotlin/utils/FileReader.kt
Normal file
21
src/test/kotlin/utils/FileReader.kt
Normal file
@@ -0,0 +1,21 @@
|
||||
package utils
|
||||
|
||||
import com.google.gson.Gson
|
||||
import java.io.BufferedReader
|
||||
import java.lang.reflect.ParameterizedType
|
||||
|
||||
class FileReader {
|
||||
|
||||
private val gson by lazy { Gson() }
|
||||
|
||||
fun <T : Any?> readJsonFileFromResources(fileName: String): T {
|
||||
val iStream = this::class.java.getResourceAsStream("$fileName.json")
|
||||
?: throw IllegalStateException("Unable to read the file requested")
|
||||
val data = iStream.bufferedReader().use(BufferedReader::readText)
|
||||
val genericType = ((javaClass.genericSuperclass as? ParameterizedType)
|
||||
?.actualTypeArguments?.getOrNull(0) as? Class<T>)
|
||||
?: throw IllegalStateException("Can not find class from generic argument")
|
||||
|
||||
return gson.fromJson(data, genericType)
|
||||
}
|
||||
}
|
||||
11
src/test/resources/test1.json
Normal file
11
src/test/resources/test1.json
Normal file
@@ -0,0 +1,11 @@
|
||||
{
|
||||
"firstname" : "Jim",
|
||||
"lastname" : "Brown",
|
||||
"totalprice" : 500,
|
||||
"depositpaid" : true,
|
||||
"bookingdates" : {
|
||||
"checkin" : "2025-01-01",
|
||||
"checkout" : "2025-01-10"
|
||||
},
|
||||
"additionalneeds" : "Lunch"
|
||||
}
|
||||
11
src/test/resources/test2.json
Normal file
11
src/test/resources/test2.json
Normal file
@@ -0,0 +1,11 @@
|
||||
{
|
||||
"firstname" : "Jim",
|
||||
"lastname" : "Brown",
|
||||
"totalprice" : 500,
|
||||
"depositpaid" : true,
|
||||
"bookingdates" : {
|
||||
"checkin" : "2025-01-01",
|
||||
"checkout" : "2025-01-10"
|
||||
},
|
||||
"additionalneeds" : "Lunch"
|
||||
}
|
||||
Reference in New Issue
Block a user