-
}>
-
+ }
+ >
+
-
+
{hasServers || hasSchemes || hasSecurityDefinitions ? (
- {hasServers ? (
) : null}
- {hasSchemes ? (
) : null}
- {hasSecurityDefinitions ? (
) : null}
+ {hasServers ?
: null}
+ {hasSchemes ?
: null}
+ {hasSecurityDefinitions ?
: null}
) : null}
-
+
-
-
+
+
- { isOpenAPI31 &&
+ {isOAS31 && (
-
+
- }
+ )}
-
-
+
+
diff --git a/src/core/components/license.jsx b/src/core/components/license.jsx
new file mode 100644
index 00000000..d5b3a015
--- /dev/null
+++ b/src/core/components/license.jsx
@@ -0,0 +1,41 @@
+/**
+ * @prettier
+ */
+import React from "react"
+import PropTypes from "prop-types"
+import { safeBuildUrl } from "core/utils/url"
+import { sanitizeUrl } from "core/utils"
+
+class License extends React.Component {
+ static propTypes = {
+ license: PropTypes.object,
+ getComponent: PropTypes.func.isRequired,
+ specSelectors: PropTypes.object.isRequired,
+ selectedServer: PropTypes.string,
+ url: PropTypes.string.isRequired,
+ }
+
+ render() {
+ const { license, getComponent, selectedServer, url: specUrl } = this.props
+ const name = license.get("name", "License")
+ const url = safeBuildUrl(license.get("url"), specUrl, { selectedServer })
+
+ const Link = getComponent("Link")
+
+ return (
+
+ {url ? (
+
+
+ {name}
+
+
+ ) : (
+
{name}
+ )}
+
+ )
+ }
+}
+
+export default License
diff --git a/src/core/plugins/oas3/auth-extensions/wrap-selectors.js b/src/core/plugins/oas3/auth-extensions/wrap-selectors.js
index f7b2ea75..e09b4fdf 100644
--- a/src/core/plugins/oas3/auth-extensions/wrap-selectors.js
+++ b/src/core/plugins/oas3/auth-extensions/wrap-selectors.js
@@ -1,6 +1,5 @@
import { createSelector } from "reselect"
import { List, Map, fromJS } from "immutable"
-import { isOAS3 as isOAS3Helper } from "../helpers"
// Helpers
@@ -9,8 +8,7 @@ const state = state => state
function onlyOAS3(selector) {
return (ori, system) => (...args) => {
- const spec = system.getSystem().specSelectors.specJson()
- if(isOAS3Helper(spec)) {
+ if(system.getSystem().specSelectors.isOAS3()) {
// Pass the spec plugin state to Reselect to trigger on securityDefinitions update
let resolvedSchemes = system.getState().getIn(["spec", "resolvedSubtrees",
"components", "securitySchemes"])
diff --git a/src/core/plugins/oas3/components/index.js b/src/core/plugins/oas3/components/index.js
index 49cf8460..ff180b7e 100644
--- a/src/core/plugins/oas3/components/index.js
+++ b/src/core/plugins/oas3/components/index.js
@@ -6,7 +6,6 @@ import ServersContainer from "./servers-container"
import RequestBodyEditor from "./request-body-editor"
import HttpAuth from "./http-auth"
import OperationServers from "./operation-servers"
-import Webhooks from "./webhooks"
export default {
Callbacks,
@@ -17,5 +16,4 @@ export default {
RequestBodyEditor,
OperationServers,
operationLink: OperationLink,
- Webhooks
}
diff --git a/src/core/plugins/oas3/helpers.jsx b/src/core/plugins/oas3/helpers.jsx
index 253973a5..79b95722 100644
--- a/src/core/plugins/oas3/helpers.jsx
+++ b/src/core/plugins/oas3/helpers.jsx
@@ -1,44 +1,27 @@
+/**
+ * @prettier
+ */
import React from "react"
-export function isOpenAPI30(jsSpec) {
+export function isOAS30(jsSpec) {
const oasVersion = jsSpec.get("openapi")
- if (typeof oasVersion !== "string") {
- return false
- }
- return oasVersion.startsWith("3.0.") && oasVersion.length > 4
-}
-export function isOpenAPI31(jsSpec) {
- const oasVersion = jsSpec.get("openapi")
- if (typeof oasVersion !== "string") {
- return false
- }
- return oasVersion.startsWith("3.1.") && oasVersion.length > 4
-}
-
-export function isOAS3(jsSpec) {
- const oasVersion = jsSpec.get("openapi")
- if(typeof oasVersion !== "string") {
- return false
- }
- return isOpenAPI30(jsSpec) || isOpenAPI31(jsSpec)
+ return (
+ typeof oasVersion === "string" &&
+ /^3\.0\.([0123])(?:-rc[012])?$/.test(oasVersion)
+ )
}
export function isSwagger2(jsSpec) {
const swaggerVersion = jsSpec.get("swagger")
- if(typeof swaggerVersion !== "string") {
- return false
- }
- return swaggerVersion.startsWith("2.0")
+ return typeof swaggerVersion === "string" && swaggerVersion === "2.0"
}
export function OAS3ComponentWrapFactory(Component) {
return (Ori, system) => (props) => {
- if(system && system.specSelectors && system.specSelectors.specJson) {
- const spec = system.specSelectors.specJson()
-
- if(isOAS3(spec)) {
+ if (typeof system.specSelectors?.isOAS3 === "function") {
+ if (system.specSelectors.isOAS3()) {
return
} else {
return
diff --git a/src/core/plugins/oas3/index.js b/src/core/plugins/oas3/index.js
index 29170de4..c96fac6f 100644
--- a/src/core/plugins/oas3/index.js
+++ b/src/core/plugins/oas3/index.js
@@ -1,31 +1,32 @@
-// import reducers from "./reducers"
-// import * as actions from "./actions"
+/**
+ * @prettier
+ */
import * as specWrapSelectors from "./spec-extensions/wrap-selectors"
import * as authWrapSelectors from "./auth-extensions/wrap-selectors"
import * as specSelectors from "./spec-extensions/selectors"
import components from "./components"
import wrapComponents from "./wrap-components"
-import * as oas3Actions from "./actions"
-import * as oas3Selectors from "./selectors"
-import oas3Reducers from "./reducers"
+import * as actions from "./actions"
+import * as selectors from "./selectors"
+import reducers from "./reducers"
-export default function() {
+export default function () {
return {
components,
wrapComponents,
statePlugins: {
spec: {
wrapSelectors: specWrapSelectors,
- selectors: specSelectors
+ selectors: specSelectors,
},
auth: {
- wrapSelectors: authWrapSelectors
+ wrapSelectors: authWrapSelectors,
},
oas3: {
- actions: oas3Actions,
- reducers: oas3Reducers,
- selectors: oas3Selectors,
- }
- }
+ actions,
+ reducers,
+ selectors,
+ },
+ },
}
}
diff --git a/src/core/plugins/oas3/selectors.js b/src/core/plugins/oas3/selectors.js
index 792b844e..ba2e7d2e 100644
--- a/src/core/plugins/oas3/selectors.js
+++ b/src/core/plugins/oas3/selectors.js
@@ -1,41 +1,53 @@
+/**
+ * @prettier
+ */
import { OrderedMap, Map, List } from "immutable"
-import { isOAS3 as isOAS3Helper } from "./helpers"
import { getDefaultRequestBodyValue } from "./components/request-body"
import { stringify } from "../../utils"
// Helpers
function onlyOAS3(selector) {
- return (...args) => (system) => {
- const spec = system.getSystem().specSelectors.specJson()
- if(isOAS3Helper(spec)) {
- return selector(...args)
- } else {
- return null
+ return (...args) =>
+ (system) => {
+ if (system.getSystem().specSelectors.isOAS3()) {
+ return selector(...args)
+ } else {
+ return null
+ }
}
- }
}
function validateRequestBodyIsRequired(selector) {
- return (...args) => (system) => {
- const specJson = system.getSystem().specSelectors.specJson()
- const argsList = [...args]
- // expect argsList[0] = state
- let pathMethod = argsList[1] || []
- let isOas3RequestBodyRequired = specJson.getIn(["paths", ...pathMethod, "requestBody", "required"])
+ return (...args) =>
+ (system) => {
+ const specJson = system.getSystem().specSelectors.specJson()
+ const argsList = [...args]
+ // expect argsList[0] = state
+ let pathMethod = argsList[1] || []
+ let isOas3RequestBodyRequired = specJson.getIn([
+ "paths",
+ ...pathMethod,
+ "requestBody",
+ "required",
+ ])
- if (isOas3RequestBodyRequired) {
- return selector(...args)
- } else {
- // validation pass b/c not required
- return true
+ if (isOas3RequestBodyRequired) {
+ return selector(...args)
+ } else {
+ // validation pass b/c not required
+ return true
+ }
}
- }
}
const validateRequestBodyValueExists = (state, pathMethod) => {
pathMethod = pathMethod || []
- let oas3RequestBodyValue = state.getIn(["requestData", ...pathMethod, "bodyValue"])
+ let oas3RequestBodyValue = state.getIn([
+ "requestData",
+ ...pathMethod,
+ "bodyValue",
+ ])
// context: bodyValue can be a String, or a Map
if (!oas3RequestBodyValue) {
return false
@@ -44,68 +56,85 @@ const validateRequestBodyValueExists = (state, pathMethod) => {
return true
}
-
export const selectedServer = onlyOAS3((state, namespace) => {
- const path = namespace ? [namespace, "selectedServer"] : ["selectedServer"]
- return state.getIn(path) || ""
- }
-)
+ const path = namespace ? [namespace, "selectedServer"] : ["selectedServer"]
+ return state.getIn(path) || ""
+})
export const requestBodyValue = onlyOAS3((state, path, method) => {
- return state.getIn(["requestData", path, method, "bodyValue"]) || null
- }
-)
+ return state.getIn(["requestData", path, method, "bodyValue"]) || null
+})
export const shouldRetainRequestBodyValue = onlyOAS3((state, path, method) => {
- return state.getIn(["requestData", path, method, "retainBodyValue"]) || false
- }
-)
+ return state.getIn(["requestData", path, method, "retainBodyValue"]) || false
+})
-export const selectDefaultRequestBodyValue = (state, path, method) => (system) => {
- const {oas3Selectors, specSelectors} = system.getSystem()
- const spec = specSelectors.specJson()
- if(isOAS3Helper(spec)) {
- const currentMediaType = oas3Selectors.requestContentType(path, method)
- if (currentMediaType) {
- return getDefaultRequestBodyValue(
- specSelectors.specResolvedSubtree(["paths", path, method, "requestBody"]),
- currentMediaType,
- oas3Selectors.activeExamplesMember(
- path, method,
- "requestBody",
- "requestBody",
+export const selectDefaultRequestBodyValue =
+ (state, path, method) => (system) => {
+ const { oas3Selectors, specSelectors } = system.getSystem()
+
+ if (specSelectors.isOAS3()) {
+ const currentMediaType = oas3Selectors.requestContentType(path, method)
+ if (currentMediaType) {
+ return getDefaultRequestBodyValue(
+ specSelectors.specResolvedSubtree([
+ "paths",
+ path,
+ method,
+ "requestBody",
+ ]),
+ currentMediaType,
+ oas3Selectors.activeExamplesMember(
+ path,
+ method,
+ "requestBody",
+ "requestBody"
+ )
)
- )
+ }
}
+ return null
}
- return null
-}
export const hasUserEditedBody = (state, path, method) => (system) => {
- const {oas3Selectors, specSelectors} = system.getSystem()
- const spec = specSelectors.specJson()
- if(isOAS3Helper(spec)) {
+ const { oas3Selectors, specSelectors } = system.getSystem()
+
+ if (specSelectors.isOAS3()) {
let userHasEditedBody = false
const currentMediaType = oas3Selectors.requestContentType(path, method)
let userEditedRequestBody = oas3Selectors.requestBodyValue(path, method)
if (Map.isMap(userEditedRequestBody)) {
// context is not application/json media-type
- userEditedRequestBody = stringify(userEditedRequestBody.mapEntries((kv) => Map.isMap(kv[1]) ? [kv[0], kv[1].get("value")] : kv).toJS())
+ userEditedRequestBody = stringify(
+ userEditedRequestBody
+ .mapEntries((kv) =>
+ Map.isMap(kv[1]) ? [kv[0], kv[1].get("value")] : kv
+ )
+ .toJS()
+ )
}
- if(List.isList(userEditedRequestBody)) {
+ if (List.isList(userEditedRequestBody)) {
userEditedRequestBody = stringify(userEditedRequestBody)
}
if (currentMediaType) {
const currentMediaTypeDefaultBodyValue = getDefaultRequestBodyValue(
- specSelectors.specResolvedSubtree(["paths", path, method, "requestBody"]),
+ specSelectors.specResolvedSubtree([
+ "paths",
+ path,
+ method,
+ "requestBody",
+ ]),
currentMediaType,
oas3Selectors.activeExamplesMember(
- path, method,
- "requestBody",
+ path,
+ method,
"requestBody",
+ "requestBody"
)
)
- userHasEditedBody = !!userEditedRequestBody && userEditedRequestBody !== currentMediaTypeDefaultBodyValue
+ userHasEditedBody =
+ !!userEditedRequestBody &&
+ userEditedRequestBody !== currentMediaTypeDefaultBodyValue
}
return userHasEditedBody
} else {
@@ -114,106 +143,114 @@ export const hasUserEditedBody = (state, path, method) => (system) => {
}
export const requestBodyInclusionSetting = onlyOAS3((state, path, method) => {
- return state.getIn(["requestData", path, method, "bodyInclusion"]) || Map()
- }
-)
+ return state.getIn(["requestData", path, method, "bodyInclusion"]) || Map()
+})
export const requestBodyErrors = onlyOAS3((state, path, method) => {
- return state.getIn(["requestData", path, method, "errors"]) || null
- }
-)
+ return state.getIn(["requestData", path, method, "errors"]) || null
+})
-export const activeExamplesMember = onlyOAS3((state, path, method, type, name) => {
- return state.getIn(["examples", path, method, type, name, "activeExample"]) || null
+export const activeExamplesMember = onlyOAS3(
+ (state, path, method, type, name) => {
+ return (
+ state.getIn(["examples", path, method, type, name, "activeExample"]) ||
+ null
+ )
}
)
export const requestContentType = onlyOAS3((state, path, method) => {
- return state.getIn(["requestData", path, method, "requestContentType"]) || null
- }
-)
+ return (
+ state.getIn(["requestData", path, method, "requestContentType"]) || null
+ )
+})
export const responseContentType = onlyOAS3((state, path, method) => {
- return state.getIn(["requestData", path, method, "responseContentType"]) || null
- }
-)
+ return (
+ state.getIn(["requestData", path, method, "responseContentType"]) || null
+ )
+})
export const serverVariableValue = onlyOAS3((state, locationData, key) => {
- let path
+ let path
- // locationData may take one of two forms, for backwards compatibility
- // Object: ({server, namespace?}) or String:(server)
- if(typeof locationData !== "string") {
- const { server, namespace } = locationData
- if(namespace) {
- path = [namespace, "serverVariableValues", server, key]
- } else {
- path = ["serverVariableValues", server, key]
- }
+ // locationData may take one of two forms, for backwards compatibility
+ // Object: ({server, namespace?}) or String:(server)
+ if (typeof locationData !== "string") {
+ const { server, namespace } = locationData
+ if (namespace) {
+ path = [namespace, "serverVariableValues", server, key]
} else {
- const server = locationData
path = ["serverVariableValues", server, key]
}
-
- return state.getIn(path) || null
+ } else {
+ const server = locationData
+ path = ["serverVariableValues", server, key]
}
-)
+
+ return state.getIn(path) || null
+})
export const serverVariables = onlyOAS3((state, locationData) => {
- let path
+ let path
- // locationData may take one of two forms, for backwards compatibility
- // Object: ({server, namespace?}) or String:(server)
- if(typeof locationData !== "string") {
- const { server, namespace } = locationData
- if(namespace) {
- path = [namespace, "serverVariableValues", server]
- } else {
- path = ["serverVariableValues", server]
- }
+ // locationData may take one of two forms, for backwards compatibility
+ // Object: ({server, namespace?}) or String:(server)
+ if (typeof locationData !== "string") {
+ const { server, namespace } = locationData
+ if (namespace) {
+ path = [namespace, "serverVariableValues", server]
} else {
- const server = locationData
path = ["serverVariableValues", server]
}
-
- return state.getIn(path) || OrderedMap()
+ } else {
+ const server = locationData
+ path = ["serverVariableValues", server]
}
-)
+
+ return state.getIn(path) || OrderedMap()
+})
export const serverEffectiveValue = onlyOAS3((state, locationData) => {
- var varValues, serverValue
+ var varValues, serverValue
- // locationData may take one of two forms, for backwards compatibility
- // Object: ({server, namespace?}) or String:(server)
- if(typeof locationData !== "string") {
- const { server, namespace } = locationData
- serverValue = server
- if(namespace) {
- varValues = state.getIn([namespace, "serverVariableValues", serverValue])
- } else {
- varValues = state.getIn(["serverVariableValues", serverValue])
- }
+ // locationData may take one of two forms, for backwards compatibility
+ // Object: ({server, namespace?}) or String:(server)
+ if (typeof locationData !== "string") {
+ const { server, namespace } = locationData
+ serverValue = server
+ if (namespace) {
+ varValues = state.getIn([namespace, "serverVariableValues", serverValue])
} else {
- serverValue = locationData
varValues = state.getIn(["serverVariableValues", serverValue])
}
-
- varValues = varValues || OrderedMap()
- let str = serverValue
-
- varValues.map((val, key) => {
- str = str.replace(new RegExp(`{${key}}`, "g"), val)
- })
-
- return str
+ } else {
+ serverValue = locationData
+ varValues = state.getIn(["serverVariableValues", serverValue])
}
-)
+
+ varValues = varValues || OrderedMap()
+ let str = serverValue
+
+ varValues.map((val, key) => {
+ str = str.replace(new RegExp(`{${key}}`, "g"), val)
+ })
+
+ return str
+})
export const validateBeforeExecute = validateRequestBodyIsRequired(
(state, pathMethod) => validateRequestBodyValueExists(state, pathMethod)
)
-export const validateShallowRequired = (state, { oas3RequiredRequestBodyContentType, oas3RequestContentType, oas3RequestBodyValue} ) => {
+export const validateShallowRequired = (
+ state,
+ {
+ oas3RequiredRequestBodyContentType,
+ oas3RequestContentType,
+ oas3RequestBodyValue,
+ }
+) => {
let missingRequiredKeys = []
// context: json => String; urlencoded, form-data => Map
if (!Map.isMap(oas3RequestBodyValue)) {
@@ -221,16 +258,19 @@ export const validateShallowRequired = (state, { oas3RequiredRequestBodyContentT
}
let requiredKeys = []
// Cycle through list of possible contentTypes for matching contentType and defined requiredKeys
- Object.keys(oas3RequiredRequestBodyContentType.requestContentType).forEach((contentType) => {
- if (contentType === oas3RequestContentType) {
- let contentTypeVal = oas3RequiredRequestBodyContentType.requestContentType[contentType]
- contentTypeVal.forEach((requiredKey) => {
- if (requiredKeys.indexOf(requiredKey) < 0 ) {
- requiredKeys.push(requiredKey)
- }
- })
+ Object.keys(oas3RequiredRequestBodyContentType.requestContentType).forEach(
+ (contentType) => {
+ if (contentType === oas3RequestContentType) {
+ let contentTypeVal =
+ oas3RequiredRequestBodyContentType.requestContentType[contentType]
+ contentTypeVal.forEach((requiredKey) => {
+ if (requiredKeys.indexOf(requiredKey) < 0) {
+ requiredKeys.push(requiredKey)
+ }
+ })
+ }
}
- })
+ )
requiredKeys.forEach((key) => {
let requiredKeyValue = oas3RequestBodyValue.getIn([key, "value"])
if (!requiredKeyValue) {
diff --git a/src/core/plugins/oas3/spec-extensions/selectors.js b/src/core/plugins/oas3/spec-extensions/selectors.js
index b7c85ee0..587a11a9 100644
--- a/src/core/plugins/oas3/spec-extensions/selectors.js
+++ b/src/core/plugins/oas3/spec-extensions/selectors.js
@@ -1,72 +1,39 @@
-import { createSelector } from "reselect"
import { Map } from "immutable"
-import { isOAS3 as isOAS3Helper, isOpenAPI31 as isOpenAPI31Helper, isSwagger2 as isSwagger2Helper } from "../helpers"
+import { isSwagger2 as isSwagger2Helper, isOAS30 as isOAS30Helper } from "../helpers"
-// Helpers
+/**
+ * Helpers
+ */
-// 1/2023: as of now, more accurately, isAnyOAS3
-function onlyOAS3(selector) {
- return () => (system, ...args) => {
- const spec = system.getSystem().specSelectors.specJson()
- if(isOAS3Helper(spec)) {
- return selector(...args)
- } else {
- return null
- }
- }
-}
-
-function isOpenAPI31(selector) {
- return () => (system, ...args) => {
- const spec = system.getSystem().specSelectors.specJson()
- if (isOpenAPI31Helper(spec)) {
- return selector(...args)
- } else {
- return null
- }
- }
-}
-
-const state = state => {
- return state || Map()
-}
-
-const specJson = createSelector(
- state,
- spec => spec.get("json", Map())
-)
-
-const specResolved = createSelector(
- state,
- spec => spec.get("resolved", Map())
-)
-
-const spec = state => {
- let res = specResolved(state)
- if(res.count() < 1)
- res = specJson(state)
- return res
-}
-
-// New selectors
-
-export const servers = onlyOAS3(createSelector(
- spec,
- spec => spec.getIn(["servers"]) || Map()
-))
-
-export const isSwagger2 = (ori, system) => () => {
+export const isSwagger2 = () => (system) => {
const spec = system.getSystem().specSelectors.specJson()
return isSwagger2Helper(spec)
}
-export const selectIsOpenAPI31 = (ori, system) => () => {
+export const isOAS30 = () => (system) => {
const spec = system.getSystem().specSelectors.specJson()
- return isOpenAPI31Helper(spec)
+ return isOAS30Helper(spec)
}
-export const selectWebhooks = isOpenAPI31(createSelector(
- spec,
- spec => spec.getIn(["webhooks"]) || Map()
-))
+export const isOAS3 = () => (system) => {
+ return system.getSystem().specSelectors.isOAS30()
+}
+
+function onlyOAS3(selector) {
+ return () => (system, ...args) => {
+ const spec = system.getSystem().specSelectors.specJson()
+ if(system.specSelectors.isOAS3(spec)) {
+ const result = selector(...args)
+ return typeof result === "function" ? result(system, ...args) : result
+ } else {
+ return null
+ }
+ }
+}
+
+export const servers = onlyOAS3(() => (system) => {
+ const spec = system.specSelectors.specJson()
+ return spec.get("servers", servers.mapConst)
+})
+servers.mapConst = Map()
diff --git a/src/core/plugins/oas3/spec-extensions/wrap-selectors.js b/src/core/plugins/oas3/spec-extensions/wrap-selectors.js
index 8e82572d..8572fc1e 100644
--- a/src/core/plugins/oas3/spec-extensions/wrap-selectors.js
+++ b/src/core/plugins/oas3/spec-extensions/wrap-selectors.js
@@ -1,107 +1,54 @@
+/**
+ * @prettier
+ */
import { createSelector } from "reselect"
import { specJsonWithResolvedSubtrees } from "../../spec/selectors"
import { Map } from "immutable"
-import { isOAS3 as isOAS3Helper, isOpenAPI31 as isOpenAPI31Helper, isSwagger2 as isSwagger2Helper } from "../helpers"
-
-// Helpers
-// 1/2023: as of now, more accurately, isAnyOAS3
+/**
+ * Helpers
+ */
function onlyOAS3(selector) {
- return (ori, system) => (...args) => {
- const spec = system.getSystem().specSelectors.specJson()
- if(isOAS3Helper(spec)) {
- return selector(...args)
- } else {
- return ori(...args)
+ return (ori, system) =>
+ (...args) => {
+ if (system.getSystem().specSelectors.isOAS3()) {
+ const result = selector(...args)
+ return typeof result === "function" ? result(system, ...args) : result
+ } else {
+ return ori(...args)
+ }
}
- }
-}
-
-function isOpenAPI31(selector) {
- return (ori, system) => (...args) => {
- const spec = system.getSystem().specSelectors.specJson()
- if (isOpenAPI31Helper(spec)) {
- return selector(...args)
- } else {
- return null
- }
- }
-}
-
-const state = state => {
- return state || Map()
}
const nullSelector = createSelector(() => null)
const OAS3NullSelector = onlyOAS3(nullSelector)
-const specJson = createSelector(
- state,
- spec => spec.get("json", Map())
-)
+/**
+ * Wrappers
+ */
-const specResolved = createSelector(
- state,
- spec => spec.get("resolved", Map())
-)
+export const definitions = onlyOAS3(() => (system) => {
+ const spec = system.getSystem().specSelectors.specJson()
+ const schemas = spec.getIn(["components", "schemas"])
+ return Map.isMap(schemas) ? schemas : definitions.mapConst
+})
+definitions.mapConst = Map()
-const spec = state => {
- let res = specResolved(state)
- if(res.count() < 1)
- res = specJson(state)
- return res
-}
-
-// Wrappers
-
-export const definitions = onlyOAS3(createSelector(
- spec,
- spec => {
- const res = spec.getIn(["components", "schemas"])
- return Map.isMap(res) ? res : Map()
- }
-))
-
-export const hasHost = onlyOAS3((state) => {
- return spec(state).hasIn(["servers", 0])
+export const hasHost = onlyOAS3(() => (system) => {
+ const spec = system.getSystem().specSelectors.specJson()
+ return spec.hasIn(["servers", 0])
})
-export const securityDefinitions = onlyOAS3(createSelector(
- specJsonWithResolvedSubtrees,
- spec => spec.getIn(["components", "securitySchemes"]) || null
-))
+export const securityDefinitions = onlyOAS3(
+ createSelector(
+ specJsonWithResolvedSubtrees,
+ (spec) => spec.getIn(["components", "securitySchemes"]) || null
+ )
+)
export const host = OAS3NullSelector
export const basePath = OAS3NullSelector
export const consumes = OAS3NullSelector
export const produces = OAS3NullSelector
export const schemes = OAS3NullSelector
-
-// New selectors
-
-export const servers = onlyOAS3(createSelector(
- spec,
- spec => spec.getIn(["servers"]) || Map()
-))
-
-export const isOAS3 = (ori, system) => () => {
- const spec = system.getSystem().specSelectors.specJson()
- return isOAS3Helper(Map.isMap(spec) ? spec : Map())
-}
-
-export const isSwagger2 = (ori, system) => () => {
- const spec = system.getSystem().specSelectors.specJson()
- return isSwagger2Helper(Map.isMap(spec) ? spec : Map())
-}
-
-export const selectIsOpenAPI31 = (ori, system) => () => {
- const spec = system.getSystem().specSelectors.specJson()
- return isOpenAPI31Helper(Map.isMap(spec) ? spec : Map())
-}
-
-export const selectWebhooks = isOpenAPI31(createSelector(
- spec,
- spec => spec.getIn(["webhooks"]) || Map()
-))
-
diff --git a/src/core/plugins/oas3/wrap-components/index.js b/src/core/plugins/oas3/wrap-components/index.js
index cd0c627a..2c421add 100644
--- a/src/core/plugins/oas3/wrap-components/index.js
+++ b/src/core/plugins/oas3/wrap-components/index.js
@@ -4,8 +4,6 @@ import VersionStamp from "./version-stamp"
import OnlineValidatorBadge from "./online-validator-badge"
import Model from "./model"
import JsonSchema_string from "./json-schema-string"
-import License from "./license"
-import info from "./info"
export default {
Markdown,
@@ -14,6 +12,4 @@ export default {
VersionStamp,
model: Model,
onlineValidatorBadge: OnlineValidatorBadge,
- License,
- info,
}
diff --git a/src/core/plugins/oas3/wrap-components/info.jsx b/src/core/plugins/oas3/wrap-components/info.jsx
deleted file mode 100644
index 42112b97..00000000
--- a/src/core/plugins/oas3/wrap-components/info.jsx
+++ /dev/null
@@ -1,78 +0,0 @@
-import React from "react"
-import PropTypes from "prop-types"
-import ImPropTypes from "react-immutable-proptypes"
-import { sanitizeUrl } from "core/utils"
-import { safeBuildUrl } from "core/utils/url"
-import { OAS3ComponentWrapFactory } from "../helpers"
-
-const Info = (props) => {
- const { info, url, host, basePath, getComponent, specSelectors, externalDocs, selectedServer, url: specUrl } = props
- const isOpenAPI31 = specSelectors.selectIsOpenAPI31()
- const version = info.get("version")
- const description = info.get("description")
- const title = info.get("title")
- const termsOfServiceUrl = safeBuildUrl(info.get("termsOfService"), specUrl, { selectedServer })
- const contact = info.get("contact")
- const license = info.get("license")
- // note that ux may want to move summary to a sub-heading, as summary is a string that does not need to be Markdown
- const summary = info.get("summary") // OAS3.1 field
- const rawExternalDocsUrl = externalDocs && externalDocs.get("url")
- const externalDocsUrl = safeBuildUrl(rawExternalDocsUrl, specUrl, { selectedServer })
- const externalDocsDescription = externalDocs && externalDocs.get("description")
-
- const Markdown = getComponent("Markdown", true)
- const Link = getComponent("Link")
- const VersionStamp = getComponent("VersionStamp")
- const InfoUrl = getComponent("InfoUrl")
- const InfoBasePath = getComponent("InfoBasePath")
- const License = getComponent("License")
- const Contact = getComponent("Contact")
-
- return (
-
-
- {title}
- {version && }
-
- {host || basePath ? : null}
- {url && }
-
-
- {
- isOpenAPI31 && summary &&
-
-
- }
-
-
-
-
- {
- termsOfServiceUrl &&
- Terms of service
-
- }
-
- {contact && contact.size ?
: null}
- {license && license.size ?
: null}
- {externalDocsUrl ?
-
{externalDocsDescription || externalDocsUrl}
- : null}
-
-
- )
-}
-
-Info.propTypes = {
- info: PropTypes.object,
- url: PropTypes.string,
- host: PropTypes.string,
- basePath: PropTypes.string,
- externalDocs: ImPropTypes.map,
- getComponent: PropTypes.func.isRequired,
- specSelectors: PropTypes.object.isRequired,
- oas3selectors: PropTypes.func,
- selectedServer: PropTypes.string,
-}
-
-export default OAS3ComponentWrapFactory(Info)
\ No newline at end of file
diff --git a/src/core/plugins/oas3/wrap-components/license.jsx b/src/core/plugins/oas3/wrap-components/license.jsx
deleted file mode 100644
index 7560a6b8..00000000
--- a/src/core/plugins/oas3/wrap-components/license.jsx
+++ /dev/null
@@ -1,49 +0,0 @@
-import React from "react"
-import PropTypes from "prop-types"
-import { sanitizeUrl } from "core/utils"
-import { safeBuildUrl } from "core/utils/url"
-import { OAS3ComponentWrapFactory } from "../helpers"
-
-const baseSPDXurl = "https://spdx.org/licenses"
-const createSPDXurl = (identifier) => {
- return `${baseSPDXurl}/${identifier}.html`
-}
-
-const License = (props) => {
- const { license, getComponent, selectedServer, url: specUrl, specSelectors } = props
- const Link = getComponent("Link")
- const name = license.get("name") || "License"
- const url = safeBuildUrl(license.get("url"), specUrl, { selectedServer })
- const identifier = license.get("identifier") || "" // OAS3.1 field
- const identifierUrl = createSPDXurl(identifier)
- const isOpenAPI31 = specSelectors.selectIsOpenAPI31()
-
- return (
-
- {
- !isOpenAPI31 && url &&
{name}
- }
- {
- isOpenAPI31 && url && !identifier &&
{name}
- }
- {
- isOpenAPI31 && identifier && !url &&
SPDX License: {identifier}
- }
- {/* {
- isOpenAPI31 && identifier && url &&
Render Error: License.url and License.identifier are mutually exclusive fields
- } */}
-
- )
-}
-
-License.propTypes = {
- license: PropTypes.shape({
- get: PropTypes.func,
- }),
- getComponent: PropTypes.func.isRequired,
- specSelectors: PropTypes.object.isRequired,
- selectedServer: PropTypes.string,
- url: PropTypes.string.isRequired,
-}
-
-export default OAS3ComponentWrapFactory(License)
\ No newline at end of file
diff --git a/src/core/plugins/oas31/components/info.jsx b/src/core/plugins/oas31/components/info.jsx
new file mode 100644
index 00000000..048be5dd
--- /dev/null
+++ b/src/core/plugins/oas31/components/info.jsx
@@ -0,0 +1,155 @@
+/**
+ * @prettier
+ */
+import React from "react"
+import PropTypes from "prop-types"
+import ImPropTypes from "react-immutable-proptypes"
+import { sanitizeUrl } from "core/utils"
+import { safeBuildUrl } from "core/utils/url"
+
+export class InfoBasePath extends React.Component {
+ static propTypes = {
+ host: PropTypes.string,
+ basePath: PropTypes.string,
+ }
+
+ render() {
+ const { host, basePath } = this.props
+
+ return (
+
+ [ Base URL: {host}
+ {basePath} ]
+
+ )
+ }
+}
+
+export class InfoUrl extends React.PureComponent {
+ static propTypes = {
+ url: PropTypes.string.isRequired,
+ getComponent: PropTypes.func.isRequired,
+ }
+
+ render() {
+ const { url, getComponent } = this.props
+ const Link = getComponent("Link")
+
+ return (
+
+
{url}
+
+ )
+ }
+}
+
+class Info extends React.Component {
+ static propTypes = {
+ title: PropTypes.any,
+ description: PropTypes.any,
+ version: PropTypes.any,
+ info: PropTypes.object,
+ url: PropTypes.string,
+ host: PropTypes.string,
+ basePath: PropTypes.string,
+ externalDocs: ImPropTypes.map,
+ getComponent: PropTypes.func.isRequired,
+ oas3selectors: PropTypes.func,
+ selectedServer: PropTypes.string,
+ }
+
+ render() {
+ const {
+ info,
+ url,
+ host,
+ basePath,
+ getComponent,
+ externalDocs,
+ selectedServer,
+ url: specUrl,
+ } = this.props
+ const version = info.get("version")
+ const summary = info.get("summary")
+ const description = info.get("description")
+ const title = info.get("title")
+ const termsOfServiceUrl = safeBuildUrl(
+ info.get("termsOfService"),
+ specUrl,
+ { selectedServer }
+ )
+ const contactData = info.get("contact")
+ const licenseData = info.get("license")
+ const rawExternalDocsUrl = externalDocs && externalDocs.get("url")
+ const externalDocsUrl = safeBuildUrl(rawExternalDocsUrl, specUrl, {
+ selectedServer,
+ })
+ const externalDocsDescription =
+ externalDocs && externalDocs.get("description")
+
+ const Markdown = getComponent("Markdown", true)
+ const Link = getComponent("Link")
+ const VersionStamp = getComponent("VersionStamp")
+ const InfoUrl = getComponent("InfoUrl")
+ const InfoBasePath = getComponent("InfoBasePath")
+ const License = getComponent("License")
+ const Contact = getComponent("Contact")
+
+ return (
+
+
+
+ {title}
+ {version && }
+
+ {host || basePath ? (
+
+ ) : null}
+ {url && }
+
+ {summary && (
+
+
+
+ )}
+
+
+
+ {termsOfServiceUrl && (
+
+
+ Terms of service
+
+
+ )}
+ {contactData?.size > 0 && (
+
+ )}
+ {licenseData?.size > 0 && (
+
+ )}
+ {externalDocsUrl ? (
+
+ {externalDocsDescription || externalDocsUrl}
+
+ ) : null}
+
+ )
+ }
+}
+
+export default Info
diff --git a/src/core/plugins/oas31/components/license.jsx b/src/core/plugins/oas31/components/license.jsx
new file mode 100644
index 00000000..ae620e79
--- /dev/null
+++ b/src/core/plugins/oas31/components/license.jsx
@@ -0,0 +1,52 @@
+/**
+ * @prettier
+ */
+import React from "react"
+import PropTypes from "prop-types"
+import { safeBuildUrl } from "core/utils/url"
+import { sanitizeUrl } from "core/utils"
+
+class License extends React.Component {
+ static propTypes = {
+ license: PropTypes.object,
+ getComponent: PropTypes.func.isRequired,
+ selectedServer: PropTypes.string,
+ url: PropTypes.string.isRequired,
+ }
+
+ render() {
+ const { license, getComponent, selectedServer, url: specUrl } = this.props
+ const name = license.get("name", "License")
+ const url = sanitizeUrl(
+ safeBuildUrl(license.get("url"), specUrl, { selectedServer })
+ )
+ const identifier = license.get("identifier", "")
+ const spdxURL = sanitizeUrl(`https://spdx.org/licenses/${identifier}.html`)
+
+ const Link = getComponent("Link")
+
+ return (
+
+ {identifier && (
+
+
+ {name}
+
+
+ )}
+
+ {url && !identifier && (
+
+
+ {name}
+
+
+ )}
+
+ {!url && !identifier &&
{name}}
+
+ )
+ }
+}
+
+export default License
diff --git a/src/core/plugins/oas3/components/webhooks.jsx b/src/core/plugins/oas31/components/webhooks.jsx
similarity index 94%
rename from src/core/plugins/oas3/components/webhooks.jsx
rename to src/core/plugins/oas31/components/webhooks.jsx
index 9bd3e8e6..b4e7f7cc 100644
--- a/src/core/plugins/oas3/components/webhooks.jsx
+++ b/src/core/plugins/oas31/components/webhooks.jsx
@@ -1,4 +1,3 @@
-// OpenAPI 3.1 feature
import React from "react"
import PropTypes from "prop-types"
import { fromJS } from "immutable"
@@ -8,8 +7,8 @@ import ImPropTypes from "react-immutable-proptypes"
// to show/hide all webhook items
const Webhooks = (props) => {
const { specSelectors, getComponent, specPath } = props
-
- const webhooksPathItems = specSelectors.selectWebhooks() // OrderedMap
+
+ const webhooksPathItems = specSelectors.webhooks()
if (!webhooksPathItems || webhooksPathItems?.size < 1) {
return null
}
@@ -21,7 +20,7 @@ const Webhooks = (props) => {
operation
})
// using defaultProps for `specPath`; may want to remove from props
- // and/or if extract to separate PathItem component, allow for use
+ // and/or if extract to separate PathItem component, allow for use
// with both OAS3.1 "webhooks" and "components.pathItems" features
return
{
+ const oasVersion = jsSpec.get("openapi")
+
+ return (
+ typeof oasVersion === "string" && /^3\.1\.(?:[1-9]\d*|0)$/.test(oasVersion)
+ )
+}
diff --git a/src/core/plugins/oas31/index.js b/src/core/plugins/oas31/index.js
new file mode 100644
index 00000000..11cc4d1b
--- /dev/null
+++ b/src/core/plugins/oas31/index.js
@@ -0,0 +1,37 @@
+/**
+ * @prettier
+ */
+import Webhooks from "./components/webhooks"
+import License from "./components/license"
+import Info from "./components/info"
+import LicenseWrapper from "./wrap-components/license"
+import InfoWrapper from "./wrap-components/info"
+import { isOAS31, webhooks } from "./spec-extensions/selectors"
+import { isOAS3 } from "./spec-extensions/wrap-selectors"
+
+const OAS31Plugin = () => {
+ return {
+ components: {
+ Webhooks,
+ OAS31Info: Info,
+ OAS31License: License,
+ },
+ wrapComponents: {
+ License: LicenseWrapper,
+ info: InfoWrapper,
+ },
+ statePlugins: {
+ spec: {
+ selectors: {
+ isOAS31,
+ webhooks,
+ },
+ wrapSelectors: {
+ isOAS3,
+ },
+ },
+ },
+ }
+}
+
+export default OAS31Plugin
diff --git a/src/core/plugins/oas31/spec-extensions/selectors.js b/src/core/plugins/oas31/spec-extensions/selectors.js
new file mode 100644
index 00000000..dadd946f
--- /dev/null
+++ b/src/core/plugins/oas31/spec-extensions/selectors.js
@@ -0,0 +1,29 @@
+/**
+ * @prettier
+ */
+import { Map } from "immutable"
+
+import { isOAS31 as isOAS31Helper } from "../helpers"
+
+export const isOAS31 = () => (system) => {
+ const spec = system.specSelectors.specJson()
+ return isOAS31Helper(spec)
+}
+
+const onlyOAS31 =
+ (selector) =>
+ () =>
+ (system, ...args) => {
+ if (system.getSystem().specSelectors.isOAS31()) {
+ const result = selector(...args)
+ return typeof result === "function" ? result(system, ...args) : result
+ } else {
+ return null
+ }
+ }
+
+export const webhooks = onlyOAS31(() => (system) => {
+ const spec = system.specSelectors.specJson()
+ return spec.get("webhooks", webhooks.mapConst)
+})
+webhooks.mapConst = Map()
diff --git a/src/core/plugins/oas31/spec-extensions/wrap-selectors.js b/src/core/plugins/oas31/spec-extensions/wrap-selectors.js
new file mode 100644
index 00000000..482bdcb0
--- /dev/null
+++ b/src/core/plugins/oas31/spec-extensions/wrap-selectors.js
@@ -0,0 +1,4 @@
+export const isOAS3 = (oriSelector, system) => (state, ...args) => {
+ const isOAS31 = system.specSelectors.isOAS31()
+ return isOAS31 || oriSelector(...args)
+}
diff --git a/src/core/plugins/oas31/wrap-components/info.jsx b/src/core/plugins/oas31/wrap-components/info.jsx
new file mode 100644
index 00000000..3530044c
--- /dev/null
+++ b/src/core/plugins/oas31/wrap-components/info.jsx
@@ -0,0 +1,16 @@
+/**
+ * @prettier
+ */
+import React from "react"
+
+const InfoWrapper = (Original, system) => (props) => {
+ if (system.specSelectors.isOAS31()) {
+ const OAS31Info = system.getComponent("OAS31Info")
+
+ return
+ }
+
+ return
+}
+
+export default InfoWrapper
diff --git a/src/core/plugins/oas31/wrap-components/license.jsx b/src/core/plugins/oas31/wrap-components/license.jsx
new file mode 100644
index 00000000..200da560
--- /dev/null
+++ b/src/core/plugins/oas31/wrap-components/license.jsx
@@ -0,0 +1,16 @@
+/**
+ * @prettier
+ */
+import React from "react"
+
+const LicenseWrapper = (Original, system) => (props) => {
+ if (system.specSelectors.isOAS31()) {
+ const OAS31License = system.getComponent("OAS31License")
+
+ return
+ }
+
+ return
+}
+
+export default LicenseWrapper
diff --git a/src/core/presets/apis.js b/src/core/presets/apis.js
index 14afc627..bc2bdf44 100644
--- a/src/core/presets/apis.js
+++ b/src/core/presets/apis.js
@@ -1,12 +1,10 @@
+/**
+ * @prettier
+ */
import BasePreset from "./base"
import OAS3Plugin from "../plugins/oas3"
-
-// Just the base, for now.
+import OAS31Plugin from "../plugins/oas31"
export default function PresetApis() {
-
- return [
- BasePreset,
- OAS3Plugin
- ]
+ return [BasePreset, OAS3Plugin, OAS31Plugin]
}
diff --git a/src/core/presets/base.js b/src/core/presets/base.js
index 43662c49..ca33bb51 100644
--- a/src/core/presets/base.js
+++ b/src/core/presets/base.js
@@ -1,3 +1,6 @@
+/**
+ * @prettier
+ */
import err from "core/plugins/err"
import layout from "core/plugins/layout"
import spec from "core/plugins/spec"
@@ -57,13 +60,10 @@ import Errors from "core/components/errors"
import ContentType from "core/components/content-type"
import Overview from "core/components/overview"
import InitializedInput from "core/components/initialized-input"
-import Info, {
- InfoUrl,
- InfoBasePath,
- License,
- Contact,
-} from "core/components/info"
+import Info, { InfoUrl, InfoBasePath } from "core/components/info"
import InfoContainer from "core/containers/info"
+import Contact from "core/components/contact"
+import License from "core/components/license"
import JumpToPath from "core/components/jump-to-path"
import CopyToClipboardBtn from "core/components/copy-to-clipboard-btn"
import Footer from "core/components/footer"
@@ -87,16 +87,12 @@ import VersionPragmaFilter from "core/components/version-pragma-filter"
import VersionStamp from "core/components/version-stamp"
import DeepLink from "core/components/deep-link"
import SvgAssets from "core/components/svg-assets"
-
import Markdown from "core/components/providers/markdown"
-
import BaseLayout from "core/components/layouts/base"
-
import * as LayoutUtils from "core/components/layout-utils"
import * as JsonSchemaComponents from "core/json-schema-components"
-export default function() {
-
+export default function () {
let coreComponents = {
components: {
App,
@@ -115,6 +111,10 @@ export default function() {
InitializedInput,
info: Info,
InfoContainer,
+ InfoUrl,
+ InfoBasePath,
+ Contact,
+ License,
JumpToPath,
CopyToClipboardBtn,
onlineValidatorBadge: OnlineValidatorBadge,
@@ -163,23 +163,19 @@ export default function() {
OperationTag,
OperationContainer,
DeepLink,
- InfoUrl,
- InfoBasePath,
- License,
- Contact,
SvgAssets,
Example,
ExamplesSelect,
ExamplesSelectValueRetainer,
- }
+ },
}
let formComponents = {
- components: LayoutUtils
+ components: LayoutUtils,
}
let jsonSchemaComponents = {
- components: JsonSchemaComponents
+ components: JsonSchemaComponents,
}
return [
diff --git a/test/e2e-cypress/static/documents/features/info-openAPI2.yaml b/test/e2e-cypress/static/documents/features/info-openAPI2.yaml
index 05d62de0..6363c983 100644
--- a/test/e2e-cypress/static/documents/features/info-openAPI2.yaml
+++ b/test/e2e-cypress/static/documents/features/info-openAPI2.yaml
@@ -1,4 +1,5 @@
-swagger: 2.0.0
+swagger: "2.0"
+
info:
title: OpenAPI 2.0 Info Object
version: 1.0.0
diff --git a/test/e2e-cypress/static/documents/features/license-openAPI2.yaml b/test/e2e-cypress/static/documents/features/license-openAPI2.yaml
index 4ef77050..be0f7b0c 100644
--- a/test/e2e-cypress/static/documents/features/license-openAPI2.yaml
+++ b/test/e2e-cypress/static/documents/features/license-openAPI2.yaml
@@ -1,4 +1,4 @@
-swagger: 2.0.0
+swagger: "2.0"
info:
title: OpenAPI 2.0 License with only url present
version: 1.0.0
diff --git a/test/e2e-cypress/static/documents/features/license-openAPI31-identifier.yaml b/test/e2e-cypress/static/documents/features/license-openAPI31-identifier.yaml
index 9a777a5a..b88bc161 100644
--- a/test/e2e-cypress/static/documents/features/license-openAPI31-identifier.yaml
+++ b/test/e2e-cypress/static/documents/features/license-openAPI31-identifier.yaml
@@ -5,5 +5,4 @@ info:
description: This is a sample server for a pet store.
license:
name: Apache 2.0
- # url: https://www.apache.org/licenses/LICENSE-2.0.html
- identifier: Apache-2.0 # mutually exclusive of url; separately, for json_schema, consider const, prefix, array items can be of a different type (current assumption is all array items are the same)
+ identifier: Apache-2.0
diff --git a/test/e2e-cypress/tests/features/info.js b/test/e2e-cypress/tests/features/info.js
index 499d4c28..9884f197 100644
--- a/test/e2e-cypress/tests/features/info.js
+++ b/test/e2e-cypress/tests/features/info.js
@@ -1,11 +1,13 @@
describe("Render Info Component", () => {
- describe("OpenAPI 2.x", () => {
+ describe("OpenAPI 2.0", () => {
const baseUrl = "/?url=/documents/features/info-openAPI2.yaml"
+
it("should render Info Description", () => {
cy.visit(baseUrl)
.get(".info .description")
.should("contains.text", "This is a sample")
})
+
it("should render Info Main anchor target xss link with safe `rel` attributes", () => {
cy.visit(baseUrl)
.get(".info .main > a")
@@ -16,19 +18,23 @@ describe("Render Info Component", () => {
.should("have.attr", "target")
.and("equal", "_blank")
})
+
it("should not render Info Summary (an OpenAPI 3.1 field)", () => {
cy.visit(baseUrl)
.get(".info__summary")
.should("not.exist")
})
})
+
describe("OpenAPI 3.0.x", () => {
const baseUrl = "/?url=/documents/features/info-openAPI30.yaml"
+
it("should render Info Description", () => {
cy.visit(baseUrl)
.get(".info .description")
.should("contains.text", "This is a sample")
})
+
it("should render Info Main anchor target xss link with safe `rel` attributes", () => {
cy.visit(baseUrl)
.get(".info .main > a")
@@ -39,19 +45,23 @@ describe("Render Info Component", () => {
.should("have.attr", "target")
.and("equal", "_blank")
})
+
it("should not render Info Summary (an OpenAPI 3.1 field)", () => {
cy.visit(baseUrl)
.get(".info__summary")
.should("not.exist")
})
})
+
describe("OpenAPI 3.1.x", () => {
const baseUrl = "/?url=/documents/features/info-openAPI31.yaml"
+
it("should render Info Description", () => {
cy.visit(baseUrl)
.get(".info .description")
.should("contains.text", "This is a sample")
})
+
it("should render Info Main anchor target xss link with safe `rel` attributes", () => {
cy.visit(baseUrl)
.get(".info .main > a")
diff --git a/test/e2e-cypress/tests/features/license.js b/test/e2e-cypress/tests/features/license.js
index 009cb101..8d48f95f 100644
--- a/test/e2e-cypress/tests/features/license.js
+++ b/test/e2e-cypress/tests/features/license.js
@@ -1,18 +1,20 @@
+/**
+ * @prettier
+ */
describe("Render License Component", () => {
- describe("OpenAPI 2", () =>{
+ describe("OpenAPI 2.0", () => {
const baseUrl = "/?url=/documents/features/license-openAPI2.yaml"
+
it("should render License URL", () => {
cy.visit(baseUrl)
.get(".info__license")
.should("exist")
.should("contains.text", "Apache 2.0")
- .should("not.contains.text", "SPDX License")
- .get(".info__license__identifier")
- .should("not.exist")
})
- it("should render License URL anchor target xss link with safe `rel` attributes ", () => {
+
+ it("should render License URL anchor target xss link with safe `rel` attributes", () => {
cy.visit(baseUrl)
- .get(".info__license > .link")
+ .get(".info__license__url > .link")
.should("have.attr", "rel")
.and("include", "noopener")
.and("include", "noreferrer")
@@ -21,18 +23,18 @@ describe("Render License Component", () => {
.and("equal", "_blank")
})
})
+
describe("OpenAPI 3.0.x", () => {
const baseUrl = "/?url=/documents/features/license-openAPI30.yaml"
+
it("should render License URL", () => {
cy.visit(baseUrl)
.get(".info__license__url")
.should("exist")
.should("contains.text", "Apache 2.0")
- .should("not.contains.text", "SPDX License")
- .get(".info__license__identifier")
- .should("not.exist")
- })
- it("should render URL anchor target xss link with safe `rel` attributes ", () => {
+ })
+
+ it("should render URL anchor target xss link with safe `rel` attributes", () => {
cy.visit(baseUrl)
.get(".info__license__url > a")
.should("have.attr", "rel")
@@ -43,19 +45,22 @@ describe("Render License Component", () => {
.and("equal", "_blank")
})
})
- describe("OpenAPI 3.1.x", () => {
- describe("only URL", () => {
+
+ describe("OpenAPI 3.1.x", () => {
+ describe("given URL field", () => {
const baseUrl = "/?url=/documents/features/license-openAPI31-url.yaml"
+
it("should render URL", () => {
cy.visit(baseUrl)
.get(".info__license__url")
.should("exist")
.should("contains.text", "Apache 2.0")
- .should("not.contains.text", "SPDX License")
- .get(".info__license__identifier")
- .should("not.exist")
- })
- it("should render URL anchor target xss link with safe `rel` attributes ", () => {
+ .get(".info__license__url > a")
+ .should("have.attr", "href")
+ .and("equal", "https://www.apache.org/licenses/LICENSE-2.0.html")
+ })
+
+ it("should render URL anchor target xss link with safe `rel` attributes", () => {
cy.visit(baseUrl)
.get(".info__license__url > a")
.should("have.attr", "rel")
@@ -66,40 +71,43 @@ describe("Render License Component", () => {
.and("equal", "_blank")
})
})
- describe("only SPDX Identifier", () => {
- const baseUrl = "/?url=/documents/features/license-openAPI31-identifier.yaml"
- it("should render SPDX Identifier", () => {
+
+ describe("given identifier field", () => {
+ const baseUrl =
+ "/?url=/documents/features/license-openAPI31-identifier.yaml"
+
+ it("should render URL using identifier", () => {
cy.visit(baseUrl)
- .get(".info__license__identifier")
- .should("exist")
- .should("contains.text", "Apache-2.0")
- .should("contains.text", "SPDX License")
.get(".info__license__url")
- .should("not.exist")
- })
- it("should render SPDX and Identifier anchor target xss links with safe `rel` attributes ", () => {
+ .should("exist")
+ .should("contains.text", "Apache 2.0")
+ .get(".info__license__url > a")
+ .should("have.attr", "href")
+ .and("equal", "https://spdx.org/licenses/Apache-2.0.html")
+ })
+
+ it("should render URL anchor target xss links with safe `rel` attributes", () => {
cy.visit(baseUrl)
- .get(".info__license__identifier > a")
- .each(($el) => {
- cy.get($el)
- .should("have.attr", "rel")
- .and("include", "noopener")
- .and("include", "noreferrer")
- cy.get($el)
- .should("have.attr", "target")
- .and("equal", "_blank")
- })
+ .get(".info__license__url > a")
+ .should("have.attr", "rel")
+ .and("include", "noopener")
+ .and("include", "noreferrer")
+ .get(".info .main > a")
+ .should("have.attr", "target")
+ .and("equal", "_blank")
})
})
+
describe("URL and SPX are mutually exclusive", () => {
it("should render nothing if both URL & SPDX exists", () => {
- const baseUrl = "/?url=/documents/features/license-openAPI31-error-both-identifier-and-url.yaml"
+ const baseUrl =
+ "/?url=/documents/features/license-openAPI31-error-both-identifier-and-url.yaml"
cy.visit(baseUrl)
.get(".info__license__identifier")
.should("not.exist")
.get(".info__license__url")
.should("not.exist")
- })
+ })
})
})
})
diff --git a/test/unit/core/plugins/oas3/helpers.js b/test/unit/core/plugins/oas3/helpers.js
index 14e31c97..7eef6d4f 100644
--- a/test/unit/core/plugins/oas3/helpers.js
+++ b/test/unit/core/plugins/oas3/helpers.js
@@ -1,7 +1,7 @@
import { fromJS } from "immutable"
-import { isOAS3, isSwagger2 } from "corePlugins/oas3/helpers"
+import { isOAS30, isSwagger2 } from "corePlugins/oas3/helpers"
-const isOAS3Shorthand = (version) => isOAS3(fromJS({
+const isOAS3Shorthand = (version) => isOAS30(fromJS({
openapi: version
}))
@@ -13,7 +13,7 @@ describe("isOAS3", function () {
it("should recognize valid OAS3 version values", function () {
expect(isOAS3Shorthand("3.0.0")).toEqual(true)
expect(isOAS3Shorthand("3.0.1")).toEqual(true)
- expect(isOAS3Shorthand("3.0.11111")).toEqual(true)
+ expect(isOAS3Shorthand("3.0.11111")).toEqual(false)
expect(isOAS3Shorthand("3.0.0-rc0")).toEqual(true)
})
@@ -31,7 +31,7 @@ describe("isOAS3", function () {
})
it("should gracefully fail when `openapi` field is missing", function () {
- expect(isOAS3(fromJS({
+ expect(isOAS30(fromJS({
openApi: "3.0.0"
}))).toEqual(false)
expect(isOAS3Shorthand(null)).toEqual(false)
@@ -41,7 +41,7 @@ describe("isOAS3", function () {
describe("isSwagger2", function () {
it("should recognize valid Swagger 2.0 version values", function () {
expect(isSwagger2Shorthand("2.0")).toEqual(true)
- expect(isSwagger2Shorthand("2.0-rc0")).toEqual(true)
+ expect(isSwagger2Shorthand("2.0-rc0")).toEqual(false)
})
it("should fail for invalid Swagger 2.0 version values", function () {
diff --git a/test/unit/core/plugins/oas3/state-integration.js b/test/unit/core/plugins/oas3/state-integration.js
index e80918d9..62b1f620 100644
--- a/test/unit/core/plugins/oas3/state-integration.js
+++ b/test/unit/core/plugins/oas3/state-integration.js
@@ -26,7 +26,8 @@ describe("OAS3 plugin - state", function() {
specSelectors: {
specJson: () => {
return fromJS({ openapi: "3.0.0" })
- }
+ },
+ isOAS3: () => true,
}
}
}
@@ -55,7 +56,8 @@ describe("OAS3 plugin - state", function() {
specSelectors: {
specJson: () => {
return fromJS({ openapi: "3.0.0" })
- }
+ },
+ isOAS3: () => true,
}
}
}
@@ -88,7 +90,8 @@ describe("OAS3 plugin - state", function() {
specSelectors: {
specJson: () => {
return fromJS({ openapi: "3.0.0" })
- }
+ },
+ isOAS3: () => true,
}
}
}
@@ -124,7 +127,8 @@ describe("OAS3 plugin - state", function() {
specSelectors: {
specJson: () => {
return fromJS({ openapi: "3.0.0" })
- }
+ },
+ isOAS3: () => true,
}
}
}
@@ -167,7 +171,8 @@ describe("OAS3 plugin - state", function() {
specSelectors: {
specJson: () => {
return fromJS({ openapi: "3.0.0" })
- }
+ },
+ isOAS3: () => true,
}
}
}
@@ -207,7 +212,8 @@ describe("OAS3 plugin - state", function() {
specSelectors: {
specJson: () => {
return fromJS({ openapi: "3.0.0" })
- }
+ },
+ isOAS3: () => true,
}
}
}
@@ -261,7 +267,8 @@ describe("OAS3 plugin - state", function() {
specSelectors: {
specJson: () => {
return fromJS({ openapi: "3.0.0" })
- }
+ },
+ isOAS3: () => true,
}
}
}
@@ -314,7 +321,8 @@ describe("OAS3 plugin - state", function() {
specSelectors: {
specJson: () => {
return fromJS({ openapi: "3.0.0" })
- }
+ },
+ isOAS3: () => true,
}
}
}
@@ -342,7 +350,8 @@ describe("OAS3 plugin - state", function() {
specSelectors: {
specJson: () => {
return fromJS({ openapi: "3.0.0" })
- }
+ },
+ isOAS3: () => true,
}
}
}
diff --git a/test/unit/core/plugins/oas3/wrap-auth-selectors.js b/test/unit/core/plugins/oas3/wrap-auth-selectors.js
index 59fd8a90..4d3ef3bf 100644
--- a/test/unit/core/plugins/oas3/wrap-auth-selectors.js
+++ b/test/unit/core/plugins/oas3/wrap-auth-selectors.js
@@ -17,6 +17,7 @@ describe("oas3 plugin - auth extensions - wrapSelectors", function(){
specJson: () => fromJS({
openapi: "3.0.0"
}),
+ isOAS3: () => true,
securityDefinitions: () => {
return fromJS({
"oauth2AuthorizationCode": {
diff --git a/test/unit/core/plugins/oas3/wrap-spec-selectors.js b/test/unit/core/plugins/oas3/wrap-spec-selectors.js
index 55b196e9..35bdcafc 100644
--- a/test/unit/core/plugins/oas3/wrap-spec-selectors.js
+++ b/test/unit/core/plugins/oas3/wrap-spec-selectors.js
@@ -1,8 +1,5 @@
-
import { fromJS } from "immutable"
-import {
- definitions
-} from "corePlugins/oas3/spec-extensions/wrap-selectors"
+import { definitions } from "corePlugins/oas3/spec-extensions/wrap-selectors"
describe("oas3 plugin - spec extensions - wrapSelectors", function(){
@@ -28,6 +25,7 @@ describe("oas3 plugin - spec extensions - wrapSelectors", function(){
getSystem: () => system,
specSelectors: {
specJson: () => spec,
+ isOAS3: () => true,
}
}
@@ -57,6 +55,7 @@ describe("oas3 plugin - spec extensions - wrapSelectors", function(){
getSystem: () => system,
specSelectors: {
specJson: () => spec,
+ isOAS3: () => true,
}
}
@@ -82,7 +81,8 @@ describe("oas3 plugin - spec extensions - wrapSelectors", function(){
getSystem: () => system,
specSelectors: {
specJson: () => spec,
- }
+ isOAS3: () => true,
+ },
}
// When
diff --git a/test/unit/xss/anchor-target-rel/info.jsx b/test/unit/xss/anchor-target-rel/info.jsx
index 75f2f15a..628f22d0 100644
--- a/test/unit/xss/anchor-target-rel/info.jsx
+++ b/test/unit/xss/anchor-target-rel/info.jsx
@@ -1,7 +1,9 @@
import React from "react"
import { render } from "enzyme"
import { fromJS } from "immutable"
-import Info, { InfoUrl, License } from "components/info"
+import Info, { InfoUrl } from "components/info"
+import Contact from "components/contact"
+import License from "components/license"
import { Link } from "components/layout-utils"
import Markdown from "components/providers/markdown"
@@ -11,7 +13,8 @@ describe(" Anchor Target Safety", function(){
Markdown,
InfoUrl,
License,
- Link
+ Contact,
+ Link,
}
const baseProps = {
getComponent: c => components[c] || dummyComponent,