fix(oas3): attempt to render schemas not resolved by swagger-client (#9629)

Refs #9513
This commit is contained in:
Oliwia Rogala
2024-02-23 11:30:28 +01:00
committed by GitHub
parent cfb7ca9a07
commit 7300e6c04e
7 changed files with 63117 additions and 7 deletions

View File

@@ -2,6 +2,7 @@ import React from "react"
import ImmutablePureComponent from "react-immutable-pure-component"
import ImPropTypes from "react-immutable-proptypes"
import PropTypes from "prop-types"
import { Map } from "immutable"
import RollingLoadSVG from "core/assets/rolling-load.svg"
@@ -55,20 +56,35 @@ export default class Model extends ImmutablePureComponent {
const PrimitiveModel = getComponent("PrimitiveModel")
let type = "object"
let $$ref = schema && schema.get("$$ref")
let $ref = schema && schema.get("$ref")
// If we weren't passed a `name` but have a ref, grab the name from the ref
if ( !name && $$ref ) {
name = this.getModelName( $$ref )
// If we weren't passed a `name` but have a resolved ref, grab the name from the ref
if (!name && $$ref) {
name = this.getModelName($$ref)
}
// If we weren't passed a `schema` but have a ref, grab the schema from the ref
if ( !schema && $$ref ) {
schema = this.getRefSchema( name )
/*
* If we have an unresolved ref, get the schema and name from the ref.
* If the ref is external, we can't resolve it, so we just display the ref location.
* This is for situations where the ref was not resolved by Swagger Client
* because we reached the traversal depth limit.
*/
if ($ref) {
name = this.getModelName($ref)
const refSchema = this.getRefSchema(name)
if (Map.isMap(refSchema)) {
schema = refSchema.set("$$ref", $ref)
$$ref = $ref
} else {
schema = null
name = $ref
}
}
if(!schema) {
return <span className="model model-title">
<span className="model-title__text">{ displayName || name }</span>
<RollingLoadSVG height="20px" width="20px" />
{!$ref && <RollingLoadSVG height="20px" width="20px" />}
</span>
}

View File

@@ -65,6 +65,7 @@ export default class ObjectModel extends Component {
}
</span>)
const allOf = specSelectors.isOAS3() ? schema.get("allOf") : null
const anyOf = specSelectors.isOAS3() ? schema.get("anyOf") : null
const oneOf = specSelectors.isOAS3() ? schema.get("oneOf") : null
const not = specSelectors.isOAS3() ? schema.get("not") : null
@@ -194,6 +195,22 @@ export default class ObjectModel extends Component {
</td>
</tr>
}
{
!allOf ? null
: <tr>
<td>{ "allOf ->" }</td>
<td>
{allOf.map((schema, k) => {
return <div key={k}><Model { ...otherProps } required={ false }
getComponent={ getComponent }
specPath={specPath.push("allOf", k)}
getConfigs={ getConfigs }
schema={ schema }
depth={ depth + 1 } /></div>
})}
</td>
</tr>
}
{
!anyOf ? null
: <tr>

View File

@@ -47,6 +47,16 @@ export const servers = onlyOAS3(() => (system) => {
return spec.get("servers", map)
})
export const findSchema = (state, schemaName) => {
const resolvedSchema = state.getIn(
["resolvedSubtrees", "components", "schemas", schemaName],
null
)
const unresolvedSchema = state.getIn(["json", "components", "schemas", schemaName], null)
return resolvedSchema || unresolvedSchema || null
}
export const callbacksOperations = onlyOAS3(
(state, { callbacks, specPath }) =>
(system) => {

View File

@@ -32,6 +32,10 @@ const OAS3NullSelector = onlyOAS3(nullSelector)
* Wrappers
*/
export const findDefinition = onlyOAS3((state, schemaName) => (system) => {
return system.getSystem().specSelectors.findSchema(schemaName)
})
export const definitions = onlyOAS3(() => (system) => {
const spec = system.getSystem().specSelectors.specJson()
const schemas = spec.getIn(["components", "schemas"])

View File

@@ -0,0 +1,37 @@
/**
* @prettier
*/
describe("OpenAPI 3.0 complex spec with allOf and nested references", () => {
it("should render nested references", () => {
cy.visit("/?url=/documents/features/oas3-complex-spec.json").then(() => {
cy.get(
"[id='model-com.sap.ctsm.backend.core.api.study.v1.StudyAPIv1.StudyTreatments-create']"
)
.find("button")
.click()
cy.get(".property-row")
.contains("scenario")
.siblings()
.as("scenarioSiblings")
cy.get("@scenarioSiblings").find("button").click()
cy.get("@scenarioSiblings")
.find("span")
.contains("scenarioID")
.should("not.exist")
cy.get("@scenarioSiblings")
.find("span")
.contains("Scenarios (for create)")
.should("exist")
.click()
cy.get("@scenarioSiblings")
.find("span")
.contains("scenarioID")
.should("exist")
cy.get("@scenarioSiblings")
.find("span")
.contains("#/components/schemas/unresolvedRef")
.should("exist")
})
})
})

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,62 @@
/**
* @prettier
*/
import { fromJS } from "immutable"
import { findSchema } from "core/plugins/oas3/spec-extensions/selectors"
describe("findSchema", function () {
const state = fromJS({
resolvedSubtrees: {
components: {
schemas: {
resolvedSchema: {
type: "object",
properties: {
name: {
type: "string",
},
},
},
},
},
},
json: {
components: {
schemas: {
unresolvedSchema: {
$ref: "#/components/schemas/resolvedSchema",
},
resolvedSchema: {
type: "object",
properties: {
name: {
type: "string",
},
},
},
},
},
},
})
it("should get an unresolved schema", function () {
const result = findSchema(state, "unresolvedSchema")
expect(result).toEqual(
state.getIn(["json", "components", "schemas", "unresolvedSchema"])
)
})
it("should get a resolved schema", function () {
const result = findSchema(state, "resolvedSchema")
expect(result).toEqual(
state.getIn([
"resolvedSubtrees",
"components",
"schemas",
"resolvedSchema",
])
)
})
})