All Downloads are FREE. Search and download functionalities are using the official Maven repository.

run.smt.ktest.rest.logger.SteppedAllureLogger.kt Maven / Gradle / Ivy

package run.smt.ktest.rest.logger

import com.fasterxml.jackson.databind.JsonNode
import com.fasterxml.jackson.databind.node.TextNode
import io.restassured.response.Response
import io.restassured.specification.FilterableRequestSpecification
import org.slf4j.LoggerFactory
import run.smt.ktest.allure.attach
import run.smt.ktest.allure.step
import run.smt.ktest.json.deserialize
import run.smt.ktest.json.dump

class SteppedAllureLogger : Logger {
    companion object {
        private val logger = LoggerFactory.getLogger(SteppedAllureLogger::class.java)
    }

    override fun log(request: FilterableRequestSpecification): (Response) -> Unit {
        val requestName = "HTTP ${request.method} ${request.derivedPath} -->"
        val finishWrappingStep = step("$requestName ???")

        "request" step {
            if (!request.queryParams.isEmpty()) {
                attach("query-parameters", request.queryParams.dump(), "application/json")
            }
            val contentType = purifyContentType(request.contentType)
            val requestBody = request.getBody()
            val body: Any? = when {
                contentType?.equals("application/json", ignoreCase = true) == true -> when (requestBody) {
                    is String -> beautify(requestBody)
                    is ByteArray -> beautify(requestBody.toString(charset = Charsets.UTF_8))
                    else -> requestBody
                }
                else -> requestBody
            }
            val bodyString = requestBody?.let { body as? String ?: body.dump() }

            body?.let { attach("body", it,  contentType ?: "application/json") }

            attach("headers", request.headersString, "text/plain")
            attach("cURL", "curl -X ${request.method} '${request.uri}' ${curlHeaders(request)} ${curlBody(bodyString)}")
        }

        return { response ->
                "response" step {
                    val contentType = purifyContentType(response.contentType)
                    val bodyAsString = if (contentType?.equals("application/json", ignoreCase = true) == true) {
                        beautify(response.asString())
                    } else {
                        response.asString()
                    }
                    attach("body", bodyAsString, contentType ?: "application/json")
                    attach("headers", response.headersString, "text/plain")

                    try {
                        val developerMessageNode = (bodyAsString deserialize JsonNode::class).path("developerMessage")
                        if (response.statusCode >= 400 && developerMessageNode is TextNode) {
                            attach("stacktrace", developerMessageNode.textValue())
                        }
                    } catch (e: Exception) {
                        // never mind...
                    }
                }

                finishWrappingStep(null, "$requestName ${response.statusLine}")
            }

    }

    private fun curlBody(bodyString: String?) =
        bodyString?.let { "--data-raw '${it.replace("\'", "\\\'")}'" } ?: ""

    private fun purifyContentType(contentType: String?): String? = contentType?.replace(";.*$".toRegex(), "")

    private fun curlHeaders(request: FilterableRequestSpecification) =
        request.headers.asList().joinToString(" ") { "-H '${it.name}: ${it.value}'" }

    private val FilterableRequestSpecification.headersString
        get() = headers.joinToString("\n") { "${it.name}: ${it.value}" }

    private fun beautify(value: String) = try {
        value.deserialize().dump()
    } catch (e: Exception) {
        logger.info("Failed to beautify json due to:", e)
        value
    }

    private val Response.headersString
        get() = headers.joinToString("\n") { "${it.name}: ${it.value}" }
}




© 2015 - 2024 Weber Informatics LLC | Privacy Policy