fix: detect property type changes on referenced component schemas in OpenAPI 3.1
Fixes #910
Problem
In OpenAPI 3.1 documents, a type change on a property of a referenced component schema was silently ignored: getChangedOperations() and getChangedSchemas() came back empty. The identical change in an OpenAPI 3.0 document is detected as INCOMPATIBLE (covered by SchemaDiffTest#schemaPropertyTypeChanged with the schema-props-type-handling-1/2.yaml fixtures, as noted in the issue triage).
Root cause
swagger-parser deserializes OpenAPI 3.1 schemas into JsonSchema instances in which the type keyword is stored in the types set (Schema#getTypes()), while Schema#getType() returns null. The type-change gate in SchemaDiff#computeDiffForReal compared only getType(), so for 3.1 it compared null with null and never fired — the property type change was dropped (property diffs inside SchemaDiffResult never look at the type).
For OpenAPI 3.0, getType() carries the type, so the gate fired and produced the changedType result, which ChangedSchema classifies as INCOMPATIBLE (incompatible.schema.type.changed is enabled by default).
Fix
Compare the effective type set (union of getType() and getTypes()) in addition to the raw getType() string:
- OpenAPI 3.1 (JsonSchema):
type=null, types ingetTypes()→ union is the type carrier → type changes are now detected. - OpenAPI 3.0 typed schemas (
StringSchema,ObjectSchema, ...): bothtypeandtypesare populated → union is unchanged, no behavior change. - OpenAPI 3.0 composed schemas merged from their allOf/anyOf children (
SchemaDiff#addSchemacopiestypebut nottypes): onlytypeis populated → union keeps these comparisons working exactly as before (allOf-equivalence testsAllOfDiffTest/Issue887Testconfirm no regression).
Because the fix reuses the exact same getTypeChangedSchema path that OpenAPI 3.0 takes, the classification is identical to 3.0: the property reports changedType=true, the schema/operation is reported as changed and classified INCOMPATIBLE.
Tests
SchemaDiffTest#schemaPropertyTypeChanged31mirrors the 3.0 type-change test using the issue's spec pair (GET /widgets, 200 response, `` toWidget,Widget.properties.weight.typeinteger→string,openapi: 3.1.0): fixturesschema-props-type-handling-3.1-1.yaml/-2.yaml. It failed before the fix (changedOperationsexpected 1 but was 0, matching the issue) and passes after.
Scope notes
formatchanges in 3.1 are already detected (the parser storesformatin the regular field and the gate compares it) — verified; no other property attribute shares thetypesgap.- Multi-type keywords (
type: [integer, string]) are compared as sets, so reordering does not produce a false change.
Summary by cubic
Fixes #910. Property type changes on referenced component schemas in OpenAPI 3.1 documents were silently ignored — getChangedOperations() and getChangedSchemas() returned empty. The type-change gate now compares the effective type set (union of getType() and getTypes(), which OpenAPI 3.1 deserialization populates), so these changes are detected and classified as INCOMPATIBLE, matching OpenAPI 3.0 behavior.
- Dropped the raw
getType()comparison so equivalent schemas with the same effective type no longer report a false change. resolveComposedSchemanow flattens allOf/anyOf on any schema (3.1 compositions deserialize intoJsonSchema, notComposedSchema) andaddSchemapropagatesgetTypes(), so composed schemas keep their effective types.- Added the
schemaPropertyTypeChanged31regression test with the issue's spec pair, asserting theINCOMPATIBLEclassification.