mirror of
https://github.com/hmalik144/api-testing-automation-framework.git
synced 2026-03-18 07:26:17 +00:00
readme.md added
This commit is contained in:
7
src/main/kotlin/org/example/api/ApiUtils.kt
Normal file
7
src/main/kotlin/org/example/api/ApiUtils.kt
Normal file
@@ -0,0 +1,7 @@
|
||||
package org.example.api
|
||||
|
||||
import java.util.*
|
||||
|
||||
fun createBasicAuthTokenForHeader(username: String, password: String) =
|
||||
StringBuilder("Basic ").append(Base64.getEncoder().encodeToString("$username:$password".toByteArray()))
|
||||
.toString()
|
||||
@@ -36,7 +36,6 @@ class BookerApi {
|
||||
.setLenient()
|
||||
.create()
|
||||
|
||||
|
||||
private fun buildOkHttpClient(timeoutSeconds: Long = 30L): OkHttpClient {
|
||||
val builder = OkHttpClient.Builder()
|
||||
|
||||
|
||||
@@ -33,20 +33,20 @@ interface RestfulBookerApi {
|
||||
suspend fun updateBooking(
|
||||
@Path("id") id: String,
|
||||
@Body booking: BookingRequest,
|
||||
@Header("Authorization") token: String
|
||||
@Header("Authorization") basicHeaderToken: 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,
|
||||
@Header("Authorization") basicHeaderToken: String,
|
||||
@Body update: UpdateBookingRequest
|
||||
): Response<BookingResponse>
|
||||
|
||||
@DELETE("booking/{id}")
|
||||
suspend fun deleteBooking(
|
||||
@Path("id") id: String,
|
||||
@Header("Authorization") token: String
|
||||
@Header("Authorization") basicHeaderToken: String
|
||||
): Response<Any>
|
||||
}
|
||||
@@ -7,5 +7,5 @@ data class BookingResponse(
|
||||
var totalprice: Int,
|
||||
var depositpaid: Boolean,
|
||||
var bookingdates: Bookingdates,
|
||||
var additionalneeds: String
|
||||
var additionalneeds: String?
|
||||
)
|
||||
@@ -1,7 +1,7 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<Configuration status="warn">
|
||||
<Properties>
|
||||
<Property name="basePath">Classpath</Property>
|
||||
<Property name="basePath">./</Property>
|
||||
</Properties>
|
||||
<Appenders>
|
||||
<RollingFile name="fileLogger" fileName="${basePath}/app-info.html"
|
||||
|
||||
@@ -1,10 +1,16 @@
|
||||
package org.example
|
||||
|
||||
import io.github.cdimascio.dotenv.dotenv
|
||||
import kotlinx.coroutines.runBlocking
|
||||
import org.apache.logging.log4j.LogManager
|
||||
import org.apache.logging.log4j.message.MessageFormatMessage
|
||||
import retrofit2.Response
|
||||
import java.io.IOException
|
||||
|
||||
abstract class NetworkTests {
|
||||
abstract class BaseNetworkTests {
|
||||
private val logger = LogManager.getLogger(Tests::javaClass)
|
||||
|
||||
private val env by lazy { dotenv() }
|
||||
|
||||
// Call retrofit API and unwrap response or throw exception
|
||||
fun <T : Any> responseUnwrap(
|
||||
@@ -22,4 +28,8 @@ abstract class NetworkTests {
|
||||
}
|
||||
}
|
||||
|
||||
fun getStoredVariable(key: String) = env.get(key)
|
||||
|
||||
fun logMessage(logMessage: String) = logger.info(logMessage)
|
||||
fun logMessage(logMessage: MessageFormatMessage) = logger.info(logMessage)
|
||||
}
|
||||
@@ -2,26 +2,25 @@ package org.example
|
||||
|
||||
import org.example.api.BookerApi
|
||||
import org.example.api.RestfulBookerApi
|
||||
import org.example.model.AuthRequest
|
||||
import org.example.model.BookingRequest
|
||||
import org.example.model.Bookingdates
|
||||
import org.example.model.UpdateBookingRequest
|
||||
import org.apache.logging.log4j.LogManager
|
||||
import org.apache.logging.log4j.message.MessageFormatMessage
|
||||
import org.assertj.core.api.AssertionsForClassTypes.assertThat
|
||||
import org.example.api.createBasicAuthTokenForHeader
|
||||
import org.junit.jupiter.api.*
|
||||
import org.example.storage.OrdersDatabase
|
||||
import org.example.utils.FileReader
|
||||
import org.example.utils.TestHelper
|
||||
import org.example.utils.PASSWORD_KEY
|
||||
import org.example.utils.USERNAME_KEY
|
||||
import java.util.*
|
||||
|
||||
|
||||
@TestMethodOrder(MethodOrderer.OrderAnnotation::class)
|
||||
class Tests : NetworkTests() {
|
||||
class Tests : BaseNetworkTests() {
|
||||
|
||||
companion object {
|
||||
private lateinit var bookerApi: RestfulBookerApi
|
||||
private val fileReader = FileReader()
|
||||
private val logger = LogManager.getLogger(Tests::javaClass)
|
||||
private val testHelper = TestHelper()
|
||||
|
||||
private val storage = OrdersDatabase()
|
||||
|
||||
@@ -33,8 +32,8 @@ class Tests : NetworkTests() {
|
||||
internal fun beforeAll() {
|
||||
bookerApi = BookerApi().invoke()
|
||||
|
||||
bookingRequestTestOne = fileReader.readJsonFileFromResources("test1", BookingRequest::class.java)
|
||||
bookingRequestTestTwo = fileReader.readJsonFileFromResources("test2", BookingRequest::class.java)
|
||||
bookingRequestTestOne = testHelper.readJsonFileFromResources("test1", BookingRequest::class.java)
|
||||
bookingRequestTestTwo = testHelper.readJsonFileFromResources("test2", BookingRequest::class.java)
|
||||
}
|
||||
|
||||
@AfterAll
|
||||
@@ -56,17 +55,7 @@ class Tests : NetworkTests() {
|
||||
/*
|
||||
* Given
|
||||
*/
|
||||
val bookingRequestThree = BookingRequest(
|
||||
firstname = "Mark",
|
||||
lastname = "Wahlberg",
|
||||
totalprice = 750,
|
||||
depositpaid = true,
|
||||
bookingdates = Bookingdates(
|
||||
checkin = "2025-01-01",
|
||||
checkout = "2025-01-10"
|
||||
),
|
||||
additionalneeds = "Breakfast"
|
||||
)
|
||||
val bookingRequestThree = testHelper.readJsonFileFromResources("test3", BookingRequest::class.java)
|
||||
|
||||
/*
|
||||
* When
|
||||
@@ -85,17 +74,17 @@ class Tests : NetworkTests() {
|
||||
.isGreaterThanOrEqualTo(3)
|
||||
val bookingIds = bookingIdsResponse.map { it.bookingid }.joinToString()
|
||||
|
||||
logger.info("Available booking IDs: $bookingIds")
|
||||
logMessage("Available booking IDs: $bookingIds")
|
||||
|
||||
// Add the booking details and idea for later
|
||||
bookingResponses.forEach { response ->
|
||||
storage.insertBooking(response.bookingid, response.booking)
|
||||
|
||||
logger.trace(
|
||||
logMessage(
|
||||
MessageFormatMessage(
|
||||
"Booking with ID: {0} has been added: {1}",
|
||||
response.bookingid,
|
||||
response.booking
|
||||
testHelper.toJsonString(response.booking)
|
||||
)
|
||||
)
|
||||
}
|
||||
@@ -130,21 +119,11 @@ class Tests : NetworkTests() {
|
||||
/*
|
||||
* When
|
||||
*/
|
||||
val auth = responseUnwrap {
|
||||
bookerApi.createAuthToken(
|
||||
AuthRequest(
|
||||
UUID.randomUUID().toString(),
|
||||
UUID.randomUUID().toString()
|
||||
)
|
||||
)
|
||||
}
|
||||
val tokenBuilder =
|
||||
StringBuilder("Basic ").append(Base64.getEncoder().encodeToString("admin:password123".toByteArray()))
|
||||
.toString()
|
||||
val tokenBuilder = buildBasicAuthToken()
|
||||
val updateTestOneResponse = responseUnwrap {
|
||||
bookerApi.partialUpdateBooking(
|
||||
id = orderIdTestOne.toString(),
|
||||
token = tokenBuilder,
|
||||
basicHeaderToken = tokenBuilder,
|
||||
update = UpdateBookingRequest(
|
||||
totalprice = 1000
|
||||
)
|
||||
@@ -155,7 +134,7 @@ class Tests : NetworkTests() {
|
||||
val updateTestTwoResponse = responseUnwrap {
|
||||
bookerApi.partialUpdateBooking(
|
||||
id = orderIdTestTwo.toString(),
|
||||
token = tokenBuilder,
|
||||
basicHeaderToken = tokenBuilder,
|
||||
update = UpdateBookingRequest(
|
||||
totalprice = 1500
|
||||
)
|
||||
@@ -163,23 +142,22 @@ class Tests : NetworkTests() {
|
||||
}.also {
|
||||
storage.updateCompleteOrder(orderIdTestTwo, it)
|
||||
}
|
||||
val updateResponseList = listOf(updateTestOneResponse, updateTestTwoResponse)
|
||||
|
||||
/*
|
||||
* Then
|
||||
*/
|
||||
logger.info(
|
||||
logMessage(
|
||||
MessageFormatMessage(
|
||||
"Booking with ID: {0} has been updated to the following: {1}",
|
||||
orderIdTestOne,
|
||||
updateTestOneResponse
|
||||
testHelper.toJsonString(updateTestOneResponse)
|
||||
)
|
||||
)
|
||||
logger.info(
|
||||
logMessage(
|
||||
MessageFormatMessage(
|
||||
"Booking with ID: {0} has been updated to the following: {1}",
|
||||
orderIdTestTwo,
|
||||
updateTestTwoResponse
|
||||
testHelper.toJsonString(updateTestTwoResponse)
|
||||
)
|
||||
)
|
||||
}
|
||||
@@ -205,11 +183,11 @@ class Tests : NetworkTests() {
|
||||
/*
|
||||
* Then
|
||||
*/
|
||||
logger.info(
|
||||
logMessage(
|
||||
MessageFormatMessage(
|
||||
"Booking with ID: {0} has been delete and given the following response: {1}",
|
||||
idOfAny,
|
||||
deleteResponse
|
||||
testHelper.toJsonString(deleteResponse)
|
||||
)
|
||||
)
|
||||
}
|
||||
@@ -220,6 +198,7 @@ class Tests : NetworkTests() {
|
||||
/*
|
||||
* Given
|
||||
*/
|
||||
println("The log4j library will create the report in the root of the folder")
|
||||
|
||||
/*
|
||||
* When
|
||||
@@ -229,4 +208,14 @@ class Tests : NetworkTests() {
|
||||
* Then
|
||||
*/
|
||||
}
|
||||
|
||||
/**
|
||||
* build a basic header token needed for using end points like partial update
|
||||
*/
|
||||
private fun buildBasicAuthToken(): String {
|
||||
val username = getStoredVariable(USERNAME_KEY)
|
||||
val password = getStoredVariable(PASSWORD_KEY)
|
||||
|
||||
return createBasicAuthTokenForHeader(username, password)
|
||||
}
|
||||
}
|
||||
4
src/test/kotlin/org/example/utils/Constants.kt
Normal file
4
src/test/kotlin/org/example/utils/Constants.kt
Normal file
@@ -0,0 +1,4 @@
|
||||
package org.example.utils
|
||||
|
||||
const val USERNAME_KEY = "API_USERNAME"
|
||||
const val PASSWORD_KEY = "API_PASSWORD"
|
||||
@@ -2,10 +2,8 @@ package org.example.utils
|
||||
|
||||
import com.google.gson.Gson
|
||||
import java.io.BufferedReader
|
||||
import java.lang.reflect.ParameterizedType
|
||||
import kotlin.reflect.KClass
|
||||
|
||||
class FileReader {
|
||||
class TestHelper {
|
||||
|
||||
private val gson by lazy { Gson() }
|
||||
|
||||
@@ -18,4 +16,6 @@ class FileReader {
|
||||
val data = iStream.bufferedReader().use(BufferedReader::readText)
|
||||
return gson.fromJson(data, clazz)
|
||||
}
|
||||
|
||||
fun toJsonString(any: Any) = gson.toJson(any)
|
||||
}
|
||||
@@ -1,11 +1,10 @@
|
||||
{
|
||||
"firstname" : "Jim",
|
||||
"lastname" : "Brown",
|
||||
"totalprice" : 500,
|
||||
"depositpaid" : true,
|
||||
"firstname" : "Andrea",
|
||||
"lastname" : "Sims",
|
||||
"totalprice" : 1000,
|
||||
"depositpaid" : false,
|
||||
"bookingdates" : {
|
||||
"checkin" : "2025-01-01",
|
||||
"checkout" : "2025-01-10"
|
||||
},
|
||||
"additionalneeds" : "Lunch"
|
||||
}
|
||||
}
|
||||
@@ -1,11 +1,11 @@
|
||||
{
|
||||
"firstname" : "Jim",
|
||||
"lastname" : "Brown",
|
||||
"totalprice" : 500,
|
||||
"firstname" : "Mark",
|
||||
"lastname" : "Wahlberg",
|
||||
"totalprice" : 1500,
|
||||
"depositpaid" : true,
|
||||
"bookingdates" : {
|
||||
"checkin" : "2025-01-01",
|
||||
"checkout" : "2025-01-10"
|
||||
},
|
||||
"additionalneeds" : "Lunch"
|
||||
"additionalneeds" : "Lunch|Dinner"
|
||||
}
|
||||
Reference in New Issue
Block a user