fix(oas3): attempt to render schemas not resolved by swagger-client (#9629)
Refs #9513
This commit is contained in:
@@ -2,6 +2,7 @@ import React from "react"
|
|||||||
import ImmutablePureComponent from "react-immutable-pure-component"
|
import ImmutablePureComponent from "react-immutable-pure-component"
|
||||||
import ImPropTypes from "react-immutable-proptypes"
|
import ImPropTypes from "react-immutable-proptypes"
|
||||||
import PropTypes from "prop-types"
|
import PropTypes from "prop-types"
|
||||||
|
import { Map } from "immutable"
|
||||||
|
|
||||||
import RollingLoadSVG from "core/assets/rolling-load.svg"
|
import RollingLoadSVG from "core/assets/rolling-load.svg"
|
||||||
|
|
||||||
@@ -55,20 +56,35 @@ export default class Model extends ImmutablePureComponent {
|
|||||||
const PrimitiveModel = getComponent("PrimitiveModel")
|
const PrimitiveModel = getComponent("PrimitiveModel")
|
||||||
let type = "object"
|
let type = "object"
|
||||||
let $$ref = schema && schema.get("$$ref")
|
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 we weren't passed a `name` but have a resolved ref, grab the name from the ref
|
||||||
if ( !name && $$ref ) {
|
if (!name && $$ref) {
|
||||||
name = this.getModelName( $$ref )
|
name = this.getModelName($$ref)
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* 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 we weren't passed a `schema` but have a ref, grab the schema from the ref
|
|
||||||
if ( !schema && $$ref ) {
|
|
||||||
schema = this.getRefSchema( name )
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if(!schema) {
|
if(!schema) {
|
||||||
return <span className="model model-title">
|
return <span className="model model-title">
|
||||||
<span className="model-title__text">{ displayName || name }</span>
|
<span className="model-title__text">{ displayName || name }</span>
|
||||||
<RollingLoadSVG height="20px" width="20px" />
|
{!$ref && <RollingLoadSVG height="20px" width="20px" />}
|
||||||
</span>
|
</span>
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -65,6 +65,7 @@ export default class ObjectModel extends Component {
|
|||||||
}
|
}
|
||||||
</span>)
|
</span>)
|
||||||
|
|
||||||
|
const allOf = specSelectors.isOAS3() ? schema.get("allOf") : null
|
||||||
const anyOf = specSelectors.isOAS3() ? schema.get("anyOf") : null
|
const anyOf = specSelectors.isOAS3() ? schema.get("anyOf") : null
|
||||||
const oneOf = specSelectors.isOAS3() ? schema.get("oneOf") : null
|
const oneOf = specSelectors.isOAS3() ? schema.get("oneOf") : null
|
||||||
const not = specSelectors.isOAS3() ? schema.get("not") : null
|
const not = specSelectors.isOAS3() ? schema.get("not") : null
|
||||||
@@ -194,6 +195,22 @@ export default class ObjectModel extends Component {
|
|||||||
</td>
|
</td>
|
||||||
</tr>
|
</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
|
!anyOf ? null
|
||||||
: <tr>
|
: <tr>
|
||||||
|
|||||||
@@ -47,6 +47,16 @@ export const servers = onlyOAS3(() => (system) => {
|
|||||||
return spec.get("servers", map)
|
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(
|
export const callbacksOperations = onlyOAS3(
|
||||||
(state, { callbacks, specPath }) =>
|
(state, { callbacks, specPath }) =>
|
||||||
(system) => {
|
(system) => {
|
||||||
|
|||||||
@@ -32,6 +32,10 @@ const OAS3NullSelector = onlyOAS3(nullSelector)
|
|||||||
* Wrappers
|
* Wrappers
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
export const findDefinition = onlyOAS3((state, schemaName) => (system) => {
|
||||||
|
return system.getSystem().specSelectors.findSchema(schemaName)
|
||||||
|
})
|
||||||
|
|
||||||
export const definitions = onlyOAS3(() => (system) => {
|
export const definitions = onlyOAS3(() => (system) => {
|
||||||
const spec = system.getSystem().specSelectors.specJson()
|
const spec = system.getSystem().specSelectors.specJson()
|
||||||
const schemas = spec.getIn(["components", "schemas"])
|
const schemas = spec.getIn(["components", "schemas"])
|
||||||
|
|||||||
@@ -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")
|
||||||
|
})
|
||||||
|
})
|
||||||
|
})
|
||||||
62964
test/e2e-cypress/static/documents/features/oas3-complex-spec.json
Normal file
62964
test/e2e-cypress/static/documents/features/oas3-complex-spec.json
Normal file
File diff suppressed because it is too large
Load Diff
62
test/unit/core/plugins/oas3/selectors.js
Normal file
62
test/unit/core/plugins/oas3/selectors.js
Normal 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",
|
||||||
|
])
|
||||||
|
)
|
||||||
|
})
|
||||||
|
})
|
||||||
Reference in New Issue
Block a user