Skip to content

Commit

Permalink
chore: refactor code and add docstrings
Browse files Browse the repository at this point in the history
  • Loading branch information
OmarAlJarrah committed Aug 19, 2024
1 parent fe57072 commit da250cf
Show file tree
Hide file tree
Showing 7 changed files with 62 additions and 55 deletions.
48 changes: 22 additions & 26 deletions sdk-test/src/main/kotlin/com/expediagroup/sdk/test/CLI.kt
Original file line number Diff line number Diff line change
Expand Up @@ -27,16 +27,13 @@ package com.expediagroup.sdk.test

import com.expediagroup.sdk.test.contract.ContractTestsGenerator
import com.expediagroup.sdk.test.contract.MAX_TEST_REQUEST_PER_SCENARIO
import com.expediagroup.sdk.test.contract.model.api.TestCaseApiCall
import com.expediagroup.sdk.test.openapi.SdkTestGenerator
import com.expediagroup.sdk.test.util.toBoolean
import com.github.rvesse.airline.SingleCommand
import com.github.rvesse.airline.annotations.Command
import com.github.rvesse.airline.annotations.Option
import org.openapitools.codegen.config.GeneratorSettings
import org.slf4j.LoggerFactory
import java.io.File
import java.util.logging.Logger
import java.util.logging.LoggingPermission

