Hi, moved this here from general. I'm experiencing...
# pactflow
n
Hi, moved this here from general. I'm experiencing difficulties in validating a consumer against the provider contract generated from an OpenAPI spec. The OpenAPI spec has references, inheritance,
oneOf/allOf
keywords and some circular references. The comparison is failing in several places due to "x should NOT have additional properties". I have followed the guidance given here, but even after dereferencing and inlining the same errors still occur. I have eventually been able to get this working by further manually wrangling the spec, so could potentially write a script that would take care of this for me. However, this feels a bit hacky and is not ideal. Are these more advanced OpenAPI spec features not supported? Is there any other guidance on what steps we can take without having to resort to intervening and amending the spec this way, or does anyone have any advice on how best to tackle this? I am using pact-python for the consumer, and pact-php for the provider. Will comment on this thread with some excerpts of the OpenAPI spec. Thanks in advance.
đź‘‹ 1
Example of inheritance & references in the spec:
Copy code
"Parent": {
	"description": "Parent schema",
	"type": "object",
	"required": ["id", "activities"],
	"properties": {
		"id": {
			"type": "integer",
			"example": 3,
			"enum": [3, 4, 5, 6, 7, 8, 9, 16],
			"nullable": false
		},
		"activities": {
			"type": "array",
			"nullable": false,
			"minimum": 1,
			"items": {
				"type": "string",
				"example": "6AA2A3B9-66BD-447C-90C8-A350F60D592B"
			}
		}
	}
},
"Child": {
	"description": "",
	"allOf": [{
		"$ref": "#/components/schemas/Parent"
	}],
	"type": "object",
	"properties": {
		"id": {
			"type": "integer",
			"enum": [3]
		},
		"activities": {
			"type": "array",
			"items": {
				"type": "string",
				"enum": [
					"value",
					"another value"
				]
			}
		}
	}
}
Example of keyword & circular references:
Copy code
"properties": {
	"project_type": {
		"type": "object",
		"nullable": true,
		"oneOf": [{
			"$ref": "#/components/schemas/Category"
		}]
	}
}
....
"schemas": {
	"Category": {
		"type": "object",
		"required": ["short_name"],
		"properties": {
			"short_name": {
				"type": "string",
				"nullable": false,
				"example": "test"
			},
			"child": {
				"nullable": true,
				"allOf": [{
					"$ref": "#/components/schemas/Category"
				}]
			}
		}
	}
}
m
Thanks Nick. When you say “manual wrangling” what did you have to do to get it working? I’d need an engineer on the team to look into it. As you’ve noticed, the keyword support comes with caveats due to the way the schemas get applied and merged
y
As above, would be good to know the exact steps of manual wrangling? Also is it possible to have a repro pact/openapi spec and we can do some digging
n
Thanks both. So it was a combination of things - firstly de-referencing and then using the json-schema-resolve-allof library as described in the docs. This however resulted in an invalid schema in our case, specifically due to the inheritance enums in the example above resolving strangely which leads to errors in PactFlow due to duplicate IDs (one of many of the same error):
schema is invalid: data.definitions['Projects'].items.properties['props'].properties['thing'].oneOf[0].properties['primaries'].items.oneOf[1].properties['id'].enum should NOT have duplicate items (items ## 0 and 1 are identical)
However these do not appear to actually be duplicated:
Copy code
"oneOf": [{
		"description": "",
		"type": "object",
		"properties": {
			"id": {
				"type": "integer",
				"enum": [3, 4, 5, 6, 7, 8, 9, 16],
				"example": 3,
				"nullable": false
			},
			"activities": {
				....
			}
		},
		"required": ["id", "activities"]
	},
	{
		"description": "",
		"type": "object",
		"properties": {
			"id": {
				"type": "integer",
				"enum": [4, 4, 5, 6, 7, 8, 9, 16],
				"example": 3,
				"nullable": false
			},
			"activities": {
				....
			}
		},
		"required": ["id", "activities"]
	}
	...
]
There is definitely an issue here with the dereferencing, as the enum values have been listed incorrectly (I assume due to inheritance), but I am unsure why PactFlow is identifying those as duplicates, as
properties.id.enum
values are different between the two. After manually fixing this (so each child contains a single enum value e.g.
properties.id.enum: [3]
), the dereferencing has fixed a bunch of errors - but unfortunately there are still a large number of
should NOT have additional properties
errors, where we have
oneOf
. In some situations, where we only have a single reference within the
oneOf
, I was able to get this working by removing the
oneOf
array. For the example in the
schemas.category
above, this became the following which works:
Copy code
"properties": {
	"project_type": {
		"type": "object",
		"nullable": true,
		"required": ["short_name"],
		"properties": {
			"short_name": {
				"type": "string",
				"nullable": false,
				"example": "test"
			},
			"child": {
				"nullable": true,
				"type": "object",
				"required": ["short_name"],
				"properties": {
					"short_name": {
						"type": "string",
						"nullable": false,
						"example": "test"
					},
					"child": {
						"nullable": true
					}
				}
			}
		}
	}
}
But has meant the loss of the circular reference for the nested
child
property. Where multiple entities exist under
oneOf
and so couldn't just be removed, I added
additionalProperties: true
wherever the keyword was used, which seems to be the nuclear option I'd much rather avoid. E.g
Copy code
"properties": {
	"metrics": {
		"type": "array",
		"nullable": true,
		"items": {
			"additionalProperties": true,
			"oneOf": [{
					...
				}, {
					...
				}
				...
			]
		}
	}
}
Am just checking with the powers that be that I'm ok to send over a copy of the spec/pact - will do this asap. Thanks again.
y
no worries chap, thanks for all the additional detail It would be great if you could raise the issue against https://github.com/pactflow/swagger-mock-validator as this is the underlying tool we use, if you can build a non client specific example, if would be great to get in as a test case, unit or e2e, so we have a good base for investigations
n
Thanks Yousaf - will try and make the time to raise the issue sometime this week. Have got the all-clear to send over the (anonymised somewhat) copies of our Open API spec/Pact contract. Will DM them to you directly
Finally managed to get to this - I have created an issue here: https://github.com/pactflow/swagger-mock-validator/issues/21 Included a simple example OAS spec & PactFile. Thanks!
m
Thanks for sharing, we’ll review with some upcoming work on this tool
thank you note 1