fix: response examples should respect media-type (#6456)
* response sample generation should take content type into consideration for stringify
This commit is contained in:
@@ -4,6 +4,7 @@ import ImPropTypes from "react-immutable-proptypes"
|
|||||||
import cx from "classnames"
|
import cx from "classnames"
|
||||||
import { fromJS, Seq, Iterable, List, Map } from "immutable"
|
import { fromJS, Seq, Iterable, List, Map } from "immutable"
|
||||||
import { getSampleSchema, fromJSOrdered, stringify } from "core/utils"
|
import { getSampleSchema, fromJSOrdered, stringify } from "core/utils"
|
||||||
|
import { isFunc } from "../utils"
|
||||||
|
|
||||||
const getExampleComponent = ( sampleResponse, HighlightCode, getConfigs ) => {
|
const getExampleComponent = ( sampleResponse, HighlightCode, getConfigs ) => {
|
||||||
if (
|
if (
|
||||||
@@ -100,7 +101,6 @@ export default class Response extends React.Component {
|
|||||||
const Example = getComponent("Example")
|
const Example = getComponent("Example")
|
||||||
|
|
||||||
|
|
||||||
var sampleResponse
|
|
||||||
var schema, specPathWithPossibleSchema
|
var schema, specPathWithPossibleSchema
|
||||||
|
|
||||||
const activeContentType = this.state.responseContentType || contentType
|
const activeContentType = this.state.responseContentType || contentType
|
||||||
@@ -118,38 +118,63 @@ export default class Response extends React.Component {
|
|||||||
specPathWithPossibleSchema = response.has("schema") ? specPath.push("schema") : specPath
|
specPathWithPossibleSchema = response.has("schema") ? specPath.push("schema") : specPath
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const overrideSchemaExample = (oldSchema, newExample) => {
|
||||||
|
if(newExample === undefined)
|
||||||
|
return oldSchema
|
||||||
|
|
||||||
|
if(!oldSchema)
|
||||||
|
oldSchema = { }
|
||||||
|
|
||||||
|
if(isFunc(oldSchema.toJS))
|
||||||
|
oldSchema = oldSchema.toJS()
|
||||||
|
|
||||||
|
oldSchema.example = newExample && isFunc(newExample.toJS)
|
||||||
|
? newExample.toJS()
|
||||||
|
: newExample
|
||||||
|
return oldSchema
|
||||||
|
}
|
||||||
|
let mediaTypeExample
|
||||||
|
let shouldOverrideSchemaExample = false
|
||||||
|
let sampleSchema
|
||||||
|
let sampleGenConfig = {
|
||||||
|
includeReadOnly: true
|
||||||
|
}
|
||||||
|
|
||||||
// Goal: find an example value for `sampleResponse`
|
// Goal: find an example value for `sampleResponse`
|
||||||
if(isOAS3) {
|
if(isOAS3) {
|
||||||
const oas3SchemaForContentType = activeMediaType.get("schema", Map({}))
|
sampleSchema = activeMediaType.get("schema", Map({})).toJS()
|
||||||
|
|
||||||
if(examplesForMediaType) {
|
if(examplesForMediaType) {
|
||||||
const targetExamplesKey = this.getTargetExamplesKey()
|
const targetExamplesKey = this.getTargetExamplesKey()
|
||||||
const targetExample = examplesForMediaType.get(targetExamplesKey, Map({}))
|
mediaTypeExample = examplesForMediaType
|
||||||
sampleResponse = stringify(targetExample.get("value"))
|
.get(targetExamplesKey, Map({}))
|
||||||
|
.get("value")
|
||||||
|
if(mediaTypeExample === undefined) {
|
||||||
|
mediaTypeExample = examplesForMediaType.values().next().value
|
||||||
|
}
|
||||||
|
shouldOverrideSchemaExample = true
|
||||||
} else if(activeMediaType.get("example") !== undefined) {
|
} else if(activeMediaType.get("example") !== undefined) {
|
||||||
// use the example key's value
|
// use the example key's value
|
||||||
sampleResponse = stringify(activeMediaType.get("example"))
|
mediaTypeExample = activeMediaType.get("example")
|
||||||
} else {
|
shouldOverrideSchemaExample = true
|
||||||
// use an example value generated based on the schema
|
|
||||||
sampleResponse = getSampleSchema(oas3SchemaForContentType.toJS(), this.state.responseContentType, {
|
|
||||||
includeReadOnly: true
|
|
||||||
})
|
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
if(response.getIn(["examples", activeContentType])) {
|
sampleSchema = schema
|
||||||
sampleResponse = response.getIn(["examples", activeContentType])
|
sampleGenConfig = {...sampleGenConfig, includeWriteOnly: true}
|
||||||
} else {
|
const oldOASMediaTypeExample = response.getIn(["examples", activeContentType])
|
||||||
sampleResponse = schema ? getSampleSchema(
|
if(oldOASMediaTypeExample) {
|
||||||
schema.toJS(),
|
mediaTypeExample = oldOASMediaTypeExample
|
||||||
activeContentType,
|
shouldOverrideSchemaExample = true
|
||||||
{
|
|
||||||
includeReadOnly: true,
|
|
||||||
includeWriteOnly: true // writeOnly has no filtering effect in swagger 2.0
|
|
||||||
}
|
|
||||||
) : null
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const schemaForSampleGeneration = shouldOverrideSchemaExample
|
||||||
|
? overrideSchemaExample(sampleSchema, mediaTypeExample)
|
||||||
|
: sampleSchema
|
||||||
|
|
||||||
|
const sampleResponse = schemaForSampleGeneration
|
||||||
|
? getSampleSchema(schemaForSampleGeneration, activeContentType, sampleGenConfig)
|
||||||
|
: null
|
||||||
|
|
||||||
let example = getExampleComponent( sampleResponse, HighlightCode, getConfigs )
|
let example = getExampleComponent( sampleResponse, HighlightCode, getConfigs )
|
||||||
|
|
||||||
return (
|
return (
|
||||||
|
|||||||
52
test/e2e-cypress/static/documents/bugs/6442.yaml
Normal file
52
test/e2e-cypress/static/documents/bugs/6442.yaml
Normal file
@@ -0,0 +1,52 @@
|
|||||||
|
openapi: 3.0.1
|
||||||
|
info:
|
||||||
|
title: Example Swagger
|
||||||
|
version: '1.0'
|
||||||
|
servers:
|
||||||
|
- url: /api/v1
|
||||||
|
paths:
|
||||||
|
/xmlTest:
|
||||||
|
get:
|
||||||
|
summary: subscribes to a siri vm stream
|
||||||
|
operationId: xmlTest
|
||||||
|
parameters: []
|
||||||
|
responses:
|
||||||
|
'200':
|
||||||
|
description: Simple example
|
||||||
|
content:
|
||||||
|
application/xml:
|
||||||
|
schema:
|
||||||
|
type: object
|
||||||
|
xml:
|
||||||
|
name: root
|
||||||
|
properties:
|
||||||
|
x:
|
||||||
|
type: string
|
||||||
|
example:
|
||||||
|
x: what the f
|
||||||
|
examples:
|
||||||
|
x2:
|
||||||
|
summary: "xml not rendered via 'examples' keyword"
|
||||||
|
value:
|
||||||
|
x: should be xml
|
||||||
|
/xmlTest2:
|
||||||
|
get:
|
||||||
|
summary: subscribes to a siri vm stream
|
||||||
|
operationId: xmlTest2
|
||||||
|
parameters: []
|
||||||
|
responses:
|
||||||
|
'200':
|
||||||
|
description: Simple example
|
||||||
|
content:
|
||||||
|
application/xml:
|
||||||
|
schema:
|
||||||
|
type: object
|
||||||
|
xml:
|
||||||
|
name: root
|
||||||
|
properties:
|
||||||
|
x:
|
||||||
|
type: string
|
||||||
|
example:
|
||||||
|
x: what the f
|
||||||
|
example:
|
||||||
|
x: should be xml
|
||||||
33
test/e2e-cypress/tests/bugs/6442.js
Normal file
33
test/e2e-cypress/tests/bugs/6442.js
Normal file
@@ -0,0 +1,33 @@
|
|||||||
|
describe("#6442: 'Examples' keyword definitions can not be rendered as xml", () => {
|
||||||
|
it("should render response examples accourdingly to content-type xml", () => {
|
||||||
|
const xmlIndicator = "<x>should be xml</x>"
|
||||||
|
|
||||||
|
cy
|
||||||
|
.visit("?url=/documents/bugs/6442.yaml")
|
||||||
|
.get("#operations-default-xmlTest")
|
||||||
|
.click()
|
||||||
|
.get(".responses-wrapper")
|
||||||
|
.within(() => {
|
||||||
|
cy
|
||||||
|
.get(".microlight")
|
||||||
|
.should("include.text", xmlIndicator)
|
||||||
|
})
|
||||||
|
})
|
||||||
|
})
|
||||||
|
|
||||||
|
describe("#6442: 'Example' keyword definitions can not be rendered as xml", () => {
|
||||||
|
it("should render response examples accourdingly to content-type xml", () => {
|
||||||
|
const xmlIndicator = "<x>should be xml</x>"
|
||||||
|
|
||||||
|
cy
|
||||||
|
.visit("?url=/documents/bugs/6442.yaml")
|
||||||
|
.get("#operations-default-xmlTest2")
|
||||||
|
.click()
|
||||||
|
.get(".responses-wrapper")
|
||||||
|
.within(() => {
|
||||||
|
cy
|
||||||
|
.get(".microlight")
|
||||||
|
.should("include.text", xmlIndicator)
|
||||||
|
})
|
||||||
|
})
|
||||||
|
})
|
||||||
Reference in New Issue
Block a user