* Added tooling for appending OAS3 relative URLs to selected Server Info * Terms of service URL * Contact URL * License URL * External Docs URL Tag * Tag External Docs URL Operation * Operation External Docs ** Operation Tag Co-authored-by: Tim Lai <timothy.lai@gmail.com>bubble
@@ -1,8 +1,8 @@ | |||||
import React from "react" | import React from "react" | ||||
import PropTypes from "prop-types" | import PropTypes from "prop-types" | ||||
import { fromJS } from "immutable" | |||||
import ImPropTypes from "react-immutable-proptypes" | import ImPropTypes from "react-immutable-proptypes" | ||||
import { sanitizeUrl } from "core/utils" | import { sanitizeUrl } from "core/utils" | ||||
import { buildUrl } from "core/utils/url" | |||||
export class InfoBasePath extends React.Component { | export class InfoBasePath extends React.Component { | ||||
@@ -26,13 +26,16 @@ export class InfoBasePath extends React.Component { | |||||
class Contact extends React.Component { | class Contact extends React.Component { | ||||
static propTypes = { | static propTypes = { | ||||
data: PropTypes.object, | data: PropTypes.object, | ||||
getComponent: PropTypes.func.isRequired | |||||
getComponent: PropTypes.func.isRequired, | |||||
specSelectors: PropTypes.object.isRequired, | |||||
selectedServer: PropTypes.string, | |||||
url: PropTypes.string.isRequired, | |||||
} | } | ||||
render(){ | render(){ | ||||
let { data, getComponent } = this.props | |||||
let { data, getComponent, selectedServer, url: specUrl} = this.props | |||||
let name = data.get("name") || "the developer" | let name = data.get("name") || "the developer" | ||||
let url = data.get("url") | |||||
let url = buildUrl(data.get("url"), specUrl, {selectedServer}) | |||||
let email = data.get("email") | let email = data.get("email") | ||||
const Link = getComponent("Link") | const Link = getComponent("Link") | ||||
@@ -53,17 +56,18 @@ class Contact extends React.Component { | |||||
class License extends React.Component { | class License extends React.Component { | ||||
static propTypes = { | static propTypes = { | ||||
license: PropTypes.object, | license: PropTypes.object, | ||||
getComponent: PropTypes.func.isRequired | |||||
getComponent: PropTypes.func.isRequired, | |||||
specSelectors: PropTypes.object.isRequired, | |||||
selectedServer: PropTypes.string, | |||||
url: PropTypes.string.isRequired, | |||||
} | } | ||||
render(){ | render(){ | ||||
let { license, getComponent } = this.props | |||||
let { license, getComponent, selectedServer, url: specUrl } = this.props | |||||
const Link = getComponent("Link") | const Link = getComponent("Link") | ||||
let name = license.get("name") || "License" | |||||
let url = license.get("url") | |||||
let name = license.get("name") || "License" | |||||
let url = buildUrl(license.get("url"), specUrl, {selectedServer}) | |||||
return ( | return ( | ||||
<div className="info__license"> | <div className="info__license"> | ||||
@@ -88,7 +92,7 @@ export class InfoUrl extends React.PureComponent { | |||||
const Link = getComponent("Link") | const Link = getComponent("Link") | ||||
return <Link target="_blank" href={ sanitizeUrl(url) }><span className="url"> { url } </span></Link> | |||||
return <Link target="_blank" href={ sanitizeUrl(url) }><span className="url"> { url }</span></Link> | |||||
} | } | ||||
} | } | ||||
@@ -100,17 +104,21 @@ export default class Info extends React.Component { | |||||
basePath: PropTypes.string, | basePath: PropTypes.string, | ||||
externalDocs: ImPropTypes.map, | externalDocs: ImPropTypes.map, | ||||
getComponent: PropTypes.func.isRequired, | getComponent: PropTypes.func.isRequired, | ||||
oas3selectors: PropTypes.func, | |||||
selectedServer: PropTypes.string, | |||||
} | } | ||||
render() { | render() { | ||||
let { info, url, host, basePath, getComponent, externalDocs } = this.props | |||||
let { info, url, host, basePath, getComponent, externalDocs, selectedServer, url: specUrl } = this.props | |||||
let version = info.get("version") | let version = info.get("version") | ||||
let description = info.get("description") | let description = info.get("description") | ||||
let title = info.get("title") | let title = info.get("title") | ||||
let termsOfService = info.get("termsOfService") | |||||
let termsOfServiceUrl = buildUrl(info.get("termsOfService"), specUrl, {selectedServer}) | |||||
let contact = info.get("contact") | let contact = info.get("contact") | ||||
let license = info.get("license") | let license = info.get("license") | ||||
const { url:externalDocsUrl, description:externalDocsDescription } = (externalDocs || fromJS({})).toJS() | |||||
let rawExternalDocsUrl = externalDocs && externalDocs.get("url") | |||||
let externalDocsUrl = buildUrl(rawExternalDocsUrl, specUrl, {selectedServer}) | |||||
let externalDocsDescription = externalDocs && externalDocs.get("description") | |||||
const Markdown = getComponent("Markdown", true) | const Markdown = getComponent("Markdown", true) | ||||
const Link = getComponent("Link") | const Link = getComponent("Link") | ||||
@@ -133,14 +141,14 @@ export default class Info extends React.Component { | |||||
</div> | </div> | ||||
{ | { | ||||
termsOfService && <div className="info__tos"> | |||||
<Link target="_blank" href={ sanitizeUrl(termsOfService) }>Terms of service</Link> | |||||
termsOfServiceUrl && <div className="info__tos"> | |||||
<Link target="_blank" href={ sanitizeUrl(termsOfServiceUrl) }>Terms of service</Link> | |||||
</div> | </div> | ||||
} | } | ||||
{contact && contact.size ? <Contact getComponent={getComponent} data={ contact } /> : null } | |||||
{license && license.size ? <License getComponent={getComponent} license={ license } /> : null } | |||||
{ externalDocsUrl ? | |||||
{contact && contact.size ? <Contact getComponent={getComponent} data={ contact } selectedServer={selectedServer} url={url} /> : null } | |||||
{license && license.size ? <License getComponent={getComponent} license={ license } selectedServer={selectedServer} url={url}/> : null } | |||||
{ externalDocs ? | |||||
<Link className="info__extdocs" target="_blank" href={sanitizeUrl(externalDocsUrl)}>{externalDocsDescription || externalDocsUrl}</Link> | <Link className="info__extdocs" target="_blank" href={sanitizeUrl(externalDocsUrl)}>{externalDocsDescription || externalDocsUrl}</Link> | ||||
: null } | : null } | ||||
@@ -3,6 +3,7 @@ import PropTypes from "prop-types" | |||||
import ImPropTypes from "react-immutable-proptypes" | import ImPropTypes from "react-immutable-proptypes" | ||||
import Im from "immutable" | import Im from "immutable" | ||||
import { createDeepLinkPath, escapeDeepLinkPath, sanitizeUrl } from "core/utils" | import { createDeepLinkPath, escapeDeepLinkPath, sanitizeUrl } from "core/utils" | ||||
import { buildUrl } from "core/utils/url" | |||||
export default class OperationTag extends React.Component { | export default class OperationTag extends React.Component { | ||||
@@ -15,12 +16,15 @@ export default class OperationTag extends React.Component { | |||||
tagObj: ImPropTypes.map.isRequired, | tagObj: ImPropTypes.map.isRequired, | ||||
tag: PropTypes.string.isRequired, | tag: PropTypes.string.isRequired, | ||||
oas3Selectors: PropTypes.func.isRequired, | |||||
layoutSelectors: PropTypes.object.isRequired, | layoutSelectors: PropTypes.object.isRequired, | ||||
layoutActions: PropTypes.object.isRequired, | layoutActions: PropTypes.object.isRequired, | ||||
getConfigs: PropTypes.func.isRequired, | getConfigs: PropTypes.func.isRequired, | ||||
getComponent: PropTypes.func.isRequired, | getComponent: PropTypes.func.isRequired, | ||||
specUrl: PropTypes.string.isRequired, | |||||
children: PropTypes.element, | children: PropTypes.element, | ||||
} | } | ||||
@@ -29,11 +33,12 @@ export default class OperationTag extends React.Component { | |||||
tagObj, | tagObj, | ||||
tag, | tag, | ||||
children, | children, | ||||
oas3Selectors, | |||||
layoutSelectors, | layoutSelectors, | ||||
layoutActions, | layoutActions, | ||||
getConfigs, | getConfigs, | ||||
getComponent, | getComponent, | ||||
specUrl, | |||||
} = this.props | } = this.props | ||||
let { | let { | ||||
@@ -50,7 +55,8 @@ export default class OperationTag extends React.Component { | |||||
let tagDescription = tagObj.getIn(["tagDetails", "description"], null) | let tagDescription = tagObj.getIn(["tagDetails", "description"], null) | ||||
let tagExternalDocsDescription = tagObj.getIn(["tagDetails", "externalDocs", "description"]) | let tagExternalDocsDescription = tagObj.getIn(["tagDetails", "externalDocs", "description"]) | ||||
let tagExternalDocsUrl = tagObj.getIn(["tagDetails", "externalDocs", "url"]) | |||||
let rawTagExternalDocsUrl = tagObj.getIn(["tagDetails", "externalDocs", "url"]) | |||||
let tagExternalDocsUrl = buildUrl( rawTagExternalDocsUrl, specUrl, {selectedServer: oas3Selectors.selectedServer()} ) | |||||
let isShownKey = ["operations-tag", tag] | let isShownKey = ["operations-tag", tag] | ||||
let showTag = layoutSelectors.isShown(isShownKey, docExpansion === "full" || docExpansion === "list") | let showTag = layoutSelectors.isShown(isShownKey, docExpansion === "full" || docExpansion === "list") | ||||
@@ -2,6 +2,7 @@ import React, { PureComponent } from "react" | |||||
import PropTypes from "prop-types" | import PropTypes from "prop-types" | ||||
import { getList } from "core/utils" | import { getList } from "core/utils" | ||||
import { getExtensions, sanitizeUrl, escapeDeepLinkPath } from "core/utils" | import { getExtensions, sanitizeUrl, escapeDeepLinkPath } from "core/utils" | ||||
import { buildUrl } from "core/utils/url" | |||||
import { Iterable, List } from "immutable" | import { Iterable, List } from "immutable" | ||||
import ImPropTypes from "react-immutable-proptypes" | import ImPropTypes from "react-immutable-proptypes" | ||||
@@ -81,6 +82,7 @@ export default class Operation extends PureComponent { | |||||
schemes | schemes | ||||
} = op | } = op | ||||
const externalDocsUrl = externalDocs ? buildUrl(externalDocs.url, specSelectors.url(), { selectedServer: oas3Selectors.selectedServer() }) : "" | |||||
let operation = operationProps.getIn(["op"]) | let operation = operationProps.getIn(["op"]) | ||||
let responses = operation.get("responses") | let responses = operation.get("responses") | ||||
let parameters = getList(operation, ["parameters"]) | let parameters = getList(operation, ["parameters"]) | ||||
@@ -127,14 +129,14 @@ export default class Operation extends PureComponent { | |||||
</div> | </div> | ||||
} | } | ||||
{ | { | ||||
externalDocs && externalDocs.url ? | |||||
externalDocsUrl ? | |||||
<div className="opblock-external-docs-wrapper"> | <div className="opblock-external-docs-wrapper"> | ||||
<h4 className="opblock-title_normal">Find more details</h4> | <h4 className="opblock-title_normal">Find more details</h4> | ||||
<div className="opblock-external-docs"> | <div className="opblock-external-docs"> | ||||
<span className="opblock-external-docs__description"> | <span className="opblock-external-docs__description"> | ||||
<Markdown source={ externalDocs.description } /> | <Markdown source={ externalDocs.description } /> | ||||
</span> | </span> | ||||
<Link target="_blank" className="opblock-external-docs__link" href={sanitizeUrl(externalDocs.url)}>{externalDocs.url}</Link> | |||||
<Link target="_blank" className="opblock-external-docs__link" href={sanitizeUrl(externalDocsUrl)}>{externalDocsUrl}</Link> | |||||
</div> | </div> | ||||
</div> : null | </div> : null | ||||
} | } | ||||
@@ -16,6 +16,7 @@ export default class Operations extends React.Component { | |||||
specActions: PropTypes.object.isRequired, | specActions: PropTypes.object.isRequired, | ||||
oas3Actions: PropTypes.object.isRequired, | oas3Actions: PropTypes.object.isRequired, | ||||
getComponent: PropTypes.func.isRequired, | getComponent: PropTypes.func.isRequired, | ||||
oas3Selectors: PropTypes.func.isRequired, | |||||
layoutSelectors: PropTypes.object.isRequired, | layoutSelectors: PropTypes.object.isRequired, | ||||
layoutActions: PropTypes.object.isRequired, | layoutActions: PropTypes.object.isRequired, | ||||
authActions: PropTypes.object.isRequired, | authActions: PropTypes.object.isRequired, | ||||
@@ -28,6 +29,7 @@ export default class Operations extends React.Component { | |||||
let { | let { | ||||
specSelectors, | specSelectors, | ||||
getComponent, | getComponent, | ||||
oas3Selectors, | |||||
layoutSelectors, | layoutSelectors, | ||||
layoutActions, | layoutActions, | ||||
getConfigs, | getConfigs, | ||||
@@ -65,10 +67,12 @@ export default class Operations extends React.Component { | |||||
key={"operation-" + tag} | key={"operation-" + tag} | ||||
tagObj={tagObj} | tagObj={tagObj} | ||||
tag={tag} | tag={tag} | ||||
oas3Selectors={oas3Selectors} | |||||
layoutSelectors={layoutSelectors} | layoutSelectors={layoutSelectors} | ||||
layoutActions={layoutActions} | layoutActions={layoutActions} | ||||
getConfigs={getConfigs} | getConfigs={getConfigs} | ||||
getComponent={getComponent}> | |||||
getComponent={getComponent} | |||||
specUrl={specSelectors.url()}> | |||||
{ | { | ||||
operations.map( op => { | operations.map( op => { | ||||
const path = op.get("path") | const path = op.get("path") | ||||
@@ -7,16 +7,18 @@ export default class InfoContainer extends React.Component { | |||||
specActions: PropTypes.object.isRequired, | specActions: PropTypes.object.isRequired, | ||||
specSelectors: PropTypes.object.isRequired, | specSelectors: PropTypes.object.isRequired, | ||||
getComponent: PropTypes.func.isRequired, | getComponent: PropTypes.func.isRequired, | ||||
oas3Selectors: PropTypes.func.isRequired, | |||||
} | } | ||||
render () { | render () { | ||||
const {specSelectors, getComponent} = this.props | |||||
const {specSelectors, getComponent, oas3Selectors} = this.props | |||||
const info = specSelectors.info() | const info = specSelectors.info() | ||||
const url = specSelectors.url() | const url = specSelectors.url() | ||||
const basePath = specSelectors.basePath() | const basePath = specSelectors.basePath() | ||||
const host = specSelectors.host() | const host = specSelectors.host() | ||||
const externalDocs = specSelectors.externalDocs() | const externalDocs = specSelectors.externalDocs() | ||||
const selectedServer = oas3Selectors.selectedServer() | |||||
const Info = getComponent("info") | const Info = getComponent("info") | ||||
@@ -24,7 +26,7 @@ export default class InfoContainer extends React.Component { | |||||
<div> | <div> | ||||
{info && info.count() ? ( | {info && info.count() ? ( | ||||
<Info info={info} url={url} host={host} basePath={basePath} externalDocs={externalDocs} | <Info info={info} url={url} host={host} basePath={basePath} externalDocs={externalDocs} | ||||
getComponent={getComponent}/> | |||||
getComponent={getComponent} selectedServer={selectedServer} /> | |||||
) : null} | ) : null} | ||||
</div> | </div> | ||||
) | ) | ||||
@@ -399,7 +399,7 @@ export const validatePattern = (val, rxPattern) => { | |||||
// validation of parameters before execute | // validation of parameters before execute | ||||
export const validateParam = (param, value, { isOAS3 = false, bypassRequiredCheck = false } = {}) => { | export const validateParam = (param, value, { isOAS3 = false, bypassRequiredCheck = false } = {}) => { | ||||
let errors = [] | let errors = [] | ||||
let paramRequired = param.get("required") | let paramRequired = param.get("required") | ||||
@@ -436,7 +436,7 @@ export const validateParam = (param, value, { isOAS3 = false, bypassRequiredChec | |||||
let objectStringCheck = type === "object" && typeof value === "string" && value | let objectStringCheck = type === "object" && typeof value === "string" && value | ||||
const allChecks = [ | const allChecks = [ | ||||
stringCheck, arrayCheck, arrayListCheck, arrayStringCheck, fileCheck, | |||||
stringCheck, arrayCheck, arrayListCheck, arrayStringCheck, fileCheck, | |||||
booleanCheck, numberCheck, integerCheck, objectCheck, objectStringCheck, | booleanCheck, numberCheck, integerCheck, objectCheck, objectStringCheck, | ||||
] | ] | ||||
@@ -640,7 +640,6 @@ export function sanitizeUrl(url) { | |||||
return braintreeSanitizeUrl(url) | return braintreeSanitizeUrl(url) | ||||
} | } | ||||
export function requiresValidationURL(uri) { | export function requiresValidationURL(uri) { | ||||
if (!uri || uri.indexOf("localhost") >= 0 || uri.indexOf("127.0.0.1") >= 0 || uri === "none") { | if (!uri || uri.indexOf("localhost") >= 0 || uri.indexOf("127.0.0.1") >= 0 || uri === "none") { | ||||
return false | return false | ||||
@@ -0,0 +1,23 @@ | |||||
export function isAbsoluteUrl(url) { | |||||
return url.match(/^(?:[a-z]+:)?\/\//i) // Matches http://, HTTP://, https://, ftp://, //example.com, | |||||
} | |||||
export function addProtocol(url) { | |||||
if(!url.match(/^\/\//i)) return url // Checks if protocol is missing e.g. //example.com | |||||
return `${window.location.protocol}${url}` | |||||
} | |||||
export function buildBaseUrl(selectedServer, specUrl) { | |||||
if(!selectedServer) return specUrl | |||||
if(isAbsoluteUrl(selectedServer)) return addProtocol(selectedServer) | |||||
return new URL(selectedServer, specUrl).href | |||||
} | |||||
export function buildUrl(url, specUrl, { selectedServer="" } = {}) { | |||||
if(!url) return | |||||
if(isAbsoluteUrl(url)) return url | |||||
const baseUrl = buildBaseUrl(selectedServer, specUrl) | |||||
return new URL(url, baseUrl).href | |||||
} |
@@ -17,7 +17,10 @@ describe("<InfoContainer/>", function () { | |||||
url () {}, | url () {}, | ||||
basePath () {}, | basePath () {}, | ||||
host () {}, | host () {}, | ||||
externalDocs () {} | |||||
externalDocs () {}, | |||||
}, | |||||
oas3Selectors: { | |||||
selectedServer () {}, | |||||
}, | }, | ||||
getComponent: c => components[c] | getComponent: c => components[c] | ||||
} | } | ||||
@@ -29,6 +29,7 @@ describe("<Operations/>", function(){ | |||||
}, | }, | ||||
specSelectors: { | specSelectors: { | ||||
isOAS3() { return false }, | isOAS3() { return false }, | ||||
url() { return "https://petstore.swagger.io/v2/swagger.json" }, | |||||
taggedOperations() { | taggedOperations() { | ||||
return fromJS({ | return fromJS({ | ||||
"default": { | "default": { | ||||
@@ -83,6 +84,7 @@ describe("<Operations/>", function(){ | |||||
}, | }, | ||||
specSelectors: { | specSelectors: { | ||||
isOAS3() { return true }, | isOAS3() { return true }, | ||||
url() { return "https://petstore.swagger.io/v2/swagger.json" }, | |||||
taggedOperations() { | taggedOperations() { | ||||
return fromJS({ | return fromJS({ | ||||
"default": { | "default": { | ||||
@@ -32,6 +32,13 @@ import { | |||||
generateCodeVerifier, | generateCodeVerifier, | ||||
createCodeChallenge, | createCodeChallenge, | ||||
} from "core/utils" | } from "core/utils" | ||||
import { | |||||
isAbsoluteUrl, | |||||
buildBaseUrl, | |||||
buildUrl, | |||||
} from "core/utils/url" | |||||
import win from "core/window" | import win from "core/window" | ||||
describe("utils", function() { | describe("utils", function() { | ||||
@@ -1334,6 +1341,92 @@ describe("utils", function() { | |||||
}) | }) | ||||
}) | }) | ||||
describe("isAbsoluteUrl", function() { | |||||
it("check if url is absolute", function() { | |||||
expect(!!isAbsoluteUrl("http://example.com")).toEqual(true) | |||||
expect(!!isAbsoluteUrl("https://secure-example.com")).toEqual(true) | |||||
expect(!!isAbsoluteUrl("HTTP://uppercase-example.com")).toEqual(true) | |||||
expect(!!isAbsoluteUrl("HTTP://uppercase-secure-example.com")).toEqual(true) | |||||
expect(!!isAbsoluteUrl("http://trailing-slash.com/")).toEqual(true) | |||||
expect(!!isAbsoluteUrl("ftp://file-transfer-protocol.com")).toEqual(true) | |||||
expect(!!isAbsoluteUrl("//no-protocol.com")).toEqual(true) | |||||
}) | |||||
it("check if url is not absolute", function() { | |||||
expect(!!isAbsoluteUrl("/url-relative-to-host/base-path/path")).toEqual(false) | |||||
expect(!!isAbsoluteUrl("url-relative-to-base/base-path/path")).toEqual(false) | |||||
}) | |||||
}) | |||||
describe("buildBaseUrl", function() { | |||||
const specUrl = "https://petstore.swagger.io/v2/swagger.json" | |||||
const noServerSelected = "" | |||||
const absoluteServerUrl = "https://server-example.com/base-path/path" | |||||
const serverUrlRelativeToBase = "server-example/base-path/path" | |||||
const serverUrlRelativeToHost = "/server-example/base-path/path" | |||||
it("build base url with no server selected", function() { | |||||
expect(buildBaseUrl(noServerSelected, specUrl)).toBe("https://petstore.swagger.io/v2/swagger.json") | |||||
}) | |||||
it("build base url from absolute server url", function() { | |||||
expect(buildBaseUrl(absoluteServerUrl, specUrl)).toBe("https://server-example.com/base-path/path") | |||||
}) | |||||
it("build base url from relative server url", function() { | |||||
expect(buildBaseUrl(serverUrlRelativeToBase, specUrl)).toBe("https://petstore.swagger.io/v2/server-example/base-path/path") | |||||
expect(buildBaseUrl(serverUrlRelativeToHost, specUrl)).toBe("https://petstore.swagger.io/server-example/base-path/path") | |||||
}) | |||||
}) | |||||
describe("buildUrl", function() { | |||||
const specUrl = "https://petstore.swagger.io/v2/swagger.json" | |||||
const noUrl = "" | |||||
const absoluteUrl = "https://example.com/base-path/path" | |||||
const urlRelativeToBase = "relative-url/base-path/path" | |||||
const urlRelativeToHost = "/relative-url/base-path/path" | |||||
const noServerSelected = "" | |||||
const absoluteServerUrl = "https://server-example.com/base-path/path" | |||||
const serverUrlRelativeToBase = "server-example/base-path/path" | |||||
const serverUrlRelativeToHost = "/server-example/base-path/path" | |||||
it("build no url", function() { | |||||
expect(buildUrl(noUrl, specUrl, { selectedServer: absoluteServerUrl })).toBe(undefined) | |||||
expect(buildUrl(noUrl, specUrl, { selectedServer: serverUrlRelativeToBase })).toBe(undefined) | |||||
expect(buildUrl(noUrl, specUrl, { selectedServer: serverUrlRelativeToHost })).toBe(undefined) | |||||
}) | |||||
it("build absolute url", function() { | |||||
expect(buildUrl(absoluteUrl, specUrl, { selectedServer: absoluteServerUrl })).toBe("https://example.com/base-path/path") | |||||
expect(buildUrl(absoluteUrl, specUrl, { selectedServer: serverUrlRelativeToBase })).toBe("https://example.com/base-path/path") | |||||
expect(buildUrl(absoluteUrl, specUrl, { selectedServer: serverUrlRelativeToHost })).toBe("https://example.com/base-path/path") | |||||
}) | |||||
it("build relative url with no server selected", function() { | |||||
expect(buildUrl(urlRelativeToBase, specUrl, { selectedServer: noServerSelected })).toBe("https://petstore.swagger.io/v2/relative-url/base-path/path") | |||||
expect(buildUrl(urlRelativeToHost, specUrl, { selectedServer: noServerSelected })).toBe("https://petstore.swagger.io/relative-url/base-path/path") | |||||
}) | |||||
it("build relative url with absolute server url", function() { | |||||
expect(buildUrl(urlRelativeToBase, specUrl, { selectedServer: absoluteServerUrl })).toBe("https://server-example.com/base-path/relative-url/base-path/path") | |||||
expect(buildUrl(urlRelativeToHost, specUrl, { selectedServer: absoluteServerUrl })).toBe("https://server-example.com/relative-url/base-path/path") | |||||
}) | |||||
it("build relative url with server url relative to base", function() { | |||||
expect(buildUrl(urlRelativeToBase, specUrl, { selectedServer: serverUrlRelativeToBase })).toBe("https://petstore.swagger.io/v2/server-example/base-path/relative-url/base-path/path") | |||||
expect(buildUrl(urlRelativeToHost, specUrl, { selectedServer: serverUrlRelativeToBase })).toBe("https://petstore.swagger.io/relative-url/base-path/path") | |||||
}) | |||||
it("build relative url with server url relative to host", function() { | |||||
expect(buildUrl(urlRelativeToBase, specUrl, { selectedServer: serverUrlRelativeToHost })).toBe("https://petstore.swagger.io/server-example/base-path/relative-url/base-path/path") | |||||
expect(buildUrl(urlRelativeToHost, specUrl, { selectedServer: serverUrlRelativeToHost })).toBe("https://petstore.swagger.io/relative-url/base-path/path") | |||||
}) | |||||
}) | |||||
describe("requiresValidationURL", function() { | describe("requiresValidationURL", function() { | ||||
it("Should tell us if we require a ValidationURL", function() { | it("Should tell us if we require a ValidationURL", function() { | ||||
const res = requiresValidationURL("https://example.com") | const res = requiresValidationURL("https://example.com") | ||||
@@ -18,7 +18,8 @@ describe("<Info/> Sanitization", function(){ | |||||
description: "Description *with* <script>Markdown</script>" | description: "Description *with* <script>Markdown</script>" | ||||
}), | }), | ||||
host: "example.test", | host: "example.test", | ||||
basePath: "/api" | |||||
basePath: "/api", | |||||
selectedServer: "https://example.test", | |||||
} | } | ||||
it("renders sanitized .title content", function(){ | it("renders sanitized .title content", function(){ | ||||