feat(rendering): gate rendering based on valid version identifiers (#4614)

* create VersionPragmaFilter component

* use VersionPragmaFilter in BaseLayout

* tighten version idenitifier constraints

* handle case where user specifies a valid `swagger` and `openapi` field

* add traceable class names for each message

* add tests

* linter fixes!

* UNRELATED CHANGE: remove travis short-circuit

* add bypass switch to VersionPragmaFilter
This commit is contained in:
kyle
2018-06-01 16:04:27 -07:00
committed by GitHub
parent a51bf1ea3e
commit a03c12786a
7 changed files with 161 additions and 13 deletions

View File

@@ -11,15 +11,6 @@ branches:
- master - master
- /^v\d+\.\d+(\.\d+)?(-\S*)?$/ - /^v\d+\.\d+(\.\d+)?(-\S*)?$/
install: "npm i && npm update" install: "npm i && npm update"
before_install:
- | # quickly pass if only documentation is being updated
if [ "$TRAVIS_PULL_REQUEST" != "false" ]; then
TRAVIS_COMMIT_RANGE="FETCH_HEAD...$TRAVIS_BRANCH"
git diff --name-only $TRAVIS_COMMIT_RANGE | grep -qvE '(\.md$)|(^(docs|examples))/' || {
echo "Only docs were updated, stopping build process."
exit
}
fi
before_deploy: before_deploy:
- npm run build - npm run build
env: env:

View File

@@ -40,6 +40,7 @@ export default class BaseLayout extends React.Component {
let servers = specSelectors.servers() let servers = specSelectors.servers()
let SvgAssets = getComponent("SvgAssets") let SvgAssets = getComponent("SvgAssets")
let VersionPragmaFilter = getComponent("VersionPragmaFilter")
let Info = getComponent("info") let Info = getComponent("info")
let Operations = getComponent("operations", true) let Operations = getComponent("operations", true)
let Models = getComponent("Models", true) let Models = getComponent("Models", true)
@@ -49,6 +50,9 @@ export default class BaseLayout extends React.Component {
let Servers = getComponent("Servers") let Servers = getComponent("Servers")
let Errors = getComponent("errors", true) let Errors = getComponent("errors", true)
let isSwagger2 = specSelectors.isSwagger2()
let isOAS3 = specSelectors.isOAS3()
let isLoading = specSelectors.loadingStatus() === "loading" let isLoading = specSelectors.loadingStatus() === "loading"
let isFailed = specSelectors.loadingStatus() === "failed" let isFailed = specSelectors.loadingStatus() === "failed"
let filter = layoutSelectors.currentFilter() let filter = layoutSelectors.currentFilter()
@@ -80,7 +84,7 @@ export default class BaseLayout extends React.Component {
<div className='swagger-ui'> <div className='swagger-ui'>
<SvgAssets /> <SvgAssets />
<div> <VersionPragmaFilter isSwagger2={isSwagger2} isOAS3={isOAS3} alsoShow={<Errors/>}>
<Errors/> <Errors/>
<Row className="information-container"> <Row className="information-container">
<Col mobile={12}> <Col mobile={12}>
@@ -142,7 +146,7 @@ export default class BaseLayout extends React.Component {
<Models/> <Models/>
</Col> </Col>
</Row> </Row>
</div> </VersionPragmaFilter>
</div> </div>
) )
} }

View File

@@ -0,0 +1,54 @@
import React from "react"
import PropTypes from "prop-types"
export default class VersionPragmaFilter extends React.PureComponent {
static propTypes = {
isSwagger2: PropTypes.bool.isRequired,
isOAS3: PropTypes.bool.isRequired,
bypass: PropTypes.bool,
alsoShow: PropTypes.element,
children: PropTypes.any,
}
static defaultProps = {
alsoShow: null,
children: null,
bypass: false,
}
render() {
const { bypass, isSwagger2, isOAS3, alsoShow } = this.props
if(bypass) {
return <div>{ this.props.children }</div>
}
if(isSwagger2 && isOAS3) {
return <div className="version-pragma">
{alsoShow}
<div className="version-pragma__message version-pragma__message--ambiguous">
<div>
<h3>Unable to render this definition</h3>
<p><code>swagger</code> and <code>openapi</code> fields cannot be present in the same Swagger or OpenAPI definition. Please remove one of the fields.</p>
<p>Supported version fields are <code>swagger: {"\"2.0\""}</code> and those that match <code>openapi: 3.0.n</code> (for example, <code>openapi: 3.0.0</code>).</p>
</div>
</div>
</div>
}
if(!isSwagger2 && !isOAS3) {
return <div className="version-pragma">
{alsoShow}
<div className="version-pragma__message version-pragma__message--missing">
<div>
<h3>Unable to render this definition</h3>
<p>The provided definition does not specify a valid version field.</p>
<p>Please indicate a valid Swagger or OpenAPI version field. Supported version fields are <code>swagger: {"\"2.0\""}</code> and those that match <code>openapi: 3.0.n</code> (for example, <code>openapi: 3.0.0</code>).</p>
</div>
</div>
</div>
}
return <div>{ this.props.children }</div>
}
}

View File

@@ -6,7 +6,7 @@ export function isOAS3(jsSpec) {
return false return false
} }
return oasVersion.startsWith("3") return oasVersion.startsWith("3.0.")
} }
export function isSwagger2(jsSpec) { export function isSwagger2(jsSpec) {
@@ -15,7 +15,7 @@ export function isSwagger2(jsSpec) {
return false return false
} }
return swaggerVersion.startsWith("2") return swaggerVersion.startsWith("2.0")
} }
export function OAS3ComponentWrapFactory(Component) { export function OAS3ComponentWrapFactory(Component) {

View File

@@ -66,6 +66,7 @@ import ArrayModel from "core/components/array-model"
import PrimitiveModel from "core/components/primitive-model" import PrimitiveModel from "core/components/primitive-model"
import Property from "core/components/property" import Property from "core/components/property"
import TryItOutButton from "core/components/try-it-out-button" import TryItOutButton from "core/components/try-it-out-button"
import VersionPragmaFilter from "core/components/version-pragma-filter"
import VersionStamp from "core/components/version-stamp" import VersionStamp from "core/components/version-stamp"
import DeepLink from "core/components/deep-link" import DeepLink from "core/components/deep-link"
import SvgAssets from "core/components/svg-assets" import SvgAssets from "core/components/svg-assets"
@@ -125,6 +126,7 @@ export default function() {
TryItOutButton, TryItOutButton,
Markdown, Markdown,
BaseLayout, BaseLayout,
VersionPragmaFilter,
VersionStamp, VersionStamp,
OperationExt, OperationExt,
OperationExtRow, OperationExtRow,

View File

@@ -796,3 +796,30 @@ a.nostyle {
cursor: pointer; cursor: pointer;
} }
} }
.version-pragma {
height: 100%;
padding: 5em 0px;
&__message {
display: flex;
justify-content: center;
height: 100%;
font-size: 1.2em;
text-align: center;
line-height: 1.5em;
padding: 0px .6em;
> div {
max-width: 55ch;
flex: 1;
}
code {
background-color: #dedede;
padding: 4px 4px 2px;
white-space: pre;
}
}
}

