Skip to content

Commit

Permalink
add support to custom headers on request and response (arildojr7#17)
Browse files Browse the repository at this point in the history
  • Loading branch information
arildojr7 committed Jul 6, 2023
1 parent 9bff3b9 commit 15109ef
Show file tree
Hide file tree
Showing 10 changed files with 75 additions and 37 deletions.
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
package dev.arildo.iris.mock

import dev.arildo.iris.mock.util.Method

/**
* This scope class holds everything that can be used only inside `then {}` block
*/
class InterceptedScope(method: Method, shouldIntercept: Boolean, irisMockScope: IrisMockScope) :
IrisMockCondition(method, shouldIntercept, irisMockScope)
Original file line number Diff line number Diff line change
@@ -1,9 +1,10 @@
package dev.arildo.iris.mock

import dev.arildo.iris.mock.util.Method
import okhttp3.Request

class IrisMockCondition internal constructor(
internal val method: String,
open class IrisMockCondition internal constructor(
internal val method: Method,
internal val shouldIntercept: Boolean,
internal val irisMockScope: IrisMockScope
)
Expand All @@ -12,7 +13,7 @@ internal fun IrisMockScope.createCondition(
request: Request,
contains: String,
endsWith: String,
method: String
method: Method
): IrisMockCondition {
val url = request.url().toString()
val chainMethod = request.method()
Expand All @@ -26,11 +27,11 @@ internal fun IrisMockScope.createCondition(
}

endsWith.isNotBlank() -> {
url.endsWith(endsWith, true) && chainMethod == method
url.endsWith(endsWith, true) && chainMethod == method.name
}

contains.isNotBlank() -> {
url.contains(contains, true) && chainMethod == method
url.contains(contains, true) && chainMethod == method.name
}

else -> throw IllegalArgumentException("Must provide a string to match on url")
Expand Down
23 changes: 15 additions & 8 deletions iris-mock/src/main/kotlin/dev/arildo/iris/mock/IrisMockScope.kt
Original file line number Diff line number Diff line change
Expand Up @@ -8,35 +8,42 @@ import dev.arildo.iris.mock.util.IRIS_MOCK_TAG
import dev.arildo.iris.mock.util.MEDIA_TYPE
import okhttp3.Interceptor
import okhttp3.Protocol
import okhttp3.Request
import okhttp3.Response
import okhttp3.ResponseBody
import org.jetbrains.annotations.VisibleForTesting
import java.util.logging.Logger

class IrisMockScope internal constructor(chain: Interceptor.Chain) {

private var customResponse: Response? = null
@VisibleForTesting
internal var useCustomResponse = false

internal val request: Request = chain.request()
internal val url: String = request.url().toString()
internal val customResponse = Response.Builder()
internal val customRequest = chain.request().newBuilder()
internal val url = chain.request().url().toString()

internal fun createCustomResponse(httpCode: HttpCode, body: String = "") {
customResponse = Response.Builder()
val request = customRequest.build()
useCustomResponse = true
customResponse
.code(httpCode.code)
.protocol(Protocol.HTTP_1_1)
.request(request)
.message(body)
.body(ResponseBody.create(request.body()?.contentType(), body))
.addHeader(CONTENT_TYPE, MEDIA_TYPE)
.build()
}

private fun createBlankResponse() = Response.Builder()
.request(request)
.request(customRequest.build())
.protocol(Protocol.HTTP_1_1)
.code(HttpCode.OK.code)
.message("")
.addHeader(IRIS_HEADER_KEY, IRIS_HEADER_IGNORE)
.build()

internal fun build(): Response = customResponse ?: createBlankResponse()
internal fun build(): Response =
if (useCustomResponse) customResponse.build() else createBlankResponse()

companion object {
internal val logger = Logger.getLogger(IRIS_MOCK_TAG)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,4 +2,4 @@ package dev.arildo.iris.mock.annotation

@Target(AnnotationTarget.CLASS)
@Retention(AnnotationRetention.RUNTIME)
annotation class IrisMockInterceptor // TODO assert Interceptor implementation
annotation class IrisMockInterceptor
Original file line number Diff line number Diff line change
@@ -1,8 +1,9 @@
@file:JvmMultifileClass
@file:Suppress("unused")
@file:Suppress("unused", "UnusedReceiverParameter")

package dev.arildo.iris.mock.dsl

import dev.arildo.iris.mock.InterceptedScope
import dev.arildo.iris.mock.IrisMockCondition
import dev.arildo.iris.mock.IrisMockScope
import dev.arildo.iris.mock.util.HttpCode
Expand Down Expand Up @@ -67,7 +68,7 @@ infix fun IrisMockCondition.mockResponse(response: Map<String, Any?>) {
* ```
* @param response used as response body
*/
fun IrisMockCondition.mockCustomResponse(response: Map<String, Any?>, httpCode: HttpCode = OK) {
fun IrisMockCondition.mockCustomResponse(response: Map<String, String?>, httpCode: HttpCode = OK) {
if (shouldIntercept) {
IrisMockScope.logger.info("Mocking Response: [$method] ${irisMockScope.url}")

Expand All @@ -90,8 +91,8 @@ fun IrisMockCondition.mockCustomResponse(response: Map<String, Any?>, httpCode:
* }
* ```
*/
infix fun IrisMockCondition.then(block: suspend IrisMockCondition.() -> Unit) = runBlocking(IO) {
if (shouldIntercept) block()
infix fun IrisMockCondition.then(block: suspend InterceptedScope.() -> Unit) = runBlocking(IO) {
if (shouldIntercept) block(InterceptedScope(method, shouldIntercept = true, irisMockScope))
}

/**
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
@file:JvmMultifileClass
@file:Suppress("unused", "UnusedReceiverParameter")

package dev.arildo.iris.mock.dsl

import dev.arildo.iris.mock.InterceptedScope

fun InterceptedScope.addHeaderRequest(header: Pair<String, Any?>) {
irisMockScope.customRequest.addHeader(header.first, header.second.toString())
}

fun InterceptedScope.removeHeaderRequest(headerKey: String) {
irisMockScope.customRequest.removeHeader(headerKey)
}

fun InterceptedScope.addHeaderResponse(header: Pair<String, Any?>) {
irisMockScope.customResponse.addHeader(header.first, header.second.toString())
}

fun InterceptedScope.removeHeaderResponse(headerKey: String) {
irisMockScope.customResponse.removeHeader(headerKey)
}
Original file line number Diff line number Diff line change
Expand Up @@ -5,11 +5,8 @@ package dev.arildo.iris.mock.dsl
import dev.arildo.iris.mock.IrisMockCondition
import dev.arildo.iris.mock.IrisMockScope
import dev.arildo.iris.mock.createCondition
import dev.arildo.iris.mock.util.METHOD_DELETE
import dev.arildo.iris.mock.util.METHOD_GET
import dev.arildo.iris.mock.util.METHOD_PATCH
import dev.arildo.iris.mock.util.METHOD_POST
import dev.arildo.iris.mock.util.METHOD_PUT
import dev.arildo.iris.mock.util.Method
import org.jetbrains.annotations.VisibleForTesting

/**
* Intercept GET calls when [endsWith] OR [contains] are true.
Expand All @@ -22,7 +19,7 @@ import dev.arildo.iris.mock.util.METHOD_PUT
* @return a [IrisMockCondition] to be used as receiver for DSL functions.
*/
fun IrisMockScope.onGet(endsWith: String = "", contains: String = "") =
onIntercept(endsWith, contains, METHOD_GET)
onIntercept(endsWith, contains, Method.GET)

/**
* Intercept POST calls when [endsWith] OR [contains] are true.
Expand All @@ -35,7 +32,7 @@ fun IrisMockScope.onGet(endsWith: String = "", contains: String = "") =
* @return a [IrisMockCondition] to be used as receiver for DSL functions.
*/
fun IrisMockScope.onPost(endsWith: String = "", contains: String = "") =
onIntercept(endsWith, contains, METHOD_POST)
onIntercept(endsWith, contains, Method.POST)

/**
* Intercept DELETE calls when [endsWith] OR [contains] are true.
Expand All @@ -48,7 +45,7 @@ fun IrisMockScope.onPost(endsWith: String = "", contains: String = "") =
* @return a [IrisMockCondition] to be used as receiver for DSL functions.
*/
fun IrisMockScope.onDelete(endsWith: String = "", contains: String = "") =
onIntercept(endsWith, contains, METHOD_DELETE)
onIntercept(endsWith, contains, Method.DELETE)

/**
* Intercept PUT calls when [endsWith] OR [contains] are true.
Expand All @@ -61,7 +58,7 @@ fun IrisMockScope.onDelete(endsWith: String = "", contains: String = "") =
* @return a [IrisMockCondition] to be used as receiver for DSL functions.
*/
fun IrisMockScope.onPut(endsWith: String = "", contains: String = "") =
onIntercept(endsWith, contains, METHOD_PUT)
onIntercept(endsWith, contains, Method.PUT)

/**
* Intercept PATCH calls when [endsWith] OR [contains] are true.
Expand All @@ -74,14 +71,15 @@ fun IrisMockScope.onPut(endsWith: String = "", contains: String = "") =
* @return a [IrisMockCondition] to be used as receiver for DSL functions.
*/
fun IrisMockScope.onPatch(endsWith: String = "", contains: String = "") =
onIntercept(endsWith, contains, METHOD_PATCH)
onIntercept(endsWith, contains, Method.PATCH)

private fun IrisMockScope.onIntercept(
@VisibleForTesting
internal fun IrisMockScope.onIntercept(
endsWith: String,
contains: String,
method: String
method: Method
): IrisMockCondition {
return createCondition(request, contains, endsWith, method).also {
return createCondition(customRequest.build(), contains, endsWith, method).also {
if (it.shouldIntercept) IrisMockScope.logger.info("Intercepting: [$method] $url")
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,7 @@ fun irisMockScope(
* @return true if it's included
*/
fun IrisMockScope.requestBodyContains(value: String, ignoreCase: Boolean = true): Boolean =
readRequestBody(request).contains(value, ignoreCase)
readRequestBody(customRequest.build()).contains(value, ignoreCase)

/**
* Enable logs for all calls.
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,11 +2,6 @@ package dev.arildo.iris.mock.util

internal const val MEDIA_TYPE = "application/json"
internal const val CONTENT_TYPE = "Content-Type"
internal const val METHOD_POST = "POST"
internal const val METHOD_PATCH = "PATCH"
internal const val METHOD_PUT = "PUT"
internal const val METHOD_DELETE = "DELETE"
internal const val METHOD_GET = "GET"
internal const val IRIS_HEADER_KEY = "IRIS_MOCK"
internal const val IRIS_HEADER_IGNORE = "IRIS_MOCK_IGNORE"

Expand Down
5 changes: 5 additions & 0 deletions iris-mock/src/main/kotlin/dev/arildo/iris/mock/util/Method.kt
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
package dev.arildo.iris.mock.util

enum class Method {
GET, PATCH, DELETE, PUT, POST
}

0 comments on commit 15109ef

Please sign in to comment.