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

io.specmatic.conversions.ExampleFromFile.kt Maven / Gradle / Ivy

Go to download

Turn your contracts into executable specifications. Contract Driven Development - Collaboratively Design & Independently Deploy MicroServices & MicroFrontends.

There is a newer version: 2.0.37
Show newest version
package io.specmatic.conversions

import io.specmatic.core.HttpRequest
import io.specmatic.core.HttpResponse
import io.specmatic.core.NoBodyValue
import io.specmatic.core.QueryParameters
import io.specmatic.core.SpecmaticConfig
import io.specmatic.core.log.logger
import io.specmatic.core.pattern.*
import io.specmatic.core.utilities.URIUtils.parseQuery
import io.specmatic.core.value.EmptyString
import io.specmatic.core.value.JSONObjectValue
import io.specmatic.core.value.Value
import io.specmatic.mock.mockFromJSON
import io.specmatic.stub.httpResponseLog
import java.io.File
import java.net.URI

class ExampleFromFile(val json: JSONObjectValue, val file: File) {
    fun toRow(specmaticConfig: SpecmaticConfig = SpecmaticConfig()): Row {
        logger.log("Loading test file ${this.expectationFilePath}")

        val examples: Map =
            headers
                .plus(queryParams)
                .plus(requestBody?.let { mapOf("(REQUEST-BODY)" to it.toStringLiteral()) } ?: emptyMap())

        val (
            columnNames,
            values
        ) = examples.entries.let { entry ->
            entry.map { it.key } to entry.map { it.value }
        }

        val responseExample: ResponseExample? = response?.let { httpResponse ->
            when {
                specmaticConfig.isResponseValueValidationEnabled() ->
                    ResponseValueExample(httpResponse)

                else ->
                    null
            }

        }

        val mockFromJSON = mockFromJSON(json.jsonObject)

        return Row(
            columnNames,
            values,
            name = testName,
            fileSource = this.file.canonicalPath,
            responseExampleForValidation = responseExample,
            requestExample = mockFromJSON.request,
            responseExample = response
        )
    }

    constructor(file: File) : this(parsedJSONObject(file.readText()), file)

    val expectationFilePath: String = file.canonicalPath

    val response: HttpResponse
        get() {
            if(responseBody == null && responseHeaders == null)
                return HttpResponse(
                    responseStatus,
                    body = NoBodyValue,
                    headers = emptyMap()
                )

            val body = responseBody ?: EmptyString
            val headers = responseHeaders ?: JSONObjectValue()

            return HttpResponse(responseStatus, headers.jsonObject.mapValues { it.value.toStringLiteral() }, body)
        }

    val request: HttpRequest
        get() {
            return HttpRequest(
                method = requestMethod,
                path = requestPath,
                headers = headers,
                body = requestBody ?: NoBodyValue,
                queryParams = QueryParameters(queryParams),
            )
        }

    val responseBody: Value? = attempt("Error reading response body in file ${file.parentFile.canonicalPath}") {
        json.findFirstChildByPath("http-response.body")
    }

    val responseHeaders: JSONObjectValue? = attempt("Error reading response headers in file ${file.parentFile.canonicalPath}") {
        val headers = json.findFirstChildByPath("http-response.headers")
        if(headers == null)
            return@attempt null

        if(headers !is JSONObjectValue)
            throw ContractException("http-response.headers should be a JSON object, but instead it was ${headers.toStringLiteral()}")

        headers
    }

    val responseStatus: Int = attempt("Error reading status in file ${file.parentFile.canonicalPath}") {
        json.findFirstChildByPath("http-response.status")?.toStringLiteral()?.toInt()
    } ?: throw ContractException("Response status code was not found.")

    val requestMethod: String = attempt("Error reading method in file ${file.parentFile.canonicalPath}") {
        json.findFirstChildByPath("http-request.method")?.toStringLiteral()
    } ?: throw ContractException("Request method was not found.")

    private val rawPath: String? =
        json.findFirstChildByPath("http-request.path")?.toStringLiteral()

    val requestPath: String = attempt("Error reading path in file ${file.parentFile.canonicalPath}") {
        rawPath?.let { pathOnly(it) }
    } ?: throw ContractException("Request path was not found.")

    private fun pathOnly(requestPath: String): String {
        return URI(requestPath).path ?: ""
    }

    val testName: String = attempt("Error reading expectation name in file ${file.parentFile.canonicalPath}") {
        json.findFirstChildByPath("name")?.toStringLiteral() ?: file.nameWithoutExtension
    }

    val queryParams: Map
        get() {
            val path = attempt("Error reading path in file ${file.parentFile.canonicalPath}") {
                rawPath ?: throw ContractException("Request path was not found.")
            }

            val uri = URI.create(path)
            val queryParamsFromURL = parseQuery(uri.query)

            val queryParamsFromJSONBlock = attempt("Error reading query params in file ${file.parentFile.canonicalPath}") {
                (json.findFirstChildByPath("http-request.query") as JSONObjectValue?)?.jsonObject?.mapValues { (_, value) ->
                    value.toStringLiteral()
                } ?: emptyMap()
            }

            return queryParamsFromURL + queryParamsFromJSONBlock
        }

    val headers: Map = attempt("Error reading headers in file ${file.parentFile.canonicalPath}") {
        (json.findFirstChildByPath("http-request.headers") as JSONObjectValue?)?.jsonObject?.mapValues { (_, value) ->
            value.toStringLiteral()
        } ?: emptyMap()
    }

    val requestBody: Value? = attempt("Error reading request body in file ${file.parentFile.canonicalPath}") {
        json.findFirstChildByPath("http-request.body")
    }
}




© 2015 - 2024 Weber Informatics LLC | Privacy Policy