Skip to content

Commit

Permalink
Merge pull request #1154 from znsio/xml_fixes
Browse files Browse the repository at this point in the history
XML attribute fixes
  • Loading branch information
joelrosario authored Jun 26, 2024
2 parents 215bf6e + b39e65f commit 677572c
Show file tree
Hide file tree
Showing 3 changed files with 127 additions and 2 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -1141,7 +1141,12 @@ class OpenApiSpecification(
}

val attributes: Map<String, Pattern> = attributeProperties.map { (name, schema) ->
name to toSpecmaticPattern(schema, emptyList())
val attributeName = if(name !in schema.required.orEmpty())
"$name.opt"
else
name

attributeName to toSpecmaticPattern(schema, emptyList())
}.toMap()

name ?: throw ContractException("Could not determine name for an xml node")
Expand Down
5 changes: 4 additions & 1 deletion core/src/main/kotlin/in/specmatic/core/pattern/XMLPattern.kt
Original file line number Diff line number Diff line change
Expand Up @@ -110,7 +110,10 @@ data class XMLPattern(override val pattern: XMLTypeData = XMLTypeData(realName =
val matchingType = if (this.pattern.attributes.containsKey(TYPE_ATTRIBUTE_NAME)) {
val typeName = this.pattern.getAttributeValue(TYPE_ATTRIBUTE_NAME)
val xmlType = (resolver.getPattern("($typeName)") as XMLPattern)
xmlType.copy(pattern = xmlType.pattern.copy(name = this.pattern.name, realName = this.pattern.realName, attributes = this.pattern.attributes.filterKeys { it != TYPE_ATTRIBUTE_NAME }))
val attributesFromReferring = this.pattern.attributes.filterKeys { it != TYPE_ATTRIBUTE_NAME }
val attributesFromReferred = xmlType.pattern.attributes.filterKeys { it != TYPE_ATTRIBUTE_NAME }
val attributes = attributesFromReferred + attributesFromReferring
xmlType.copy(pattern = xmlType.pattern.copy(name = this.pattern.name, realName = this.pattern.realName, attributes = attributes))
} else {
this
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@ import `in`.specmatic.mock.ScenarioStub
import `in`.specmatic.stub.HttpStub
import `in`.specmatic.stub.HttpStubData
import `in`.specmatic.stub.createStubFromContracts
import `in`.specmatic.stub.stringToMockScenario
import `in`.specmatic.test.TestExecutor
import `in`.specmatic.trimmedLinesString
import integration_tests.testCount
Expand Down Expand Up @@ -7815,6 +7816,122 @@ paths:
assertThat(results.success()).isTrue()
}

@Test
fun `references in an XML structure which contains a ref should get dereferenced`() {
val xmlSpec = """
openapi: 3.0.0
info:
title: Testing API
version: 1.0.0
description: |
Testing XML
paths:
/ReqListKeys:
post:
summary: Request list of keys
operationId: reqListKeys
requestBody:
required: true
content:
application/xml:
schema:
${"$"}ref: '#/components/schemas/ReqListKeys'
responses:
'200':
description: Successful response
content:
application/xml:
schema:
${"$"}ref: '#/components/schemas/RespListKeys'
components:
schemas:
ReqListKeys:
type: object
xml:
name: "ReqListKeys"
namespace: "http://xyz.org/upi/schema//"
prefix: "upi"
properties:
Head:
${"$"}ref: '#/components/schemas/Head'
Head:
type: object
xml:
name: "Head"
properties:
msgId:
type: string
xml:
name: "msgId"
attribute: true
orgId:
type: string
xml:
name: "orgId"
attribute: true
prodType:
type: string
xml:
name: "prodType"
attribute: true
ts:
type: string
xml:
name: "ts"
attribute: true
ver:
type: string
enum: [1.0, 2.0]
xml:
name: "ver"
attribute: true
RespListKeys:
type: object
xml:
name: "RespListKeys"
namespace: "http://xyz.org/upi/schema/"
prefix: "ns2"
properties:
Head:
${"$"}ref: '#/components/schemas/Head'
""".trimIndent()

val feature = OpenApiSpecification.fromYAML(xmlSpec, "").toFeature()

val rawStub = """
{
"http-request": {
"path": "/ReqListKeys",
"method": "POST",
"headers": {
"Content-Type": "application/xml"
},
"body": "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<upi:ReqListKeys xmlns:upi=\"http://xyz.org/upi/schema/\">\n <Head msgId=\"abcde\" orgId=\"157776\" prodType=\"UPI\" ts=\"1970-01-01T05:30:00+05:30\" ver=\"2.0\"/>\n</upi:ReqListKeys>"
},
"http-response": {
"status": 200,
"body": "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<ns2:RespListKeys xmlns:ns2=\"http://xyz.org/upi/schema/\">\n <Head msgId=\"syz\" orgId=\"org\" ts=\"2024-05-27T15:35:12+05:30\" ver=\"2.0\"/>\n</ns2:RespListKeys>\n",
"status-text": "OK",
"headers": {
"Content-Type": "application/xml"
}
}
}
""".trimIndent()

val expectation: ScenarioStub = stringToMockScenario(StringValue(rawStub))

HttpStub(feature, listOf(expectation)).use { stub ->
val request = expectation.request

val response = stub.client.execute(request)

assertThat(response.status).isEqualTo(200)
assertThat(response.body.toStringLiteral()).contains("msgId")
}
}

private fun ignoreButLogException(function: () -> OpenApiSpecification) {
try {
function()
Expand Down

0 comments on commit 677572c

Please sign in to comment.