Skip to content

Commit

Permalink
Pulled out HttpPathPattern and HttpQueryParamPattern from HttpURLPattern
Browse files Browse the repository at this point in the history
Cleanup
  • Loading branch information
nashjain authored and harikrishnan83 committed Jan 8, 2024
1 parent 80c3075 commit bebaf39
Show file tree
Hide file tree
Showing 22 changed files with 1,035 additions and 903 deletions.
4 changes: 2 additions & 2 deletions application/src/main/kotlin/application/ReclaredAPICommand.kt
Original file line number Diff line number Diff line change
Expand Up @@ -203,7 +203,7 @@ fun findRedeclarations(
): List<APIReDeclarations> {
val newPathToContractMap = newPaths.map { newPath ->
val matchingContracts = contracts.filter { (feature, _) ->
feature.scenarios.map { it.httpRequestPattern.httpUrlPattern!!.path }.any { scenarioPath ->
feature.scenarios.map { it.httpRequestPattern.httpPathPattern!!.path }.any { scenarioPath ->
scenarioPath == newPath
}
}.map { it.second }
Expand Down Expand Up @@ -231,7 +231,7 @@ fun urlPaths(newerContractYaml: String, contractPath: String): List<String>? {
}

private fun pathsFromFeature(newContract: Feature) =
newContract.scenarios.map { it.httpRequestPattern.httpUrlPattern!!.path }.sorted().distinct()
newContract.scenarios.map { it.httpRequestPattern.httpPathPattern!!.path }.sorted().distinct()

open class CanonicalFile(val file: File) {
val path: String = file.path
Expand Down
18 changes: 9 additions & 9 deletions application/src/main/kotlin/application/ValidateViaLogs.kt
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,7 @@ class ValidateViaLogs : Callable<Unit> {
override fun call() {
val feature = OpenApiSpecification.fromFile(contractPath).toFeature()

val httpUrlMatchers: List<Pair<HttpURLPattern, Resolver>> = findMatchingURLMatchers(feature)
val httpUrlMatchers: List<Pair<HttpPathPattern, Resolver>> = findMatchingURLMatchers(feature)

val requestLogs = parsedJSONArray(File(logDirPath).readText())

Expand Down Expand Up @@ -84,7 +84,7 @@ class ValidateViaLogs : Callable<Unit> {

private fun stubFromExpectationLog(
log: JSONObjectValue,
httpUrlMatchers: List<Pair<HttpURLPattern, Resolver>>
httpUrlMatchers: List<Pair<HttpPathPattern, Resolver>>
): Pair<ScenarioStub, ScenarioStub>? {
val status = log.findFirstChildByPath("http-response.status")?.toStringLiteral()

Expand All @@ -107,14 +107,14 @@ class ValidateViaLogs : Callable<Unit> {
private fun stubFromExpectationLog(
stubRequestPathLog: Value,
log: JSONObjectValue,
httpUrlMatchers: List<Pair<HttpURLPattern, Resolver>>
httpUrlMatchers: List<Pair<HttpPathPattern, Resolver>>
): ScenarioStub? {
val path = stubRequestPathLog.toStringLiteral()

val body = log.findFirstChildByPath("http-request.body") as JSONObjectValue

if (httpUrlMatchers.any { (matcher, resolver) ->
matcher.matchesPath(path, resolver) is Result.Success
matcher.matches(path, resolver) is Result.Success
})
return mockFromJSON(body.jsonObject)

Expand All @@ -123,7 +123,7 @@ class ValidateViaLogs : Callable<Unit> {

private fun stubFromRequestLog(
path: String,
httpUrlMatchers: List<Pair<HttpURLPattern, Resolver>>,
httpUrlMatchers: List<Pair<HttpPathPattern, Resolver>>,
log: JSONObjectValue
): ScenarioStub? {
val headers = log.findFirstChildByPath("http-response.headers") as JSONObjectValue?
Expand All @@ -133,16 +133,16 @@ class ValidateViaLogs : Callable<Unit> {
return null

if (httpUrlMatchers.any { (matcher, resolver) ->
matcher.matches(HttpRequest(path = path), resolver) is Result.Success
matcher.matches(path, resolver) is Result.Success
})
return mockFromJSON(log.jsonObject)

return null
}

private fun findMatchingURLMatchers(feature: Feature): List<Pair<HttpURLPattern, Resolver>> {
val httpUrlMatchers: List<Pair<HttpURLPattern, Resolver>> = feature.scenarios.map {
Pair(it.httpRequestPattern.httpUrlPattern, it.resolver)
private fun findMatchingURLMatchers(feature: Feature): List<Pair<HttpPathPattern, Resolver>> {
val httpUrlMatchers: List<Pair<HttpPathPattern, Resolver>> = feature.scenarios.map {
Pair(it.httpRequestPattern.httpPathPattern, it.resolver)
}.map { (matcher, resolver) ->
Triple(matcher, matcher?.matches(URI.create(urlPathFilter)), resolver)
}.filter {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -29,11 +29,10 @@ class APIKeyInQueryParamSecurityScheme(val name: String, private val apiKey:Stri
}

return requestPattern.copy(
httpUrlPattern = requestPattern.httpUrlPattern?.copy(
queryPatterns = requestPattern.httpUrlPattern.queryPatterns.plus(name to queryParamValueType)
httpQueryParamPattern = requestPattern.httpQueryParamPattern.copy(
queryPatterns = requestPattern.httpQueryParamPattern.queryPatterns.plus(name to queryParamValueType)
)
)

}

override fun isInRow(row: Row): Boolean = row.containsField(name)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -157,7 +157,7 @@ class OpenApiSpecification(private val openApiFilePath: String, private val pars
matchingScenarioInfos.isEmpty() -> MatchFailure(
Failure(
"""Scenario: "${specmaticScenarioInfo.scenarioName}" PATH: "${
specmaticScenarioInfo.httpRequestPattern.httpUrlPattern!!.generatePath(Resolver())
specmaticScenarioInfo.httpRequestPattern.httpPathPattern!!.generate(Resolver())
}" is not as per included wsdl / OpenApi spec"""
)
)
Expand Down Expand Up @@ -228,8 +228,8 @@ class OpenApiSpecification(private val openApiFilePath: String, private val pars
val (specmaticScenarioInfo, openApiScenarioInfos) = parameters

return MatchSuccess(specmaticScenarioInfo to openApiScenarioInfos.map { openApiScenario ->
val queryPattern = openApiScenario.httpRequestPattern.httpUrlPattern?.queryPatterns ?: emptyMap()
val zippedPathPatterns = (specmaticScenarioInfo.httpRequestPattern.httpUrlPattern?.pathSegmentPatterns ?: emptyList()).zip(openApiScenario.httpRequestPattern.httpUrlPattern?.pathSegmentPatterns ?: emptyList())
val queryPattern = openApiScenario.httpRequestPattern.httpQueryParamPattern?.queryPatterns ?: emptyMap()
val zippedPathPatterns = (specmaticScenarioInfo.httpRequestPattern.httpPathPattern?.pathSegmentPatterns ?: emptyList()).zip(openApiScenario.httpRequestPattern.httpPathPattern?.pathSegmentPatterns ?: emptyList())

val pathPatterns = zippedPathPatterns.map { (fromWrapper, fromOpenApi) ->
if(fromWrapper.pattern is ExactValuePattern)
Expand All @@ -238,21 +238,23 @@ class OpenApiSpecification(private val openApiFilePath: String, private val pars
fromOpenApi.copy(key = fromWrapper.key)
}

val httpUrlPattern = HttpURLPattern(queryPattern, pathPatterns, openApiScenario.httpRequestPattern.httpUrlPattern?.path ?: "")
val httpPathPattern = HttpPathPattern(pathPatterns, openApiScenario.httpRequestPattern.httpPathPattern?.path ?: "")
val httpQueryParamPattern = HttpQueryParamPattern(queryPattern)

val httpRequestPattern = openApiScenario.httpRequestPattern.copy(httpUrlPattern = httpUrlPattern)
val httpRequestPattern = openApiScenario.httpRequestPattern.copy(httpPathPattern = httpPathPattern, httpQueryParamPattern = httpQueryParamPattern)
openApiScenario.copy(httpRequestPattern = httpRequestPattern)
})
}

private fun openApiToScenarioInfos(): Pair<List<ScenarioInfo>, Map<String, List<Pair<HttpRequest, HttpResponse>>>> {
val data: List<Pair<List<ScenarioInfo>, Map<String, List<Pair<HttpRequest, HttpResponse>>>>> = openApiPaths().map { (openApiPath, pathItem) ->
openApiOperations(pathItem).map { (httpMethod, operation) ->
val specmaticPath = toSpecmaticPath(openApiPath, operation)
val specmaticPathParam = toSpecmaticPathParam(openApiPath, operation)
val specmaticQueryParam = toSpecmaticQueryParam(operation)

val httpRequestPatterns: List<Pair<HttpRequestPattern, Map<String, List<HttpRequest>>>> =
toHttpRequestPatterns(
specmaticPath, httpMethod, operation
specmaticPathParam, specmaticQueryParam, httpMethod, operation
)

val httpResponsePatterns: List<ResponseData> = toHttpResponsePatterns(operation.responses)
Expand Down Expand Up @@ -339,12 +341,13 @@ class OpenApiSpecification(private val openApiFilePath: String, private val pars

val scenarioInfos = openApiPaths().map { (openApiPath, pathItem) ->
openApiOperations(pathItem).map { (httpMethod, operation) ->
val specmaticPath = toSpecmaticPath(openApiPath, operation)
val specmaticPathParam = toSpecmaticPathParam(openApiPath, operation)
val specmaticQueryParam = toSpecmaticQueryParam(operation)

val requestBody: RequestBody? = resolveRequestBody(operation)

val httpResponsePatterns = toHttpResponsePatterns(operation.responses)
val httpRequestPatterns = toHttpRequestPatterns(specmaticPath, httpMethod, operation)
val httpRequestPatterns = toHttpRequestPatterns(specmaticPathParam, specmaticQueryParam, httpMethod, operation)

httpResponsePatterns.map { (response, responseMediaType, httpResponsePattern) ->
val responseExamples: Map<String, Example> = responseMediaType.examples.orEmpty()
Expand All @@ -356,7 +359,7 @@ class OpenApiSpecification(private val openApiFilePath: String, private val pars

val ignoreFailure = operation.tags.orEmpty().map { it.trim() }.contains("WIP")

val operationIdentifier = OperationIdentifier(httpMethod, specmaticPath.path, httpResponsePattern.status)
val operationIdentifier = OperationIdentifier(httpMethod, specmaticPathParam.path, httpResponsePattern.status)

val relevantExternalizedJSONExamples = externalizedJSONExamples[operationIdentifier]
val rowsToBeUsed: List<Row> = relevantExternalizedJSONExamples ?: specmaticExampleRows
Expand Down Expand Up @@ -650,7 +653,7 @@ class OpenApiSpecification(private val openApiFilePath: String, private val pars
}

private fun toHttpRequestPatterns(
httpUrlPattern: HttpURLPattern, httpMethod: String, operation: Operation
httpPathPattern: HttpPathPattern, httpQueryParamPattern: HttpQueryParamPattern, httpMethod: String, operation: Operation
): List<Pair<HttpRequestPattern, Map<String, List<HttpRequest>>>> {

val securitySchemes: Map<String, OpenAPISecurityScheme> =
Expand All @@ -666,7 +669,8 @@ class OpenApiSpecification(private val openApiFilePath: String, private val pars

val headersPattern = HttpHeadersPattern(headersMap)
val requestPattern = HttpRequestPattern(
httpUrlPattern = httpUrlPattern,
httpPathPattern = httpPathPattern,
httpQueryParamPattern = httpQueryParamPattern,
method = httpMethod,
headersPattern = headersPattern,
securitySchemes = operationSecuritySchemes(operation, securitySchemes)
Expand All @@ -685,7 +689,7 @@ class OpenApiSpecification(private val openApiFilePath: String, private val pars
val pathParams = examplePathParams[exampleName] ?: emptyMap()
val headerParams = exampleHeaderParams[exampleName] ?: emptyMap()

val path = pathParams.entries.fold(httpUrlPattern.toOpenApiPath()) { acc, (key, value) ->
val path = pathParams.entries.fold(httpPathPattern.toOpenApiPath()) { acc, (key, value) ->
acc.replace("{$key}", value)
}

Expand Down Expand Up @@ -763,7 +767,7 @@ class OpenApiSpecification(private val openApiFilePath: String, private val pars

val httpRequest = HttpRequest(
method = httpMethod,
path = httpUrlPattern.path,
path = httpPathPattern.path,
queryParams = queryParams,
body = parsedValue(it.value ?: "")
)
Expand Down Expand Up @@ -1325,8 +1329,21 @@ class OpenApiSpecification(private val openApiFilePath: String, private val pars

private fun componentNameFromReference(component: String) = component.substringAfterLast("/")

private fun toSpecmaticPath(openApiPath: String, operation: Operation): HttpURLPattern {
val parameters = operation.parameters ?: return toURLMatcherWithOptionalQueryParams(openApiPath)
private fun toSpecmaticQueryParam(operation: Operation): HttpQueryParamPattern {
val parameters = operation.parameters ?: return HttpQueryParamPattern(emptyMap())
val queryPattern: Map<String, Pattern> = parameters.filterIsInstance(QueryParameter::class.java).associate {
val specmaticPattern: Pattern = if (it.schema.type == "array") {
CsvPattern(toSpecmaticPattern(schema = it.schema.items, typeStack = emptyList()))
} else {
toSpecmaticPattern(schema = it.schema, typeStack = emptyList(), patternName = it.name)
}

"${it.name}?" to specmaticPattern
}
return HttpQueryParamPattern(queryPattern)
}
private fun toSpecmaticPathParam(openApiPath: String, operation: Operation): HttpPathPattern {
val parameters = operation.parameters ?: return buildHttpPathPattern(openApiPath)

val pathStringParts: List<String> = openApiPath.removePrefix("/").removeSuffix("/").let {
if (it.isBlank())
Expand All @@ -1350,19 +1367,9 @@ class OpenApiSpecification(private val openApiFilePath: String, private val pars
}
}

val queryPattern: Map<String, Pattern> = parameters.filterIsInstance(QueryParameter::class.java).associate {
val specmaticPattern: Pattern = if (it.schema.type == "array") {
CsvPattern(toSpecmaticPattern(schema = it.schema.items, typeStack = emptyList()))
} else {
toSpecmaticPattern(schema = it.schema, typeStack = emptyList(), patternName = it.name)
}

"${it.name}?" to specmaticPattern
}

val specmaticPath = toSpecmaticFormattedPathString(parameters, openApiPath)

return HttpURLPattern(queryPattern, pathPattern, specmaticPath)
return HttpPathPattern(pathPattern, specmaticPath)
}

private fun toSpecmaticFormattedPathString(
Expand Down
Loading

0 comments on commit bebaf39

Please sign in to comment.