Improve enum values for Enum Type in Swagger ReadOnly documentation (#4191)
* Adding enum values for Enum Type in Swagger ReadOnly documentation * Adding enum values for Enum Type in Swagger ReadOnly documentation (optimisation) and also adding default/example value * Add new display enums, defaults, and examples when not in TIO mode (another way to have enums values in swagger.json) * Fix npm test result * review corrections * fix: don't render parameter description if field is empty * use cross-version schema variable to access properties * pass className through Markdown component usage * add per-field classNames to Markdown for easier styling + testing * remove parameter Example field (out-of-scope for this PR) * get default value from schema instead of top-level parameter * tests: add e2e cases for swagger2 and oas3 * remove `swagger-petstore-enum.json` the purpose of this file lives on in the e2e test specs folder * add missing proptypes validation * use `classnames` to more effectively union class names
This commit is contained in:
@@ -107,40 +107,43 @@ export default class ParameterRow extends Component {
|
|||||||
|
|
||||||
let paramWithMeta = specSelectors.parameterWithMeta(pathMethod, param.get("name"), param.get("in"))
|
let paramWithMeta = specSelectors.parameterWithMeta(pathMethod, param.get("name"), param.get("in"))
|
||||||
|
|
||||||
let schema = param.get("schema")
|
let schema = isOAS3 && isOAS3() ? param.get("schema") : param
|
||||||
let type = isOAS3 && isOAS3() ? param.getIn(["schema", "type"]) : param.get("type")
|
let type = schema.get("type")
|
||||||
let isFormData = inType === "formData"
|
let isFormData = inType === "formData"
|
||||||
let isFormDataSupported = "FormData" in win
|
let isFormDataSupported = "FormData" in win
|
||||||
let required = param.get("required")
|
let required = param.get("required")
|
||||||
let itemType = param.getIn(isOAS3 && isOAS3() ? ["schema", "items", "type"] : ["items", "type"])
|
let itemType = schema.getIn(["items", "type"])
|
||||||
let value = paramWithMeta ? paramWithMeta.get("value") : ""
|
let value = paramWithMeta ? paramWithMeta.get("value") : ""
|
||||||
let extensions = getExtensions(param)
|
let extensions = getExtensions(param)
|
||||||
|
|
||||||
let paramItems // undefined
|
let paramItems // undefined
|
||||||
let paramItemsEnum // undefined
|
let paramEnum // undefined
|
||||||
let isDisplayParamItemsEnum = false
|
let paramDefaultValue // undefined
|
||||||
|
let paramExample // undefined
|
||||||
|
let isDisplayParamEnum = false
|
||||||
|
|
||||||
if ( param !== undefined ) {
|
if ( param !== undefined ) {
|
||||||
paramItems = param.get("items")
|
paramItems = schema.get("items")
|
||||||
}
|
}
|
||||||
if ( paramItems !== undefined ) {
|
|
||||||
paramItemsEnum = param.get("items").get("enum")
|
if (paramItems !== undefined) {
|
||||||
}
|
paramEnum = paramItems.get("enum")
|
||||||
if ( paramItemsEnum !== undefined ) {
|
paramDefaultValue = paramItems.get("default")
|
||||||
if (paramItemsEnum.size > 0) {
|
} else {
|
||||||
isDisplayParamItemsEnum = true
|
paramEnum = schema.get("enum")
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if ( paramEnum !== undefined && paramEnum.size > 0) {
|
||||||
|
isDisplayParamEnum = true
|
||||||
}
|
}
|
||||||
|
|
||||||
// Default and Example Value for readonly doc
|
// Default and Example Value for readonly doc
|
||||||
let paramDefaultValue // undefined
|
|
||||||
let paramExample // undefined
|
|
||||||
if ( param !== undefined ) {
|
if ( param !== undefined ) {
|
||||||
paramDefaultValue = param.get("default")
|
paramDefaultValue = schema.get("default")
|
||||||
paramExample = param.get("example")
|
paramExample = param.get("example")
|
||||||
|
if (paramExample === undefined) {
|
||||||
|
paramExample = param.get("x-example")
|
||||||
}
|
}
|
||||||
|
|
||||||
if (isDisplayParamItemsEnum) { // if we have an array, default value is in "items"
|
|
||||||
paramDefaultValue = paramItems.get("default")
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return (
|
return (
|
||||||
@@ -159,23 +162,18 @@ export default class ParameterRow extends Component {
|
|||||||
</td>
|
</td>
|
||||||
|
|
||||||
<td className="col parameters-col_description">
|
<td className="col parameters-col_description">
|
||||||
<Markdown source={ param.get("description") }/>
|
{ param.get("description") ? <Markdown source={ param.get("description") }/> : null }
|
||||||
|
|
||||||
{ (bodyParam || !isExecute) && isDisplayParamItemsEnum ?
|
{ (bodyParam || !isExecute) && isDisplayParamEnum ?
|
||||||
<Markdown source={
|
<Markdown className="parameter__enum" source={
|
||||||
"<i>Available values</i>: " + paramItemsEnum.map(function(item) {
|
"<i>Available values</i> : " + paramEnum.map(function(item) {
|
||||||
return item
|
return item
|
||||||
}).toArray().join(", ")}/>
|
}).toArray().join(", ")}/>
|
||||||
: null
|
: null
|
||||||
}
|
}
|
||||||
|
|
||||||
{ (bodyParam || !isExecute) && paramDefaultValue !== undefined ?
|
{ (bodyParam || !isExecute) && paramDefaultValue !== undefined ?
|
||||||
<Markdown source={"<i>Default value</i>: " + paramDefaultValue}/>
|
<Markdown className="parameter__default" source={"<i>Default value</i> : " + paramDefaultValue}/>
|
||||||
: null
|
|
||||||
}
|
|
||||||
|
|
||||||
{ (bodyParam || !isExecute) && paramExample !== undefined ?
|
|
||||||
<Markdown source={"<i>Example</i>: " + paramExample}/>
|
|
||||||
: null
|
: null
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -189,7 +187,7 @@ export default class ParameterRow extends Component {
|
|||||||
description={param.get("description") ? `${param.get("name")} - ${param.get("description")}` : `${param.get("name")}`}
|
description={param.get("description") ? `${param.get("name")} - ${param.get("description")}` : `${param.get("name")}`}
|
||||||
onChange={ this.onChangeWrapper }
|
onChange={ this.onChangeWrapper }
|
||||||
errors={ paramWithMeta.get("errors") }
|
errors={ paramWithMeta.get("errors") }
|
||||||
schema={ isOAS3 && isOAS3() ? param.get("schema") : param }/>
|
schema={ schema }/>
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@@ -2,11 +2,12 @@ import React from "react"
|
|||||||
import PropTypes from "prop-types"
|
import PropTypes from "prop-types"
|
||||||
import Remarkable from "remarkable"
|
import Remarkable from "remarkable"
|
||||||
import sanitize from "sanitize-html"
|
import sanitize from "sanitize-html"
|
||||||
|
import cx from "classnames"
|
||||||
|
|
||||||
// eslint-disable-next-line no-useless-escape
|
// eslint-disable-next-line no-useless-escape
|
||||||
const isPlainText = (str) => /^[A-Z\s0-9!?\.]+$/gi.test(str)
|
const isPlainText = (str) => /^[A-Z\s0-9!?\.]+$/gi.test(str)
|
||||||
|
|
||||||
function Markdown({ source }) {
|
function Markdown({ source, className = "" }) {
|
||||||
if(isPlainText(source)) {
|
if(isPlainText(source)) {
|
||||||
// If the source text is not Markdown,
|
// If the source text is not Markdown,
|
||||||
// let's save some time and just render it.
|
// let's save some time and just render it.
|
||||||
@@ -28,12 +29,13 @@ function Markdown({ source }) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div className="markdown" dangerouslySetInnerHTML={{ __html: sanitized }}></div>
|
<div className={cx(className, "markdown")} dangerouslySetInnerHTML={{ __html: sanitized }}></div>
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
Markdown.propTypes = {
|
Markdown.propTypes = {
|
||||||
source: PropTypes.string.isRequired
|
source: PropTypes.string.isRequired,
|
||||||
|
className: PropTypes.string.isRequired
|
||||||
}
|
}
|
||||||
|
|
||||||
export default Markdown
|
export default Markdown
|
||||||
|
|||||||
@@ -1,11 +1,12 @@
|
|||||||
import React from "react"
|
import React from "react"
|
||||||
import PropTypes from "prop-types"
|
import PropTypes from "prop-types"
|
||||||
import ReactMarkdown from "react-markdown"
|
import ReactMarkdown from "react-markdown"
|
||||||
|
import cx from "classnames"
|
||||||
import { Parser, HtmlRenderer } from "commonmark"
|
import { Parser, HtmlRenderer } from "commonmark"
|
||||||
import { OAS3ComponentWrapFactory } from "../helpers"
|
import { OAS3ComponentWrapFactory } from "../helpers"
|
||||||
import { sanitizer } from "core/components/providers/markdown"
|
import { sanitizer } from "core/components/providers/markdown"
|
||||||
|
|
||||||
export const Markdown = ({ source }) => {
|
export const Markdown = ({ source, className = "" }) => {
|
||||||
if ( source ) {
|
if ( source ) {
|
||||||
const parser = new Parser()
|
const parser = new Parser()
|
||||||
const writer = new HtmlRenderer()
|
const writer = new HtmlRenderer()
|
||||||
@@ -19,14 +20,15 @@ export const Markdown = ({ source }) => {
|
|||||||
return (
|
return (
|
||||||
<ReactMarkdown
|
<ReactMarkdown
|
||||||
source={sanitized}
|
source={sanitized}
|
||||||
className={"renderedMarkdown"}
|
className={cx(className, "renderedMarkdown")}
|
||||||
/>
|
/>
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
return null
|
return null
|
||||||
}
|
}
|
||||||
Markdown.propTypes = {
|
Markdown.propTypes = {
|
||||||
source: PropTypes.string
|
source: PropTypes.string,
|
||||||
|
className: PropTypes.string,
|
||||||
}
|
}
|
||||||
|
|
||||||
export default OAS3ComponentWrapFactory(Markdown)
|
export default OAS3ComponentWrapFactory(Markdown)
|
||||||
58
test/e2e/scenarios/features/parameter-enum-rendering.js
Normal file
58
test/e2e/scenarios/features/parameter-enum-rendering.js
Normal file
@@ -0,0 +1,58 @@
|
|||||||
|
describe("parameter enum rendering", function () {
|
||||||
|
describe("swagger 2.0", () => {
|
||||||
|
beforeEach(function (client, done) {
|
||||||
|
client
|
||||||
|
.url("localhost:3230")
|
||||||
|
.waitForElementVisible(".download-url-input", 10000)
|
||||||
|
.pause(1000)
|
||||||
|
.clearValue(".download-url-input")
|
||||||
|
.setValue(".download-url-input", "http://localhost:3230/test-specs/features/parameter-enum-rendering.swagger.yaml")
|
||||||
|
.click("button.download-url-button")
|
||||||
|
.pause(1000)
|
||||||
|
|
||||||
|
done()
|
||||||
|
})
|
||||||
|
afterEach(function (client, done) {
|
||||||
|
done()
|
||||||
|
})
|
||||||
|
it("reveals a string parameter's enums and defaults when viewing that parameter", function (client) {
|
||||||
|
client.waitForElementVisible(".opblock-tag-section", 10000)
|
||||||
|
.assert.containsText(".opblock-summary-path span", "/report")
|
||||||
|
.click(".opblock")
|
||||||
|
.waitForElementVisible(".opblock.is-open", 5000)
|
||||||
|
.pause(500)
|
||||||
|
.assert.containsText("div.parameter__enum", "today, yesterday, lastweek")
|
||||||
|
.assert.containsText("div.parameter__default", "today")
|
||||||
|
|
||||||
|
client.end()
|
||||||
|
})
|
||||||
|
})
|
||||||
|
describe("openapi 3.0", () => {
|
||||||
|
beforeEach(function (client, done) {
|
||||||
|
client
|
||||||
|
.url("localhost:3230")
|
||||||
|
.waitForElementVisible(".download-url-input", 10000)
|
||||||
|
.pause(1000)
|
||||||
|
.clearValue(".download-url-input")
|
||||||
|
.setValue(".download-url-input", "http://localhost:3230/test-specs/features/parameter-enum-rendering.openapi.yaml")
|
||||||
|
.click("button.download-url-button")
|
||||||
|
.pause(1000)
|
||||||
|
|
||||||
|
done()
|
||||||
|
})
|
||||||
|
afterEach(function (client, done) {
|
||||||
|
done()
|
||||||
|
})
|
||||||
|
it("reveals a string parameter's enums and defaults when viewing that parameter", function (client) {
|
||||||
|
client.waitForElementVisible(".opblock-tag-section", 10000)
|
||||||
|
.assert.containsText(".opblock-summary-path span", "/report")
|
||||||
|
.click(".opblock")
|
||||||
|
.waitForElementVisible(".opblock.is-open", 5000)
|
||||||
|
.pause(500)
|
||||||
|
.assert.containsText("div.parameter__enum", "today, yesterday, lastweek")
|
||||||
|
.assert.containsText("div.parameter__default", "today")
|
||||||
|
|
||||||
|
client.end()
|
||||||
|
})
|
||||||
|
})
|
||||||
|
})
|
||||||
@@ -0,0 +1,21 @@
|
|||||||
|
openapi: 3.0.0
|
||||||
|
info:
|
||||||
|
title: test
|
||||||
|
version: 0.0.0
|
||||||
|
paths:
|
||||||
|
/report:
|
||||||
|
get:
|
||||||
|
parameters:
|
||||||
|
- in: query
|
||||||
|
name: rel_date
|
||||||
|
required: true
|
||||||
|
schema:
|
||||||
|
type: string
|
||||||
|
default: today
|
||||||
|
enum:
|
||||||
|
- today
|
||||||
|
- yesterday
|
||||||
|
- lastweek
|
||||||
|
responses:
|
||||||
|
'200':
|
||||||
|
description: OK
|
||||||
@@ -0,0 +1,20 @@
|
|||||||
|
swagger: '2.0'
|
||||||
|
info:
|
||||||
|
title: test
|
||||||
|
version: 0.0.0
|
||||||
|
paths:
|
||||||
|
/report:
|
||||||
|
get:
|
||||||
|
parameters:
|
||||||
|
- in: query
|
||||||
|
name: rel_date
|
||||||
|
required: true
|
||||||
|
type: string
|
||||||
|
default: today
|
||||||
|
enum:
|
||||||
|
- today
|
||||||
|
- yesterday
|
||||||
|
- lastweek
|
||||||
|
responses:
|
||||||
|
200:
|
||||||
|
description: OK
|
||||||
Reference in New Issue
Block a user