mirror of
https://github.com/hmalik144/api-testing-automation-framework.git
synced 2026-03-18 07:26:17 +00:00
Tests pass but logging is still required
This commit is contained in:
@@ -1,26 +1,54 @@
|
||||
package api
|
||||
|
||||
import com.google.gson.GsonBuilder
|
||||
import okhttp3.OkHttpClient
|
||||
import java.util.concurrent.TimeUnit
|
||||
import okhttp3.logging.HttpLoggingInterceptor
|
||||
import retrofit2.Retrofit
|
||||
import retrofit2.converter.gson.GsonConverterFactory
|
||||
import java.security.SecureRandom
|
||||
import java.security.cert.CertificateException
|
||||
import java.security.cert.X509Certificate
|
||||
import java.util.concurrent.TimeUnit
|
||||
import javax.net.ssl.SSLContext
|
||||
import javax.net.ssl.TrustManager
|
||||
import javax.net.ssl.X509TrustManager
|
||||
|
||||
|
||||
class BookerApi {
|
||||
private val baseUrl = "https://restful-booker.herokuapp.com/"
|
||||
|
||||
private val loggingInterceptor = HttpLoggingInterceptor().apply {
|
||||
level = HttpLoggingInterceptor.Level.BODY
|
||||
}
|
||||
var trustAllCerts = arrayOf<TrustManager>(
|
||||
object : X509TrustManager {
|
||||
@Throws(CertificateException::class)
|
||||
override fun checkClientTrusted(chain: Array<X509Certificate?>?, authType: String?) {
|
||||
}
|
||||
|
||||
@Throws(CertificateException::class)
|
||||
override fun checkServerTrusted(chain: Array<X509Certificate?>?, authType: String?) {
|
||||
}
|
||||
|
||||
override fun getAcceptedIssuers(): Array<X509Certificate?> {
|
||||
return arrayOfNulls<X509Certificate>(0)
|
||||
}
|
||||
}
|
||||
)
|
||||
|
||||
var gson = GsonBuilder()
|
||||
.setLenient()
|
||||
.create()
|
||||
|
||||
|
||||
private fun buildOkHttpClient(timeoutSeconds: Long = 30L): OkHttpClient {
|
||||
val builder = OkHttpClient.Builder()
|
||||
|
||||
val sslContext = SSLContext.getInstance("SSL")
|
||||
sslContext.init(null, trustAllCerts, SecureRandom())
|
||||
|
||||
builder
|
||||
.addInterceptor(loggingInterceptor)
|
||||
.connectTimeout(timeoutSeconds, TimeUnit.SECONDS)
|
||||
.writeTimeout(timeoutSeconds, TimeUnit.SECONDS)
|
||||
.readTimeout(timeoutSeconds, TimeUnit.SECONDS)
|
||||
.sslSocketFactory(sslContext.socketFactory, trustAllCerts[0] as X509TrustManager)
|
||||
.hostnameVerifier { _, _ -> true }
|
||||
|
||||
return builder.build()
|
||||
}
|
||||
@@ -30,7 +58,7 @@ class BookerApi {
|
||||
return Retrofit.Builder()
|
||||
.client(okHttpClient)
|
||||
.baseUrl(baseUrl)
|
||||
.addConverterFactory(GsonConverterFactory.create())
|
||||
.addConverterFactory(GsonConverterFactory.create(gson))
|
||||
.build()
|
||||
.create(RestfulBookerApi::class.java)
|
||||
}
|
||||
|
||||
@@ -6,19 +6,15 @@ import retrofit2.http.*
|
||||
|
||||
interface RestfulBookerApi {
|
||||
|
||||
@Headers("Content-Type:application/json")
|
||||
@Headers("Content-Type:application/json", "Accept: application/json")
|
||||
@POST("auth")
|
||||
suspend fun createAuthToken(
|
||||
@Field("username") username: String,
|
||||
@Field("password") password: String,
|
||||
@Body authRequest: AuthRequest
|
||||
): 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}")
|
||||
@@ -26,7 +22,7 @@ interface RestfulBookerApi {
|
||||
@Path("id") id: String
|
||||
): Response<BookingResponse>
|
||||
|
||||
@Headers("Content-Type:application/json")
|
||||
@Headers("Content-Type:application/json", "Accept: application/json")
|
||||
@POST("booking")
|
||||
suspend fun createBooking(
|
||||
@Body booking: BookingRequest,
|
||||
@@ -45,17 +41,12 @@ interface RestfulBookerApi {
|
||||
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
|
||||
@Body update: UpdateBookingRequest
|
||||
): Response<BookingResponse>
|
||||
|
||||
@DELETE("booking/{id}")
|
||||
suspend fun deleteBooking(
|
||||
@Path("id") id: String
|
||||
@Path("id") id: String,
|
||||
@Header("Authorization") token: String
|
||||
): Response<Any>
|
||||
}
|
||||
6
src/main/kotlin/model/AuthRequest.kt
Normal file
6
src/main/kotlin/model/AuthRequest.kt
Normal file
@@ -0,0 +1,6 @@
|
||||
package model
|
||||
|
||||
data class AuthRequest(
|
||||
val username: String,
|
||||
val password: String
|
||||
)
|
||||
@@ -1,5 +1,5 @@
|
||||
package model
|
||||
|
||||
class AuthResponse {
|
||||
var token: String? = null
|
||||
}
|
||||
data class AuthResponse (
|
||||
val token: String
|
||||
)
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
package model
|
||||
|
||||
class BookingIdResponse {
|
||||
var bookingid = 0
|
||||
}
|
||||
data class BookingIdResponse(
|
||||
val bookingid: Int
|
||||
)
|
||||
|
||||
@@ -1,12 +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,
|
||||
var firstname: String,
|
||||
var lastname: String,
|
||||
var totalprice: Int,
|
||||
var depositpaid: Boolean,
|
||||
var bookingdates: Bookingdates,
|
||||
var additionalneeds: String,
|
||||
)
|
||||
|
||||
|
||||
|
||||
@@ -1,11 +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
|
||||
data class BookingResponse(
|
||||
var firstname: String,
|
||||
var lastname: String,
|
||||
var totalprice: Int,
|
||||
var depositpaid: Boolean,
|
||||
var bookingdates: Bookingdates,
|
||||
var additionalneeds: String
|
||||
)
|
||||
@@ -1,6 +1,6 @@
|
||||
package model
|
||||
|
||||
data class Bookingdates (
|
||||
var checkin: String? = null,
|
||||
var checkout: String? = null,
|
||||
var checkin: String,
|
||||
var checkout: String,
|
||||
)
|
||||
@@ -1,6 +1,6 @@
|
||||
package model
|
||||
|
||||
class CreateBookingResponse {
|
||||
var bookingid = 0
|
||||
var booking: BookingResponse? = null
|
||||
}
|
||||
data class CreateBookingResponse(
|
||||
var bookingid: Int,
|
||||
var booking: BookingResponse
|
||||
)
|
||||
10
src/main/kotlin/model/UpdateBookingRequest.kt
Normal file
10
src/main/kotlin/model/UpdateBookingRequest.kt
Normal file
@@ -0,0 +1,10 @@
|
||||
package model
|
||||
|
||||
data class UpdateBookingRequest(
|
||||
var firstname: String? = null,
|
||||
var lastname: String? = null,
|
||||
var totalprice: Int? = null,
|
||||
var depositpaid: Boolean? = null,
|
||||
var bookingdates: Bookingdates? = null,
|
||||
var additionalneeds: String? = null,
|
||||
)
|
||||
92
src/main/kotlin/storage/OrdersDatabase.kt
Normal file
92
src/main/kotlin/storage/OrdersDatabase.kt
Normal file
@@ -0,0 +1,92 @@
|
||||
package storage
|
||||
|
||||
import model.BookingResponse
|
||||
import model.Bookingdates
|
||||
|
||||
class OrdersDatabase {
|
||||
private val storage = mutableMapOf<Int, BookingResponse>()
|
||||
|
||||
// Create
|
||||
fun insertBooking(id: Int, booking: BookingResponse) {
|
||||
if (storage.contains(id)) {
|
||||
storage.replace(id, booking)
|
||||
} else {
|
||||
storage[id] = booking
|
||||
}
|
||||
}
|
||||
|
||||
// Read
|
||||
fun getIdsOfBookingsAvailable() = storage.keys.toList()
|
||||
fun getBookingsAvailable() = storage.values.toList()
|
||||
fun getIdsAndBookings() = storage.toMap()
|
||||
|
||||
fun getIdsOfOrderBasedOnValues(
|
||||
firstname: String? = null,
|
||||
lastname: String? = null,
|
||||
totalprice: Int? = null,
|
||||
depositpaid: Boolean? = null,
|
||||
checkin: String? = null,
|
||||
checkout: String? = null,
|
||||
additionalneeds: String? = null
|
||||
): List<Int> {
|
||||
return storage.filterValues {
|
||||
firstname?.let { f -> f == it.firstname } ?: true &&
|
||||
lastname?.let { f -> f == it.lastname } ?: true &&
|
||||
totalprice?.let { f -> f == it.totalprice } ?: true &&
|
||||
depositpaid?.let { f -> f == it.depositpaid } ?: true &&
|
||||
checkin?.let { f -> f == it.bookingdates.checkin } ?: true &&
|
||||
checkout?.let { f -> f == it.bookingdates.checkout } ?: true &&
|
||||
additionalneeds?.let { f -> f == it.additionalneeds } ?: true
|
||||
}.keys.toList()
|
||||
}
|
||||
|
||||
fun getIdsOfOrderBasedOnValues(
|
||||
id: Int
|
||||
): BookingResponse? {
|
||||
return storage[id]
|
||||
}
|
||||
|
||||
// Update
|
||||
fun updateCompleteOrder(id: Int, newBookingResponse: BookingResponse) {
|
||||
insertBooking(id, newBookingResponse)
|
||||
}
|
||||
|
||||
fun updateOrderPartial(
|
||||
id: Int,
|
||||
firstname: String? = null,
|
||||
lastname: String? = null,
|
||||
totalprice: Int? = null,
|
||||
depositpaid: Boolean? = null,
|
||||
checkin: String? = null,
|
||||
checkout: String? = null,
|
||||
additionalneeds: String? = null
|
||||
) {
|
||||
if (storage.keys.remove(id)) {
|
||||
storage.compute(id) { k, v ->
|
||||
val mFirstName = firstname ?: v!!.firstname
|
||||
val mlastname = lastname ?: v!!.lastname
|
||||
val mTotalprice = totalprice ?: v!!.totalprice
|
||||
val mDepositpaid = depositpaid ?: v!!.depositpaid
|
||||
val mCheckin = checkin ?: v!!.bookingdates.checkin
|
||||
val mCheckout = checkout ?: v!!.bookingdates.checkout
|
||||
val mAdditionalneeds = additionalneeds ?: v!!.additionalneeds
|
||||
BookingResponse(
|
||||
firstname = mFirstName,
|
||||
lastname = mlastname,
|
||||
totalprice = mTotalprice,
|
||||
depositpaid = mDepositpaid,
|
||||
bookingdates = Bookingdates(
|
||||
checkin = mCheckin,
|
||||
checkout = mCheckout
|
||||
),
|
||||
additionalneeds = mAdditionalneeds
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Delete
|
||||
fun clearAllData() = storage.clear()
|
||||
|
||||
fun deleteSingleEntry(id: Int) = storage.remove(id)
|
||||
}
|
||||
27
src/main/resources/Log4j2.xml
Normal file
27
src/main/resources/Log4j2.xml
Normal file
@@ -0,0 +1,27 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<Configuration status="warn">
|
||||
<Properties>
|
||||
<Property name="basePath">C:\\logs</Property>
|
||||
</Properties>
|
||||
<Appenders>
|
||||
<RollingFile name="fileLogger" fileName="${basePath}/app-info.html"
|
||||
filePattern="${basePath}/app-info-%d{yyyy-MM-dd}.html">
|
||||
<HTMLLayout charset="UTF-8" title="Howtodoinjava Info Logs" locationInfo="true" />
|
||||
<Policies>
|
||||
<TimeBasedTriggeringPolicy interval="1" modulate="true" />
|
||||
<SizeBasedTriggeringPolicy size="10 MB" />
|
||||
</Policies>
|
||||
</RollingFile>
|
||||
<Console name="console" target="SYSTEM_OUT">
|
||||
<PatternLayout pattern="[%-5level] %d{yyyy-MM-dd HH:mm:ss.SSS} [%t] %c{1} - %msg%n" />
|
||||
</Console>
|
||||
</Appenders>
|
||||
<Loggers>
|
||||
<Logger name="com.howtodoinjava" level="debug" additivity="false">
|
||||
<appender-ref ref="fileLogger" level="debug" />
|
||||
</Logger>
|
||||
<Root level="debug" additivity="false">
|
||||
<appender-ref ref="console" />
|
||||
</Root>
|
||||
</Loggers>
|
||||
</Configuration>
|
||||
Reference in New Issue
Block a user