@Command(name = "cli", description = "Command Line Interface for SDK Test")
class CLI {
Expand All @@ -55,10 +52,10 @@ class CLI {
@Option(name = ["-m", "--max-test-combinations"])
private var maxTestCombinations: Int = MAX_TEST_REQUEST_PER_SCENARIO

@Option(name = ["-c", "--contract-tests-only"])
private var generateContractTestsOnly = false
@Option(name = ["-c", "--generate-contract-tests"])
private var generateContractTests = false

@Option(name = ["-s", "--sdk-tests"])
@Option(name = ["-s", "--generate-sdk-tests"])
private var generateSdkTests = false

private lateinit var sdkTestGenerator: SdkTestGenerator
Expand All @@ -81,28 +78,27 @@ class CLI {
}

fun run() {
if (!listOf(generateSdkTests, generateContractTestsOnly).any(::toBoolean)){
throw IllegalArgumentException("At least one of --contract-tests-only or --sdk-tests must be set to true")
if (!listOf(generateSdkTests, generateContractTests).any(::toBoolean)) {
throw IllegalArgumentException("At least one of --generate-contract-tests or --generate-sdk-tests must be set to true")
}

contractTestsGenerator =
ContractTestsGenerator(
spec = spec,
outputDir = File(outputDir),
maxTestCombinations = maxTestCombinations
)

contractTestsGenerator.generate(writeMode = generateSdkTests.not().or(generateContractTestsOnly)).also { testCases ->
if (generateSdkTests) {
sdkTestGenerator =
SdkTestGenerator(
namespace = namespace,
spec = spec,
version = version,
testCases = testCases
)
sdkTestGenerator.generate()
contractTestsGenerator = ContractTestsGenerator(
spec = spec,
outputDir = File(outputDir),
maxTestCombinations = maxTestCombinations
)

contractTestsGenerator.generate(writeMode = generateContractTests).let { testCases ->
if (!generateSdkTests) {
return
}

sdkTestGenerator = SdkTestGenerator(
namespace = namespace,
spec = spec,
version = version,
testCases = testCases
).also { it.generate() }
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -25,16 +25,23 @@
*/
package com.expediagroup.sdk.test.contract.model.api

import com.expediagroup.sdk.test.contract.extension.isEmptyJsonObject
import com.expediagroup.sdk.test.util.toBoolean
import com.fasterxml.jackson.annotation.JsonProperty
import io.specmatic.core.HttpResponse

data class TestCaseHttpResponse(
@JsonProperty val status: Int
@JsonProperty val status: Int,
@JsonProperty val headers: Map<String, Any>? = emptyMap(),
@JsonProperty val body: String? = ""
) {
companion object {

fun from(response: HttpResponse): TestCaseHttpResponse =
TestCaseHttpResponse(
status = response.status
status = response.status,
headers = response.headers,
body = response.body.toString().takeIf { !it.isEmptyJsonObject().and(toBoolean(it)) }
)
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -85,6 +85,9 @@ class SdkTestGenerator(
addAdditionalProperty(CodegenConstants.SERIALIZATION_LIBRARY, "jackson")
addAdditionalProperty(CodegenConstants.SORT_PARAMS_BY_REQUIRED_FLAG, true)

addAdditionalProperty("namespace", product.namespace)
addAdditionalProperty("clientClassname", namespace.pascalCase())

// Mustache Helpers
mustacheHelpers.forEach { (name, func) ->
addAdditionalProperty(name, func)
Expand Down Expand Up @@ -115,13 +118,6 @@ class SdkTestGenerator(
"${namespace.pascalCase()}OperationsMetadata.kt"
)
)
add(
SupportingFile(
"testcases.mustache",
packagePath,
"${namespace.pascalCase()}TestCases.kt"
)
)
add(
SupportingFile(
"pom.mustache",
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,8 +2,10 @@ package com.expediagroup.sdk.{{{namespace}}}.test;


import com.expediagroup.sdk.rapid.client.*;
import com.expediagroup.sdk.core.model.*;
import com.expediagroup.sdk.rapid.operations.*;
import com.expediagroup.sdk.core.model.Operation;
import com.expediagroup.sdk.core.model.exception.service.*
import com.fasterxml.jackson.databind.*
import com.fasterxml.jackson.databind.node.*
import com.fasterxml.jackson.module.kotlin.*

Expand All @@ -12,22 +14,34 @@ class {{{clientClassname}}}Executor {
val mapper = jacksonObjectMapper()
}

private val client = {{{clientClassname}}}.builder()
private val client = {{{clientClassname}}}Client.builder()
.key(System.getProperty("com.expediagroup.sdk.apikey", "API_KEY"))
.secret(System.getProperty("com.expediagroup.sdk.apisecret", "API_SECRET"))
.endpoint("com.expediagroup.sdk.rapid.examples.Constants.SANDBOX_URL") // remove to connect to the production environment
.endpoint("localhost:8080")
.requestTimeout(10000)
.build()

fun execute(json: ObjectNode) {
val key = "${json["method"].asText().trim()}: ${json["path"].asText().trim()}"
val type: Class<*> = metadata[key]!!.type
fun execute(request: ObjectNode, expectedResponse: ObjectNode) {
val key = "${request["method"].asText().trim()}: ${request["path"].asText().trim()}"
val operation = mapper.readValue(json.asText(), type) as Operation<*>
execute(operation)
val requestType: Class<*> = metadata[key]!!.requestType
val operation = mapper.readValue(request.asText(), requestType) as Operation<*>
if (expectedResponse["status"].asInt() in 200..299) {
val actual = mapper.convertValue(execute(operation), JsonNode::class.java)
assert ((expectedResponse["body"] as JsonNode).equals(actual)) // TODO: Add a better way to compare responses
} else {
try {
val actual = execute(operation)
throw Exception("Response expected to be okay but was not! \n${actual.toString()}")
} catch (e: ExpediaGroupServiceException) {
// expected
}
}
}

fun execute(operation: Operation<*>) {
private fun execute(operation: Operation<*>): Response<*> =
when (operation) {
{{#apiInfo}}
{{#apis}}
Expand All @@ -40,6 +54,6 @@ class {{{clientClassname}}}Executor {
{{/operations}}
{{/apis}}
{{/apiInfo}}
else -> throw Exception("Operation not found")
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,7 @@ class Main {
val request = test["request"] as ObjectNode
val response = test["response"] as ObjectNode
executor.execute(request)
executor.execute(request, response)
}
}
}
Expand Down
Original file line number Diff line number Diff line change
@@ -1,10 +1,10 @@
package com.expediagroup.sdk.{{{namespace}}}.test;

import com.expediagroup.sdk.{{{namespace}}}.operations.*;
import com.expediagroup.sdk.{{{namespace}}}.client.*;


data class OperationMetadata(
val type: Class<*>,
val requestType: Class<*>,
val hasBody: Boolean,
val hasParams: Boolean,
)
Expand All @@ -15,7 +15,7 @@ val metadata = mapOf<String, OperationMetadata>(
{{#operations}}
{{#operation}}
"{{{httpMethod}}}: {{{path}}}" to OperationMetadata(
type={{{operationIdCamelCase}}}Operation::class.java,
requestType={{{operationIdCamelCase}}}Operation::class.java,
hasBody={{hasBodyParam}},
hasParams={{#hasNonBodyParams}}true{{/hasNonBodyParams}}{{^hasNonBodyParams}}true{{/hasNonBodyParams}},
),
Expand Down

This file was deleted.

0 comments on commit da250cf

Please sign in to comment.