View File

@@ -0,0 +1,70 @@
/* eslint-env mocha */
import React from "react"
import expect, { createSpy } from "expect"
import { shallow } from "enzyme"
import { fromJS, Map } from "immutable"
import VersionPragmaFilter from "components/version-pragma-filter"
describe("<VersionPragmaFilter/>", function(){
it("renders children for a Swagger 2 definition", function(){
// When
let wrapper = shallow(
<VersionPragmaFilter isSwagger2={true} isOAS3={false}>
hello!
</VersionPragmaFilter>
)
// Then
expect(wrapper.find("div").length).toEqual(1)
expect(wrapper.find("div").text()).toEqual("hello!")
})
it("renders children for an OpenAPI 3 definition", function(){
// When
let wrapper = shallow(
<VersionPragmaFilter isSwagger2={false} isOAS3={true}>
hello!
</VersionPragmaFilter>
)
// Then
expect(wrapper.find("div").length).toEqual(1)
expect(wrapper.find("div").text()).toEqual("hello!")
})
it("renders children when a bypass prop is set", function(){
// When
let wrapper = shallow(
<VersionPragmaFilter bypass>
hello!
</VersionPragmaFilter>
)
// Then
expect(wrapper.find("div").length).toEqual(1)
expect(wrapper.find("div").text()).toEqual("hello!")
})
it("renders the correct message for an ambiguous-version definition", function(){
// When
let wrapper = shallow(
<VersionPragmaFilter isSwagger2={true} isOAS3={true}>
hello!
</VersionPragmaFilter>
)
// Then
expect(wrapper.find("div.version-pragma__message--ambiguous").length).toEqual(1)
expect(wrapper.find("div.version-pragma__message--missing").length).toEqual(0)
})
it("renders the correct message for a missing-version definition", function(){
// When
let wrapper = shallow(
<VersionPragmaFilter isSwagger2={false} isOAS3={false}>
hello!
</VersionPragmaFilter>
)
// Then
expect(wrapper.find("div.version-pragma__message--missing").length).toEqual(1)
expect(wrapper.find("div.version-pragma__message--ambiguous").length).toEqual(0)
})
})