@@ -1,6 +1,9 @@ | |||
<!--- | |||
Thanks for filing an issue 😄 ! Before you submit, please read the following: | |||
If you're here to report a security issue, please STOP writing an issue and contact us | |||
at security@swagger.io instead! | |||
Search open/closed issues before submitting since someone might have asked the same thing before! | |||
Issues on GitHub are only related to problems of Swagger-UI itself. We'll try to offer support | |||
@@ -2,6 +2,7 @@ node_modules | |||
.idea | |||
.deps_check | |||
.DS_Store | |||
.nyc_output | |||
npm-debug.log* | |||
.eslintcache | |||
package-lock.json | |||
@@ -1,12 +1,16 @@ | |||
language: node_js | |||
node_js: | |||
- '6.9' | |||
cache: | |||
directories: | |||
- node_modules | |||
services: | |||
- docker | |||
branches: | |||
only: | |||
- master | |||
- /^v\d+\.\d+(\.\d+)?(-\S*)?$/ | |||
install: "npm i && npm update" | |||
before_deploy: | |||
- npm run build | |||
env: | |||
@@ -4,7 +4,7 @@ We love contributions from our community of users! This document explains our gu | |||
#### Environment setup | |||
0. Install Node.js (4 or newer) and npm (3 or newer). | |||
0. Install Node.js (6 or newer) and npm (3 or newer). | |||
1. Make a fork of Swagger-UI on GitHub, then clone your fork to your machine. | |||
2. Run `npm install` in your Swagger-UI directory. | |||
3. Run `npm run dev`. `localhost:3200` should open automatically. | |||
@@ -22,7 +22,7 @@ The OpenAPI Specification has undergone 5 revisions since initial creation in 20 | |||
Swagger UI Version | Release Date | OpenAPI Spec compatibility | Notes | |||
------------------ | ------------ | -------------------------- | ----- | |||
3.4.1 | 2017-10-20 | 2.0, 3.0 | [tag v3.4.1](https://github.com/swagger-api/swagger-ui/tree/v3.4.1) | |||
3.4.4 | 2017-11-03 | 2.0, 3.0 | [tag v3.4.4](https://github.com/swagger-api/swagger-ui/tree/v3.4.4) | |||
3.0.21 | 2017-07-26 | 2.0 | [tag v3.0.21](https://github.com/swagger-api/swagger-ui/tree/v3.0.21) | |||
2.2.10 | 2017-01-04 | 1.1, 1.2, 2.0 | [tag v2.2.10](https://github.com/swagger-api/swagger-ui/tree/v2.2.10) | |||
2.1.5 | 2016-07-20 | 1.1, 1.2, 2.0 | [tag v2.1.5](https://github.com/swagger-api/swagger-ui/tree/v2.1.5) | |||
@@ -20,8 +20,8 @@ Some distinct identifiers to Swagger-UI 3.X: | |||
If you've determined this is the version you have, to find the exact version: | |||
- Open your browser's web console (changes between browsers) | |||
- Type `versions` in the console and execute the call. | |||
- You might need to expand the result, until you get a string similar to `swaggerUi : Object { version: "3.1.6", gitRevision: "g786cd47", gitDirty: true, … }`. | |||
- Type `JSON.stringify(versions)` in the console and execute the call. | |||
- The result should look similar to `swaggerUi : Object { version: "3.1.6", gitRevision: "g786cd47", gitDirty: true, … }`. | |||
- The version taken from that example would be `3.1.6`. | |||
Note: This functionality was added in 3.0.8. If you're unable to execute it, you're likely to use an older version, and in that case the first step would be to upgrade. | |||
@@ -51,4 +51,4 @@ If you've determined this is the version you have, to find the exact version: | |||
* @link http://swagger.io | |||
* @license Apache-2.0 | |||
*/ | |||
``` | |||
``` |
@@ -1,6 +1,6 @@ | |||
{ | |||
"name": "swagger-ui", | |||
"version": "3.4.1", | |||
"version": "3.4.4", | |||
"main": "dist/swagger-ui.js", | |||
"repository": "git@github.com:swagger-api/swagger-ui.git", | |||
"contributors": [ | |||
@@ -33,12 +33,14 @@ | |||
"test-in-node": "npm run lint-errors && npm run just-test-in-node", | |||
"just-test": "karma start --config karma.conf.js", | |||
"just-test-in-node": "mocha --recursive --compilers js:babel-core/register test/core test/components test/bugs test/swagger-ui-dist-package test/xss", | |||
"just-check-coverage": "nyc npm run just-test-in-node", | |||
"test-e2e": "sleep 3 && nightwatch test/e2e/scenarios/ --config test/e2e/nightwatch.json", | |||
"e2e-initial-render": "nightwatch test/e2e/scenarios/ --config test/e2e/nightwatch.json --group initial-render", | |||
"mock-api": "json-server --watch test/e2e/db.json --port 3204", | |||
"e2e": "npm-run-all --parallel -r hot-server mock-api test-e2e" | |||
}, | |||
"dependencies": { | |||
"@braintree/sanitize-url": "^2.0.2", | |||
"base64-js": "^1.2.0", | |||
"brace": "0.7.0", | |||
"classnames": "^2.2.5", | |||
@@ -55,17 +57,17 @@ | |||
"memoizee": "0.4.1", | |||
"promise-worker": "^1.1.1", | |||
"prop-types": "^15.5.10", | |||
"react": "^15.4.0", | |||
"react": "^15.6.2", | |||
"react-addons-perf": "^15.4.0", | |||
"react-addons-shallow-compare": "0.14.8", | |||
"react-addons-test-utils": "^15.4.0", | |||
"react-collapse": "2.3.1", | |||
"react-dom": "^15.4.0", | |||
"react-addons-test-utils": "^15.6.2", | |||
"react-collapse": "^4.0.3", | |||
"react-dom": "^15.6.2", | |||
"react-height": "^2.0.0", | |||
"react-hot-loader": "1.3.1", | |||
"react-immutable-proptypes": "2.1.0", | |||
"react-markdown": "^2.5.0", | |||
"react-motion": "0.4.4", | |||
"react-motion": "^0.5.2", | |||
"react-object-inspector": "0.2.1", | |||
"react-redux": "^4.x.x", | |||
"react-split-pane": "0.1.57", | |||
@@ -78,11 +80,12 @@ | |||
"scroll-to-element": "^2.0.0", | |||
"serialize-error": "2.0.0", | |||
"shallowequal": "0.2.2", | |||
"swagger-client": "^3.3.1", | |||
"swagger-client": "^3.3.3", | |||
"url-parse": "^1.1.8", | |||
"whatwg-fetch": "0.11.1", | |||
"worker-loader": "^0.7.1", | |||
"xml": "1.0.1", | |||
"xml-but-prettier": "^1.0.1", | |||
"yaml-js": "0.2.0" | |||
}, | |||
"devDependencies": { | |||
@@ -125,6 +128,7 @@ | |||
"node-sass": "^4.5.0", | |||
"npm-run-all": "4.0.2", | |||
"null-loader": "0.1.1", | |||
"nyc": "^11.3.0", | |||
"open": "0.0.5", | |||
"postcss-loader": "2.0.6", | |||
"raw-loader": "0.5.1", | |||
@@ -150,5 +154,11 @@ | |||
], | |||
"optionalDependencies": { | |||
"webpack-dev-server": "2.5.0" | |||
}, | |||
"nyc": { | |||
"all": true, | |||
"include": [ | |||
"**/src/core/plugins/**.js" | |||
] | |||
} | |||
} |
@@ -24,24 +24,23 @@ export default class ArrayModel extends Component { | |||
const Markdown = getComponent("Markdown") | |||
const ModelCollapse = getComponent("ModelCollapse") | |||
const Model = getComponent("Model") | |||
const Property = getComponent("Property") | |||
const titleEl = title && | |||
<span className="model-title"> | |||
<span className="model-title__text">{ title }</span> | |||
</span> | |||
/* | |||
/* | |||
Note: we set `name={null}` in <Model> below because we don't want | |||
the name of the current Model passed (and displayed) as the name of the array element Model | |||
*/ | |||
*/ | |||
return <span className="model"> | |||
<ModelCollapse title={titleEl} collapsed={ depth > expandDepth } collapsedContent="[...]"> | |||
[ | |||
{ | |||
properties.size ? properties.entrySeq().map( ( [ key, v ] ) => <span key={`${key}-${v}`} style={ propStyle }> | |||
<br />{ key }: { String(v) }</span>) | |||
: null | |||
properties.size ? properties.entrySeq().map( ( [ key, v ] ) => <Property key={`${key}-${v}`} propKey={ key } propVal={ v } propStyle={ propStyle } />) : null | |||
} | |||
{ | |||
!description ? null : | |||
@@ -1,25 +1,23 @@ | |||
import React from "react" | |||
import PropTypes from "prop-types" | |||
import ImPropTypes from "react-immutable-proptypes" | |||
export default class AuthorizeOperationBtn extends React.Component { | |||
static propTypes = { | |||
isAuthorized: PropTypes.bool.isRequired, | |||
onClick: PropTypes.func | |||
} | |||
onClick =(e) => { | |||
e.stopPropagation() | |||
let { onClick } = this.props | |||
let { security, authActions, authSelectors } = this.props | |||
let definitions = authSelectors.getDefinitionsByNames(security) | |||
authActions.showDefinitions(definitions) | |||
if(onClick) { | |||
onClick() | |||
} | |||
} | |||
render() { | |||
let { security, authSelectors } = this.props | |||
let isAuthorized = authSelectors.isAuthorized(security) | |||
if(isAuthorized === null) { | |||
return null | |||
} | |||
let { isAuthorized } = this.props | |||
return ( | |||
<button className={isAuthorized ? "authorization__btn locked" : "authorization__btn unlocked"} onClick={ this.onClick }> | |||
@@ -30,10 +28,4 @@ export default class AuthorizeOperationBtn extends React.Component { | |||
) | |||
} | |||
static propTypes = { | |||
authSelectors: PropTypes.object.isRequired, | |||
authActions: PropTypes.object.isRequired, | |||
security: ImPropTypes.iterable.isRequired | |||
} | |||
} |
@@ -37,7 +37,7 @@ export default class ContentType extends React.Component { | |||
return ( | |||
<div className={ "content-type-wrapper " + ( className || "" ) }> | |||
<select className="content-type" value={value} onChange={this.onChangeWrapper} > | |||
<select className="content-type" value={value || ""} onChange={this.onChangeWrapper} > | |||
{ contentTypes.map( (val) => { | |||
return <option key={ val } value={ val }>{ val }</option> | |||
}).toArray()} | |||
@@ -1,6 +1,6 @@ | |||
import React from "react" | |||
import PropTypes from "prop-types" | |||
import Collapse from "react-collapse" | |||
import { Collapse } from "react-collapse" | |||
import { presets } from "react-motion" | |||
import ObjectInspector from "react-object-inspector" | |||
import Perf from "react-addons-perf" | |||
@@ -1,7 +1,7 @@ | |||
import React from "react" | |||
import PropTypes from "prop-types" | |||
import { List } from "immutable" | |||
import Collapse from "react-collapse" | |||
import { Collapse } from "react-collapse" | |||
export default class Errors extends React.Component { | |||
@@ -113,7 +113,7 @@ const SpecErrorItem = ( { error, jumpToLine } ) => { | |||
} | |||
function toTitleCase(str) { | |||
return str | |||
return (str || "") | |||
.split(" ") | |||
.map(substr => substr[0].toUpperCase() + substr.slice(1)) | |||
.join(" ") | |||
@@ -2,6 +2,7 @@ import React from "react" | |||
import PropTypes from "prop-types" | |||
import { fromJS } from "immutable" | |||
import ImPropTypes from "react-immutable-proptypes" | |||
import { sanitizeUrl } from "core/utils" | |||
class Path extends React.Component { | |||
@@ -35,9 +36,9 @@ class Contact extends React.Component { | |||
return ( | |||
<div> | |||
{ url && <div><a href={ url } target="_blank">{ name } - Website</a></div> } | |||
{ url && <div><a href={ sanitizeUrl(url) } target="_blank">{ name } - Website</a></div> } | |||
{ email && | |||
<a href={`mailto:${email}`}> | |||
<a href={sanitizeUrl(`mailto:${email}`)}> | |||
{ url ? `Send email to ${name}` : `Contact ${name}`} | |||
</a> | |||
} | |||
@@ -59,7 +60,7 @@ class License extends React.Component { | |||
return ( | |||
<div> | |||
{ | |||
url ? <a target="_blank" href={ url }>{ name }</a> | |||
url ? <a target="_blank" href={ sanitizeUrl(url) }>{ name }</a> | |||
: <span>{ name }</span> | |||
} | |||
</div> | |||
@@ -97,7 +98,7 @@ export default class Info extends React.Component { | |||
{ version && <VersionStamp version={version}></VersionStamp> } | |||
</h2> | |||
{ host || basePath ? <Path host={ host } basePath={ basePath } /> : null } | |||
{ url && <a target="_blank" href={ url }><span className="url"> { url } </span></a> } | |||
{ url && <a target="_blank" href={ sanitizeUrl(url) }><span className="url"> { url } </span></a> } | |||
</hgroup> | |||
<div className="description"> | |||
@@ -106,14 +107,14 @@ export default class Info extends React.Component { | |||
{ | |||
termsOfService && <div> | |||
<a target="_blank" href={ termsOfService }>Terms of service</a> | |||
<a target="_blank" href={ sanitizeUrl(termsOfService) }>Terms of service</a> | |||
</div> | |||
} | |||
{ contact && contact.size ? <Contact data={ contact } /> : null } | |||
{ license && license.size ? <License license={ license } /> : null } | |||
{ externalDocsUrl ? | |||
<a target="_blank" href={externalDocsUrl}>{externalDocsDescription || externalDocsUrl}</a> | |||
<a target="_blank" href={sanitizeUrl(externalDocsUrl)}>{externalDocsDescription || externalDocsUrl}</a> | |||
: null } | |||
</div> | |||
@@ -1,6 +1,6 @@ | |||
import React from "react" | |||
import PropTypes from "prop-types" | |||
import OriCollapse from "react-collapse" | |||
import { Collapse as OriCollapse } from "react-collapse" | |||
function xclass(...args) { | |||
return args.filter(a => !!a).join(" ").trim() | |||
@@ -1,7 +1,7 @@ | |||
import React, { Component } from "react" | |||
import React, { PureComponent } from "react" | |||
import PropTypes from "prop-types" | |||
export default class Model extends Component { | |||
export default class Model extends PureComponent { | |||
static propTypes = { | |||
schema: PropTypes.object.isRequired, | |||
getComponent: PropTypes.func.isRequired, | |||
@@ -35,7 +35,7 @@ export default class Model extends Component { | |||
const PrimitiveModel = getComponent("PrimitiveModel") | |||
let type = "object" | |||
let $$ref = schema && schema.get("$$ref") | |||
// If we weren't passed a `name` but have a ref, grab the name from the ref | |||
if ( !name && $$ref ) { | |||
name = this.getModelName( $$ref ) | |||
@@ -44,11 +44,11 @@ export default class Model extends Component { | |||
if ( !schema && $$ref ) { | |||
schema = this.getRefSchema( name ) | |||
} | |||
const deprecated = specSelectors.isOAS3() && schema.get("deprecated") | |||
isRef = isRef !== undefined ? isRef : !!$$ref | |||
type = schema && schema.get("type") || type | |||
switch(type) { | |||
case "object": | |||
return <ObjectModel | |||
@@ -21,6 +21,10 @@ export default class ObjectModel extends Component { | |||
let { specSelectors } = otherProps | |||
let { isOAS3 } = specSelectors | |||
if(!schema) { | |||
return null | |||
} | |||
let description = schema.get("description") | |||
let properties = schema.get("properties") | |||
let additionalProperties = schema.get("additionalProperties") | |||
@@ -1,5 +1,6 @@ | |||
import React from "react" | |||
import PropTypes from "prop-types" | |||
import { sanitizeUrl } from "core/utils" | |||
export default class OnlineValidatorBadge extends React.Component { | |||
static propTypes = { | |||
@@ -32,6 +33,8 @@ export default class OnlineValidatorBadge extends React.Component { | |||
let { getConfigs } = this.props | |||
let { spec } = getConfigs() | |||
let sanitizedValidatorUrl = sanitizeUrl(this.state.validatorUrl) | |||
if ( typeof spec === "object" && Object.keys(spec).length) return null | |||
if (!this.state.url || !this.state.validatorUrl || this.state.url.indexOf("localhost") >= 0 | |||
@@ -40,8 +43,8 @@ export default class OnlineValidatorBadge extends React.Component { | |||
} | |||
return (<span style={{ float: "right"}}> | |||
<a target="_blank" href={`${ this.state.validatorUrl }/debug?url=${ this.state.url }`}> | |||
<ValidatorImage src={`${ this.state.validatorUrl }?url=${ this.state.url }`} alt="Online validator badge"/> | |||
<a target="_blank" href={`${ sanitizedValidatorUrl }/debug?url=${ this.state.url }`}> | |||
<ValidatorImage src={`${ sanitizedValidatorUrl }?url=${ this.state.url }`} alt="Online validator badge"/> | |||
</a> | |||
</span>) | |||
} | |||
@@ -2,6 +2,7 @@ import React, { PureComponent } from "react" | |||
import PropTypes from "prop-types" | |||
import { getList } from "core/utils" | |||
import * as CustomPropTypes from "core/proptypes" | |||
import { sanitizeUrl } from "core/utils" | |||
//import "less/opblock" | |||
@@ -11,8 +12,10 @@ export default class Operation extends PureComponent { | |||
method: PropTypes.string.isRequired, | |||
operation: PropTypes.object.isRequired, | |||
showSummary: PropTypes.bool, | |||
isShown: PropTypes.bool.isRequired, | |||
isShownKey: CustomPropTypes.arrayOrString.isRequired, | |||
tagKey: PropTypes.string, | |||
operationKey: PropTypes.string, | |||
jumpToKey: CustomPropTypes.arrayOrString.isRequired, | |||
allowTryItOut: PropTypes.bool, | |||
@@ -51,38 +54,16 @@ export default class Operation extends PureComponent { | |||
} | |||
componentWillReceiveProps(nextProps) { | |||
const defaultContentType = "application/json" | |||
let { specActions, path, method, operation } = nextProps | |||
let producesValue = operation.get("produces_value") | |||
let produces = operation.get("produces") | |||
let consumes = operation.get("consumes") | |||
let consumesValue = operation.get("consumes_value") | |||
if(nextProps.response !== this.props.response) { | |||
this.setState({ executeInProgress: false }) | |||
} | |||
if (producesValue === undefined) { | |||
producesValue = produces && produces.size ? produces.first() : defaultContentType | |||
specActions.changeProducesValue([path, method], producesValue) | |||
} | |||
if (consumesValue === undefined) { | |||
consumesValue = consumes && consumes.size ? consumes.first() : defaultContentType | |||
specActions.changeConsumesValue([path, method], consumesValue) | |||
} | |||
} | |||
toggleShown =() => { | |||
let { layoutActions, isShownKey } = this.props | |||
layoutActions.show(isShownKey, !this.isShown()) | |||
} | |||
isShown =() => { | |||
let { layoutSelectors, isShownKey, getConfigs } = this.props | |||
let { docExpansion } = getConfigs() | |||
let { layoutActions, tagKey, operationKey, isShown } = this.props | |||
const isShownKey = ["operations", tagKey, operationKey] | |||
return layoutSelectors.isShown(isShownKey, docExpansion === "full" ) // Here is where we set the default | |||
layoutActions.show(isShownKey, !isShown) | |||
} | |||
onTryoutClick =() => { | |||
@@ -101,7 +82,9 @@ export default class Operation extends PureComponent { | |||
render() { | |||
let { | |||
isShownKey, | |||
operationKey, | |||
tagKey, | |||
isShown, | |||
jumpToKey, | |||
path, | |||
method, | |||
@@ -155,18 +138,17 @@ export default class Operation extends PureComponent { | |||
} | |||
let { tryItOutEnabled } = this.state | |||
let shown = this.isShown() | |||
let onChangeKey = [ path, method ] // Used to add values to _this_ operation ( indexed by path and method ) | |||
return ( | |||
<div className={deprecated ? "opblock opblock-deprecated" : shown ? `opblock opblock-${method} is-open` : `opblock opblock-${method}`} id={isShownKey.join("-")} > | |||
<div className={deprecated ? "opblock opblock-deprecated" : isShown ? `opblock opblock-${method} is-open` : `opblock opblock-${method}`} id={`operations-${tagKey}-${operationKey}`} > | |||
<div className={`opblock-summary opblock-summary-${method}`} onClick={this.toggleShown} > | |||
<span className="opblock-summary-method">{method.toUpperCase()}</span> | |||
<span className={ deprecated ? "opblock-summary-path__deprecated" : "opblock-summary-path" } > | |||
<a | |||
className="nostyle" | |||
onClick={isDeepLinkingEnabled ? (e) => e.preventDefault() : null} | |||
href={isDeepLinkingEnabled ? `#/${isShownKey[1]}/${isShownKey[2]}` : null}> | |||
href={isDeepLinkingEnabled ? `#/${tagKey}/${operationKey}` : null}> | |||
<span>{path}</span> | |||
</a> | |||
<JumpToPath path={jumpToKey} /> | |||
@@ -182,13 +164,17 @@ export default class Operation extends PureComponent { | |||
{ | |||
(!security || !security.count()) ? null : | |||
<AuthorizeOperationBtn authActions={ authActions } | |||
security={ security } | |||
authSelectors={ authSelectors }/> | |||
<AuthorizeOperationBtn | |||
isAuthorized={ authSelectors.isAuthorized(security) } | |||
onClick={() => { | |||
const applicableDefinitions = authSelectors.definitionsForRequirements(security) | |||
authActions.showDefinitions(applicableDefinitions) | |||
}} | |||
/> | |||
} | |||
</div> | |||
<Collapse isOpened={shown}> | |||
<Collapse isOpened={isShown}> | |||
<div className="opblock-body"> | |||
{ deprecated && <h4 className="opblock-title_normal"> Warning: Deprecated</h4>} | |||
{ description && | |||
@@ -206,7 +192,7 @@ export default class Operation extends PureComponent { | |||
<span className="opblock-external-docs__description"> | |||
<Markdown source={ externalDocs.get("description") } /> | |||
</span> | |||
<a className="opblock-external-docs__link" href={ externalDocs.get("url") }>{ externalDocs.get("url") }</a> | |||
<a className="opblock-external-docs__link" href={ sanitizeUrl(externalDocs.get("url")) }>{ externalDocs.get("url") }</a> | |||
</div> | |||
</div> : null | |||
} | |||
@@ -1,7 +1,7 @@ | |||
import React from "react" | |||
import PropTypes from "prop-types" | |||
import { helpers } from "swagger-client" | |||
import { createDeepLinkPath } from "core/utils" | |||
import { createDeepLinkPath, sanitizeUrl } from "core/utils" | |||
const { opId } = helpers | |||
export default class Operations extends React.Component { | |||
@@ -101,7 +101,7 @@ export default class Operations extends React.Component { | |||
{ tagExternalDocsUrl ? ": " : null } | |||
{ tagExternalDocsUrl ? | |||
<a | |||
href={tagExternalDocsUrl} | |||
href={sanitizeUrl(tagExternalDocsUrl)} | |||
onClick={(e) => e.stopPropagation()} | |||
target={"_blank"} | |||
>{tagExternalDocsUrl}</a> : null | |||
@@ -127,7 +127,8 @@ export default class Operations extends React.Component { | |||
const operationId = | |||
op.getIn(["operation", "operationId"]) || op.getIn(["operation", "__originalOperationId"]) || opId(op.get("operation"), path, method) || op.get("id") | |||
const isShownKey = ["operations", createDeepLinkPath(tag), createDeepLinkPath(operationId)] | |||
const tagKey = createDeepLinkPath(tag) | |||
const operationKey = createDeepLinkPath(operationId) | |||
const allowTryItOut = specSelectors.allowTryItOutFor(op.get("path"), op.get("method")) | |||
const response = specSelectors.responseFor(op.get("path"), op.get("method")) | |||
@@ -135,11 +136,12 @@ export default class Operations extends React.Component { | |||
return <Operation | |||
{...op.toObject()} | |||
isShownKey={isShownKey} | |||
tagKey={tagKey} | |||
operationKey={operationKey} | |||
isShown={layoutSelectors.isShown(["operations", tagKey, operationKey], docExpansion === "full")} | |||
jumpToKey={jumpToKey} | |||
showSummary={showSummary} | |||
key={isShownKey} | |||
key={tagKey + operationKey} | |||
response={ response } | |||
request={ request } | |||
allowTryItOut={allowTryItOut} | |||
@@ -28,6 +28,7 @@ export default class Primitive extends Component { | |||
let properties = schema.filter( ( v, key) => ["enum", "type", "format", "description", "$$ref"].indexOf(key) === -1 ) | |||
const Markdown = getComponent("Markdown") | |||
const EnumModel = getComponent("EnumModel") | |||
const Property = getComponent("Property") | |||
return <span className="model"> | |||
<span className="prop"> | |||
@@ -35,9 +36,7 @@ export default class Primitive extends Component { | |||
<span className="prop-type">{ type }</span> | |||
{ format && <span className="prop-format">(${format})</span>} | |||
{ | |||
properties.size ? properties.entrySeq().map( ( [ key, v ] ) => <span key={`${key}-${v}`} style={ propStyle }> | |||
<br />{ key }: { String(v) }</span>) | |||
: null | |||
properties.size ? properties.entrySeq().map( ( [ key, v ] ) => <Property key={`${key}-${v}`} propKey={ key } propVal={ v } propStyle={ propStyle } />) : null | |||
} | |||
{ | |||
!description ? null : | |||
@@ -56,4 +55,4 @@ export default class Primitive extends Component { | |||
</span> | |||
</span> | |||
} | |||
} | |||
} |
@@ -0,0 +1,16 @@ | |||
import React from "react" | |||
import PropTypes from "prop-types" | |||
export const Property = ({ propKey, propVal, propStyle }) => { | |||
return ( | |||
<span style={ propStyle }> | |||
<br />{ propKey }: { String(propVal) }</span> | |||
) | |||
} | |||
Property.propTypes = { | |||
propKey: PropTypes.string, | |||
propVal: PropTypes.any, | |||
propStyle: PropTypes.object | |||
} | |||
export default Property |
@@ -1,6 +1,6 @@ | |||
import React from "react" | |||
import PropTypes from "prop-types" | |||
import { formatXml } from "core/utils" | |||
import formatXml from "xml-but-prettier" | |||
import lowerCase from "lodash/lowerCase" | |||
export default class ResponseBody extends React.Component { | |||
@@ -31,7 +31,10 @@ export default class ResponseBody extends React.Component { | |||
// XML | |||
} else if (/xml/i.test(contentType)) { | |||
body = formatXml(content) | |||
body = formatXml(content, { | |||
textNodesOnSameLine: true, | |||
indentor: " " | |||
}) | |||
bodyEl = <HighlightCode value={ body } /> | |||
// HTML or Plain Text | |||
@@ -58,13 +58,12 @@ module.exports = function SwaggerUI(opts) { | |||
plugins: [ | |||
], | |||
// Initial state | |||
initialState: { }, | |||
// Inline Plugin | |||
fn: { }, | |||
components: { }, | |||
state: { }, | |||
// Override some core configs... at your own risk | |||
store: { }, | |||
} | |||
let queryConfig = parseSearch() | |||
@@ -74,12 +73,12 @@ module.exports = function SwaggerUI(opts) { | |||
const constructorConfig = deepExtend({}, defaults, opts, queryConfig) | |||
const storeConfigs = deepExtend({}, constructorConfig.store, { | |||
const storeConfigs = { | |||
system: { | |||
configs: constructorConfig.configs | |||
}, | |||
plugins: constructorConfig.presets, | |||
state: { | |||
state: deepExtend({ | |||
layout: { | |||
layout: constructorConfig.layout, | |||
filter: constructorConfig.filter | |||
@@ -88,8 +87,8 @@ module.exports = function SwaggerUI(opts) { | |||
spec: "", | |||
url: constructorConfig.url | |||
} | |||
} | |||
}) | |||
}, constructorConfig.initialState) | |||
} | |||
let inlinePlugin = ()=> { | |||
return { | |||
@@ -58,6 +58,7 @@ export class JsonSchema_string extends Component { | |||
if ( enumValue ) { | |||
const Select = getComponent("Select") | |||
return (<Select className={ errors.length ? "invalid" : ""} | |||
title={ errors.length ? errors : ""} | |||
allowedValues={ enumValue } | |||
value={ value } | |||
allowEmptyValue={ !required } | |||
@@ -67,10 +68,20 @@ export class JsonSchema_string extends Component { | |||
const isDisabled = schema["in"] === "formData" && !("FormData" in window) | |||
const Input = getComponent("Input") | |||
if (schema["type"] === "file") { | |||
return <Input type="file" className={ errors.length ? "invalid" : ""} onChange={ this.onChange } disabled={isDisabled}/> | |||
return (<Input type="file" | |||
className={ errors.length ? "invalid" : ""} | |||
title={ errors.length ? errors : ""} | |||
onChange={ this.onChange } | |||
disabled={isDisabled}/>) | |||
} | |||
else { | |||
return <Input type={ schema.format === "password" ? "password" : "text" } className={ errors.length ? "invalid" : ""} value={value} placeholder={description} onChange={ this.onChange } disabled={isDisabled}/> | |||
return (<Input type={ schema.format === "password" ? "password" : "text" } | |||
className={ errors.length ? "invalid" : ""} | |||
title={ errors.length ? errors : ""} | |||
value={value} | |||
placeholder={description} | |||
onChange={ this.onChange } | |||
disabled={isDisabled}/>) | |||
} | |||
} | |||
} | |||
@@ -134,11 +145,12 @@ export class JsonSchema_array extends PureComponent { | |||
if ( enumValue ) { | |||
const Select = getComponent("Select") | |||
return (<Select className={ errors.length ? "invalid" : ""} | |||
multiple={ true } | |||
value={ value } | |||
allowedValues={ enumValue } | |||
allowEmptyValue={ !required } | |||
onChange={ this.onEnumChange }/>) | |||
title={ errors.length ? errors : ""} | |||
multiple={ true } | |||
value={ value } | |||
allowedValues={ enumValue } | |||
allowEmptyValue={ !required } | |||
onChange={ this.onEnumChange }/>) | |||
} | |||
return ( | |||
@@ -175,6 +187,7 @@ export class JsonSchema_boolean extends Component { | |||
const Select = getComponent("Select") | |||
return (<Select className={ errors.length ? "invalid" : ""} | |||
title={ errors.length ? errors : ""} | |||
value={ String(value) } | |||
allowedValues={ fromJS(["true", "false"]) } | |||
allowEmptyValue={ true } | |||
@@ -11,7 +11,7 @@ export const shownDefinitions = createSelector( | |||
export const definitionsToAuthorize = createSelector( | |||
state, | |||
() => ( { specSelectors } ) => { | |||
let definitions = specSelectors.securityDefinitions() | |||
let definitions = specSelectors.securityDefinitions() || Map({}) | |||
let list = List() | |||
//todo refactor | |||
@@ -28,6 +28,7 @@ export const definitionsToAuthorize = createSelector( | |||
export const getDefinitionsByNames = ( state, securities ) => ( { specSelectors } ) => { | |||
console.warn("WARNING: getDefinitionsByNames is deprecated and will be removed in the next major version.") | |||
let securityDefinitions = specSelectors.securityDefinitions() | |||
let result = List() | |||
@@ -58,6 +59,13 @@ export const getDefinitionsByNames = ( state, securities ) => ( { specSelectors | |||
return result | |||
} | |||
export const definitionsForRequirements = (state, securities = List()) => ({ authSelectors }) => { | |||
const allDefinitions = authSelectors.definitionsToAuthorize() || List() | |||
return allDefinitions.filter((def) => { | |||
return securities.some(sec => sec.get(def.keySeq().first())) | |||
}) | |||
} | |||
export const authorized = createSelector( | |||
state, | |||
auth => auth.get("authorized") || Map() | |||
@@ -3,6 +3,7 @@ import serializeError from "serialize-error" | |||
export const NEW_THROWN_ERR = "err_new_thrown_err" | |||
export const NEW_THROWN_ERR_BATCH = "err_new_thrown_err_batch" | |||
export const NEW_SPEC_ERR = "err_new_spec_err" | |||
export const NEW_SPEC_ERR_BATCH = "err_new_spec_err_batch" | |||
export const NEW_AUTH_ERR = "err_new_auth_err" | |||
export const CLEAR = "err_clear" | |||
@@ -27,6 +28,13 @@ export function newSpecErr(err) { | |||
} | |||
} | |||
export function newSpecErrBatch(errArray) { | |||
return { | |||
type: NEW_SPEC_ERR_BATCH, | |||
payload: errArray | |||
} | |||
} | |||
export function newAuthErr(err) { | |||
return { | |||
type: NEW_AUTH_ERR, | |||
@@ -2,6 +2,7 @@ import { | |||
NEW_THROWN_ERR, | |||
NEW_THROWN_ERR_BATCH, | |||
NEW_SPEC_ERR, | |||
NEW_SPEC_ERR_BATCH, | |||
NEW_AUTH_ERR, | |||
CLEAR | |||
} from "./actions" | |||
@@ -45,6 +46,15 @@ export default function(system) { | |||
.update("errors", errors => transformErrors(errors, system.getSystem())) | |||
}, | |||
[NEW_SPEC_ERR_BATCH]: (state, { payload }) => { | |||
payload = payload.map(err => { | |||
return fromJS(Object.assign(DEFAULT_ERROR_STRUCTURE, err, { type: "spec" })) | |||
}) | |||
return state | |||
.update("errors", errors => (errors || List()).concat( fromJS( payload )) ) | |||
.update("errors", errors => transformErrors(errors, system.getSystem())) | |||
}, | |||
[NEW_AUTH_ERR]: (state, { payload }) => { | |||
let error = fromJS(Object.assign({}, payload)) | |||
@@ -108,9 +108,6 @@ export default class HttpAuth extends React.Component { | |||
<Row> | |||
<Markdown source={ schema.get("description") } /> | |||
</Row> | |||
<Row> | |||
<p>In: <code>{ schema.get("in") }</code></p> | |||
</Row> | |||
<Row> | |||
<label>Value:</label> | |||
{ | |||
@@ -50,7 +50,7 @@ RequestBody.propTypes = { | |||
getComponent: PropTypes.func.isRequired, | |||
getConfigs: PropTypes.func.isRequired, | |||
specSelectors: PropTypes.object.isRequired, | |||
contentType: PropTypes.string.isRequired, | |||
contentType: PropTypes.string, | |||
isExecute: PropTypes.bool.isRequired, | |||
onChange: PropTypes.func.isRequired | |||
} | |||
@@ -48,6 +48,10 @@ export const definitions = onlyOAS3(createSelector( | |||
spec => spec.getIn(["components", "schemas"]) || Map() | |||
)) | |||
export const hasHost = onlyOAS3((state) => { | |||
return spec(state).hasIn(["servers", 0]) | |||
}) | |||
export const securityDefinitions = onlyOAS3(createSelector( | |||
spec, | |||
spec => spec.getIn(["components", "securitySchemes"]) || null | |||
@@ -22,6 +22,7 @@ class Parameters extends Component { | |||
specActions: PropTypes.object.isRequired, | |||
operation: PropTypes.object.isRequired, | |||
getComponent: PropTypes.func.isRequired, | |||
getConfigs: PropTypes.func.isRequired, | |||
specSelectors: PropTypes.object.isRequired, | |||
oas3Actions: PropTypes.object.isRequired, | |||
oas3Selectors: PropTypes.object.isRequired, | |||
@@ -86,6 +87,7 @@ class Parameters extends Component { | |||
fn, | |||
getComponent, | |||
getConfigs, | |||
specSelectors, | |||
oas3Actions, | |||
oas3Selectors, | |||
@@ -137,6 +139,7 @@ class Parameters extends Component { | |||
eachMap(parameters, (parameter) => ( | |||
<ParameterRow fn={ fn } | |||
getComponent={ getComponent } | |||
getConfigs={ getConfigs } | |||
param={ parameter } | |||
key={ parameter.get( "name" ) } | |||
onChange={ this.onChange } | |||
@@ -10,6 +10,7 @@ import auth from "core/plugins/auth" | |||
import util from "core/plugins/util" | |||
import SplitPaneModePlugin from "core/plugins/split-pane-mode" | |||
import downloadUrlPlugin from "core/plugins/download-url" | |||
import configsPlugin from "plugins/configs" | |||
import deepLinkingPlugin from "core/plugins/deep-linking" | |||
import App from "core/components/app" | |||
@@ -52,6 +53,7 @@ import EnumModel from "core/components/enum-model" | |||
import ObjectModel from "core/components/object-model" | |||
import ArrayModel from "core/components/array-model" | |||
import PrimitiveModel from "core/components/primitive-model" | |||
import Property from "core/components/property" | |||
import TryItOutButton from "core/components/try-it-out-button" | |||
import VersionStamp from "core/components/version-stamp" | |||
@@ -106,6 +108,7 @@ export default function() { | |||
ObjectModel, | |||
ArrayModel, | |||
PrimitiveModel, | |||
Property, | |||
TryItOutButton, | |||
Markdown, | |||
BaseLayout, | |||
@@ -122,6 +125,7 @@ export default function() { | |||
} | |||
return [ | |||
configsPlugin, | |||
util, | |||
logs, | |||
view, | |||
@@ -1,5 +1,5 @@ | |||
import Im from "immutable" | |||
import { sanitizeUrl as braintreeSanitizeUrl } from "@braintree/sanitize-url" | |||
import camelCase from "lodash/camelCase" | |||
import upperFirst from "lodash/upperFirst" | |||
import _memoize from "lodash/memoize" | |||
@@ -155,83 +155,6 @@ export function getList(iterable, keys) { | |||
return Im.List.isList(val) ? val : Im.List() | |||
} | |||
// Adapted from http://stackoverflow.com/a/2893259/454004 | |||
// Note: directly ported from CoffeeScript | |||
export function formatXml (xml) { | |||
var contexp, fn, formatted, indent, l, lastType, len, lines, ln, reg, transitions, wsexp | |||
reg = /(>)(<)(\/*)/g | |||
wsexp = /[ ]*(.*)[ ]+\n/g | |||
contexp = /(<.+>)(.+\n)/g | |||
xml = xml.replace(/\r\n/g, "\n").replace(reg, "$1\n$2$3").replace(wsexp, "$1\n").replace(contexp, "$1\n$2") | |||
formatted = "" | |||
lines = xml.split("\n") | |||
indent = 0 | |||
lastType = "other" | |||
transitions = { | |||
"single->single": 0, | |||
"single->closing": -1, | |||
"single->opening": 0, | |||
"single->other": 0, | |||
"closing->single": 0, | |||
"closing->closing": -1, | |||
"closing->opening": 0, | |||
"closing->other": 0, | |||
"opening->single": 1, | |||
"opening->closing": 0, | |||
"opening->opening": 1, | |||
"opening->other": 1, | |||
"other->single": 0, | |||
"other->closing": -1, | |||
"other->opening": 0, | |||
"other->other": 0 | |||
} | |||
fn = function(ln) { | |||
var fromTo, key, padding, type, types, value | |||
types = { | |||
single: Boolean(ln.match(/<.+\/>/)), | |||
closing: Boolean(ln.match(/<\/.+>/)), | |||
opening: Boolean(ln.match(/<[^!?].*>/)) | |||
} | |||
type = ((function() { | |||
var results | |||
results = [] | |||
for (key in types) { | |||
value = types[key] | |||
if (value) { | |||
results.push(key) | |||
} | |||
} | |||
return results | |||
})())[0] | |||
type = type === void 0 ? "other" : type | |||
fromTo = lastType + "->" + type | |||
lastType = type | |||
padding = "" | |||
indent += transitions[fromTo] | |||
padding = ((function() { | |||
/* eslint-disable no-unused-vars */ | |||
var m, ref1, results, j | |||
results = [] | |||
for (j = m = 0, ref1 = indent; 0 <= ref1 ? m < ref1 : m > ref1; j = 0 <= ref1 ? ++m : --m) { | |||
results.push(" ") | |||
} | |||
/* eslint-enable no-unused-vars */ | |||
return results | |||
})()).join("") | |||
if (fromTo === "opening->closing") { | |||
formatted = formatted.substr(0, formatted.length - 1) + ln + "\n" | |||
} else { | |||
formatted += padding + ln + "\n" | |||
} | |||
} | |||
for (l = 0, len = lines.length; l < len; l++) { | |||
ln = lines[l] | |||
fn(ln) | |||
} | |||
return formatted | |||
} | |||
/** | |||
* Adapted from http://github.com/asvd/microlight | |||
* @copyright 2016 asvd <heliosframework@gmail.com> | |||
@@ -536,6 +459,13 @@ export const validateMinLength = (val, min) => { | |||
} | |||
} | |||
export const validatePattern = (val, rxPattern) => { | |||
var patt = new RegExp(rxPattern) | |||
if (!patt.test(val)) { | |||
return "Value must follow pattern " + rxPattern | |||
} | |||
} | |||
// validation of parameters before execute | |||
export const validateParam = (param, isXml, isOAS3 = false) => { | |||
let errors = [] | |||
@@ -549,6 +479,8 @@ export const validateParam = (param, isXml, isOAS3 = false) => { | |||
let format = paramDetails.get("format") | |||
let maxLength = paramDetails.get("maxLength") | |||
let minLength = paramDetails.get("minLength") | |||
let pattern = paramDetails.get("pattern") | |||
/* | |||
If the parameter is required OR the parameter has a value (meaning optional, but filled in) | |||
@@ -556,15 +488,25 @@ export const validateParam = (param, isXml, isOAS3 = false) => { | |||
Only bother validating the parameter if the type was specified. | |||
*/ | |||
if ( type && (required || value) ) { | |||
// These checks should evaluate to true if the parameter's value is valid | |||
let stringCheck = type === "string" && value && !validateString(value) | |||
// These checks should evaluate to true if there is a parameter | |||
let stringCheck = type === "string" && value | |||
let arrayCheck = type === "array" && Array.isArray(value) && value.length | |||
let listCheck = type === "array" && Im.List.isList(value) && value.count() | |||
let fileCheck = type === "file" && value instanceof win.File | |||
let booleanCheck = type === "boolean" && !validateBoolean(value) | |||
let numberCheck = type === "number" && !validateNumber(value) // validateNumber returns undefined if the value is a number | |||
let integerCheck = type === "integer" && !validateInteger(value) // validateInteger returns undefined if the value is an integer | |||
let booleanCheck = type === "boolean" && (value || value === false) | |||
let numberCheck = type === "number" && (value || value === 0) | |||
let integerCheck = type === "integer" && (value || value === 0) | |||
if ( required && !(stringCheck || arrayCheck || listCheck || fileCheck || booleanCheck || numberCheck || integerCheck) ) { | |||
errors.push("Required field is not provided") | |||
return errors | |||
} | |||
if (pattern) { | |||
let err = validatePattern(value, pattern) | |||
if (err) errors.push(err) | |||
} | |||
if (maxLength || maxLength === 0) { | |||
let err = validateMaxLength(value, maxLength) | |||
if (err) errors.push(err) | |||
@@ -575,11 +517,6 @@ export const validateParam = (param, isXml, isOAS3 = false) => { | |||
if (err) errors.push(err) | |||
} | |||
if ( required && !(stringCheck || arrayCheck || listCheck || fileCheck || booleanCheck || numberCheck || integerCheck) ) { | |||
errors.push("Required field is not provided") | |||
return errors | |||
} | |||
if (maximum || maximum === 0) { | |||
let err = validateMaximum(value, maximum) | |||
if (err) errors.push(err) | |||
@@ -722,6 +659,14 @@ export const shallowEqualKeys = (a,b, keys) => { | |||
}) | |||
} | |||
export function sanitizeUrl(url) { | |||
if(typeof url !== "string" || url === "") { | |||
return "" | |||
} | |||
return braintreeSanitizeUrl(url) | |||
} | |||
export function getAcceptControllingResponse(responses) { | |||
if(!Im.OrderedMap.isOrderedMap(responses)) { | |||
// wrong type! | |||
@@ -0,0 +1,20 @@ | |||
export const UPDATE_CONFIGS = "configs_update" | |||
export const TOGGLE_CONFIGS = "configs_toggle" | |||
// Update the configs, with a merge ( not deep ) | |||
export function update(configName, configValue) { | |||
return { | |||
type: UPDATE_CONFIGS, | |||
payload: { | |||
[configName]: configValue | |||
}, | |||
} | |||
} | |||
// Toggle's the config, by name | |||
export function toggle(configName) { | |||
return { | |||
type: TOGGLE_CONFIGS, | |||
payload: configName, | |||
} | |||
} |
@@ -1,56 +1,66 @@ | |||
import YAML from "js-yaml" | |||
import yamlConfig from "../../../swagger-config.yaml" | |||
import * as actions from "./actions" | |||
import * as selectors from "./selectors" | |||
import reducers from "./reducers" | |||
const parseYamlConfig = (yaml, system) => { | |||
try { | |||
return YAML.safeLoad(yaml) | |||
} catch(e) { | |||
if (system) { | |||
system.errActions.newThrownErr( new Error(e) ) | |||
} | |||
return {} | |||
try { | |||
return YAML.safeLoad(yaml) | |||
} catch(e) { | |||
if (system) { | |||
system.errActions.newThrownErr( new Error(e) ) | |||
} | |||
return {} | |||
} | |||
} | |||
export default function configPlugin (toolbox) { | |||
let { fn } = toolbox | |||
const actions = { | |||
downloadConfig: (url) => () => { | |||
let {fetch} = fn | |||
return fetch(url) | |||
}, | |||
getConfigByUrl: (configUrl, cb)=> ({ specActions }) => { | |||
if (configUrl) { | |||
return specActions.downloadConfig(configUrl).then(next, next) | |||
} | |||
function next(res) { | |||
if (res instanceof Error || res.status >= 400) { | |||
specActions.updateLoadingStatus("failedConfig") | |||
specActions.updateLoadingStatus("failedConfig") | |||
specActions.updateUrl("") | |||
console.error(res.statusText + " " + configUrl) | |||
cb(null) | |||
} else { | |||
cb(parseYamlConfig(res.text)) | |||
} | |||
} | |||
} | |||
const specActions = { | |||
downloadConfig: (url) => ({fn}) => { | |||
let {fetch} = fn | |||
return fetch(url) | |||
}, | |||
getConfigByUrl: (configUrl, cb)=> ({ specActions }) => { | |||
if (configUrl) { | |||
return specActions.downloadConfig(configUrl).then(next, next) | |||
} | |||
const selectors = { | |||
getLocalConfig: () => { | |||
return parseYamlConfig(yamlConfig) | |||
} | |||
function next(res) { | |||
if (res instanceof Error || res.status >= 400) { | |||
specActions.updateLoadingStatus("failedConfig") | |||
specActions.updateLoadingStatus("failedConfig") | |||
specActions.updateUrl("") | |||
console.error(res.statusText + " " + configUrl) | |||
cb(null) | |||
} else { | |||
cb(parseYamlConfig(res.text)) | |||
} | |||
} | |||
} | |||
} | |||
const specSelectors = { | |||
getLocalConfig: () => { | |||
return parseYamlConfig(yamlConfig) | |||
} | |||
} | |||
export default function configsPlugin() { | |||
return { | |||
statePlugins: { | |||
spec: { actions, selectors } | |||
} | |||
return { | |||
statePlugins: { | |||
spec: { | |||
actions: specActions, | |||
selectors: specSelectors, | |||
}, | |||
configs: { | |||
reducers, | |||
actions, | |||
selectors, | |||
} | |||
} | |||
} | |||
} |
@@ -0,0 +1,20 @@ | |||
import { fromJS } from "immutable" | |||
import { | |||
UPDATE_CONFIGS, | |||
TOGGLE_CONFIGS, | |||
} from "./actions" | |||
export default { | |||
[UPDATE_CONFIGS]: (state, action) => { | |||
return state.merge(fromJS(action.payload)) | |||
}, | |||
[TOGGLE_CONFIGS]: (state, action) => { | |||
const configName = action.payload | |||
const oriVal = state.get(configName) | |||
return state.set(configName, !oriVal) | |||
}, | |||
} |
@@ -0,0 +1,4 @@ | |||
// Just get the config value ( it can possibly be an immutable object) | |||
export const get = (state, path) => { | |||
return state.getIn(Array.isArray(path) ? path : [path]) | |||
} |
@@ -1,4 +1,4 @@ | |||
import React from "react" | |||
import React, { cloneElement } from "react" | |||
import PropTypes from "prop-types" | |||
//import "./topbar.less" | |||
@@ -134,7 +134,7 @@ export default class Topbar extends React.Component { | |||
<span>swagger</span> | |||
</Link> | |||
<form className="download-url-wrapper" onSubmit={formOnSubmit}> | |||
{control} | |||
{control.map((el, i) => cloneElement(el, { key: i }))} | |||
</form> | |||
</div> | |||
</div> | |||
@@ -25,7 +25,7 @@ | |||
margin: 0 0 10px 0; | |||
padding: 10px 20px; | |||
border-bottom: 1px solid #ebebeb; | |||
border-bottom: 1px solid $auth-container-border-color; | |||
&:last-of-type | |||
{ | |||
@@ -7,10 +7,10 @@ | |||
transition: all .3s; | |||
border: 2px solid #888; | |||
border: 2px solid $btn-border-color; | |||
border-radius: 4px; | |||
background: transparent; | |||
box-shadow: 0 1px 2px rgba(#000,.1); | |||
box-shadow: 0 1px 2px rgba($btn-box-shadow-color,.1); | |||
@include text_headline(); | |||
@@ -29,14 +29,14 @@ | |||
&:hover | |||
{ | |||
box-shadow: 0 0 5px rgba(#000,.3); | |||
box-shadow: 0 0 5px rgba($btn-box-shadow-color,.3); | |||
} | |||
&.cancel | |||
{ | |||
border-color: #ff6060; | |||
@include text_headline(#ff6060); | |||
border-color: $btn-cancel-border-color; | |||
background-color: $btn-cancel-background-color; | |||
@include text_headline($btn-cancel-font-color); | |||
} | |||
&.authorize | |||
@@ -45,9 +45,9 @@ | |||
display: inline; | |||
color: $_color-post; | |||
border-color: $_color-post; | |||
color: $btn-authorize-font-color; | |||
border-color: $btn-authorize-border-color; | |||
background-color: $btn-authorize-background-color; | |||
span | |||
{ | |||
@@ -58,16 +58,17 @@ | |||
svg | |||
{ | |||
fill: $_color-post; | |||
fill: $btn-authorize-svg-fill-color; | |||
} | |||
} | |||
&.execute | |||
{ | |||
animation: swagger-ui-pulse 2s infinite; | |||
color: #fff; | |||
border-color: #4990e2; | |||
will-change: transform; | |||
background-color: $btn-execute-background-color; | |||
color: $btn-execute-font-color; | |||
border-color: $btn-execute-border-color; | |||
} | |||
} | |||
@@ -76,21 +77,19 @@ | |||
{ | |||
0% | |||
{ | |||
color: #fff; | |||
background: #4990e2; | |||
box-shadow: 0 0 0 0 rgba(#4990e2, .8); | |||
color: $btn-execute-font-color; | |||
background: $btn-execute-background-color-alt; | |||
box-shadow: 0 0 0 0 rgba($btn-execute-background-color-alt, .8); | |||
} | |||
70% | |||
{ | |||
//color: #4990e2; | |||
//background: transparent; | |||
box-shadow: 0 0 0 5px rgba(#4990e2, 0); | |||
box-shadow: 0 0 0 5px rgba($btn-execute-background-color-alt, 0); | |||
} | |||
100% | |||
{ | |||
color: #fff; | |||
background: #4990e2; | |||
box-shadow: 0 0 0 0 rgba(#4990e2, 0); | |||
color: $btn-execute-font-color; | |||
background: $btn-execute-background-color-alt; | |||
box-shadow: 0 0 0 0 rgba($btn-execute-background-color-alt, 0); | |||
} | |||
} | |||
@@ -155,7 +154,7 @@ | |||
{ | |||
svg | |||
{ | |||
fill: #444; | |||
fill: $expand-methods-svg-fill-color-hover; | |||
} | |||
} | |||
@@ -163,7 +162,7 @@ | |||
{ | |||
transition: all .3s; | |||
fill: #777; | |||
fill: $expand-methods-svg-fill-color; | |||
} | |||
} | |||
@@ -27,7 +27,7 @@ | |||
small | |||
{ | |||
color: #666; | |||
color: $errors-wrapper-errors-small-font-color; | |||
} | |||
} | |||
@@ -5,11 +5,11 @@ select | |||
padding: 5px 40px 5px 10px; | |||
border: 2px solid #41444e; | |||
border: 2px solid $form-select-border-color; | |||
border-radius: 4px; | |||
background: #f7f7f7 url(data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHZpZXdCb3g9IjAgMCAyMCAyMCI+ICAgIDxwYXRoIGQ9Ik0xMy40MTggNy44NTljLjI3MS0uMjY4LjcwOS0uMjY4Ljk3OCAwIC4yNy4yNjguMjcyLjcwMSAwIC45NjlsLTMuOTA4IDMuODNjLS4yNy4yNjgtLjcwNy4yNjgtLjk3OSAwbC0zLjkwOC0zLjgzYy0uMjctLjI2Ny0uMjctLjcwMSAwLS45NjkuMjcxLS4yNjguNzA5LS4yNjguOTc4IDBMMTAgMTFsMy40MTgtMy4xNDF6Ii8+PC9zdmc+) right 10px center no-repeat; | |||
background: $form-select-background-color url(data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHZpZXdCb3g9IjAgMCAyMCAyMCI+ICAgIDxwYXRoIGQ9Ik0xMy40MTggNy44NTljLjI3MS0uMjY4LjcwOS0uMjY4Ljk3OCAwIC4yNy4yNjguMjcyLjcwMSAwIC45NjlsLTMuOTA4IDMuODNjLS4yNy4yNjgtLjcwNy4yNjgtLjk3OSAwbC0zLjkwOC0zLjgzYy0uMjctLjI2Ny0uMjctLjcwMSAwLS45NjkuMjcxLS4yNjguNzA5LS4yNjguOTc4IDBMMTAgMTFsMy40MTgtMy4xNDF6Ii8+PC9zdmc+) right 10px center no-repeat; | |||
background-size: 20px; | |||
box-shadow: 0 1px 2px 0 rgba(0,0,0,.25); | |||
box-shadow: 0 1px 2px 0 rgba($form-select-box-shadow-color, .25); | |||
@include text_headline(); | |||
appearance: none; | |||
@@ -19,7 +19,7 @@ select | |||
margin: 5px 0; | |||
padding: 5px; | |||
background: #f7f7f7; | |||
background: $form-select-background-color; | |||
} | |||
&.invalid { | |||
@@ -57,9 +57,9 @@ input[type=file] | |||
margin: 5px 0; | |||
padding: 8px 10px; | |||
border: 1px solid #d9d9d9; | |||
border: 1px solid $form-input-border-color; | |||
border-radius: 4px; | |||
background: #fff; | |||
background: $form-input-background-color; | |||
@media (max-width: 768px) { | |||
max-width: 175px; | |||
} | |||
@@ -110,13 +110,13 @@ textarea | |||
border: none; | |||
border-radius: 4px; | |||
outline: none; | |||
background: rgba(#fff,.8); | |||
background: rgba($form-textarea-background-color,.8); | |||
@include text_code(); | |||
&:focus | |||
{ | |||
border: 2px solid $_color-get; | |||
border: 2px solid $form-textarea-focus-border-color; | |||
} | |||
&.curl | |||
@@ -130,9 +130,9 @@ textarea | |||
resize: none; | |||
border-radius: 4px; | |||
background: #41444e; | |||
background: $form-textarea-curl-background-color; | |||
@include text_code(#fff); | |||
@include text_code($form-textarea-curl-font-color); | |||
} | |||
} | |||
@@ -143,7 +143,7 @@ textarea | |||
transition: opacity .5s; | |||
color: #333; | |||
color: $form-checkbox-label-font-color; | |||
label | |||
{ | |||
@@ -179,8 +179,8 @@ textarea | |||
cursor: pointer; | |||
border-radius: 1px; | |||
background: #e8e8e8; | |||
box-shadow: 0 0 0 2px #e8e8e8; | |||
background: $form-checkbox-background-color; | |||
box-shadow: 0 0 0 2px $form-checkbox-box-shadow-color; | |||
flex: none; | |||
@@ -192,7 +192,7 @@ textarea | |||
&:checked + label > .item | |||
{ | |||
background: #e8e8e8 url(data:image/svg+xml,%0A%3Csvg%20width%3D%2210px%22%20height%3D%228px%22%20viewBox%3D%223%207%2010%208%22%20version%3D%221.1%22%20xmlns%3D%22http%3A//www.w3.org/2000/svg%22%20xmlns%3Axlink%3D%22http%3A//www.w3.org/1999/xlink%22%3E%0A%20%20%20%20%3C%21--%20Generator%3A%20Sketch%2042%20%2836781%29%20-%20http%3A//www.bohemiancoding.com/sketch%20--%3E%0A%20%20%20%20%3Cdesc%3ECreated%20with%20Sketch.%3C/desc%3E%0A%20%20%20%20%3Cdefs%3E%3C/defs%3E%0A%20%20%20%20%3Cpolygon%20id%3D%22Rectangle-34%22%20stroke%3D%22none%22%20fill%3D%22%2341474E%22%20fill-rule%3D%22evenodd%22%20points%3D%226.33333333%2015%203%2011.6666667%204.33333333%2010.3333333%206.33333333%2012.3333333%2011.6666667%207%2013%208.33333333%22%3E%3C/polygon%3E%0A%3C/svg%3E) center center no-repeat; | |||
background: $form-checkbox-background-color url(data:image/svg+xml,%0A%3Csvg%20width%3D%2210px%22%20height%3D%228px%22%20viewBox%3D%223%207%2010%208%22%20version%3D%221.1%22%20xmlns%3D%22http%3A//www.w3.org/2000/svg%22%20xmlns%3Axlink%3D%22http%3A//www.w3.org/1999/xlink%22%3E%0A%20%20%20%20%3C%21--%20Generator%3A%20Sketch%2042%20%2836781%29%20-%20http%3A//www.bohemiancoding.com/sketch%20--%3E%0A%20%20%20%20%3Cdesc%3ECreated%20with%20Sketch.%3C/desc%3E%0A%20%20%20%20%3Cdefs%3E%3C/defs%3E%0A%20%20%20%20%3Cpolygon%20id%3D%22Rectangle-34%22%20stroke%3D%22none%22%20fill%3D%22%2341474E%22%20fill-rule%3D%22evenodd%22%20points%3D%226.33333333%2015%203%2011.6666667%204.33333333%2010.3333333%206.33333333%2012.3333333%2011.6666667%207%2013%208.33333333%22%3E%3C/polygon%3E%0A%3C/svg%3E) center center no-repeat; | |||
} | |||
} | |||
} |
@@ -30,9 +30,9 @@ | |||
padding: 3px 5px; | |||
border-radius: 4px; | |||
background: rgba(#000,.05); | |||
background: rgba($info-code-background-color,.05); | |||
@include text_code(#9012fe); | |||
@include text_code($info-code-font-color); | |||
} | |||
a | |||
@@ -41,11 +41,11 @@ | |||
transition: all .4s; | |||
@include text_body(#4990e2); | |||
@include text_body($info-link-font-color); | |||
&:hover | |||
{ | |||
color: darken(#4990e2, 15%); | |||
color: darken($info-link-font-color-hover, 15%); | |||
} | |||
} | |||
> div | |||
@@ -86,13 +86,13 @@ | |||
vertical-align: super; | |||
border-radius: 57px; | |||
background: #7d8492; | |||
background: $info-title-small-background-color; | |||
pre | |||
{ | |||
margin: 0; | |||
@include text_headline(#fff); | |||
@include text_headline($info-title-small-pre-font-color); | |||
} | |||
} | |||
} | |||
@@ -34,11 +34,11 @@ | |||
cursor: pointer; | |||
transition: all .2s; | |||
border-bottom: 1px solid rgba(#3b4151, .3); | |||
border-bottom: 1px solid rgba($opblock-tag-border-bottom-color, .3); | |||
&:hover | |||
{ | |||
background: rgba(#000,.02); | |||
background: rgba($opblock-tag-background-color-hover,.02); | |||
} | |||
} | |||
@@ -127,9 +127,9 @@ | |||
{ | |||
margin: 0 0 15px 0; | |||
border: 1px solid #000; | |||
border: 1px solid $opblock-border-color; | |||
border-radius: 4px; | |||
box-shadow: 0 0 3px rgba(#000,.19); | |||
box-shadow: 0 0 3px rgba($opblock-box-shadow-color,.19); | |||
.tab-header | |||
{ | |||
@@ -168,7 +168,7 @@ | |||
content: ''; | |||
transform: translateX(-50%); | |||
background: #888; | |||
background: $opblock-tab-header-tab-item-active-h4-span-after-background-color; | |||
} | |||
} | |||
} | |||
@@ -181,7 +181,7 @@ | |||
{ | |||
.opblock-summary | |||
{ | |||
border-bottom: 1px solid #000; | |||
border-bottom: 1px solid $opblock-isopen-summary-border-bottom-color; | |||
} | |||
} | |||
@@ -194,8 +194,8 @@ | |||
min-height: 50px; | |||
background: rgba(#fff,.8); | |||
box-shadow: 0 1px 2px rgba(#000,.1); | |||
background: rgba($opblock-isopen-section-header-background-color,.8); | |||
box-shadow: 0 1px 2px rgba($opblock-isopen-section-header-box-shadow-color,.1); | |||
label | |||
{ | |||
@@ -239,10 +239,10 @@ | |||
text-align: center; | |||
border-radius: 3px; | |||
background: #000; | |||
text-shadow: 0 1px 0 rgba(#000,.1); | |||
background: $opblock-summary-method-background-color; | |||
text-shadow: 0 1px 0 rgba($opblock-summary-method-text-shadow-color,.1); | |||
@include text_headline(#fff); | |||
@include text_headline($opblock-summary-method-font-color); | |||
} | |||
.opblock-summary-path, | |||
@@ -377,7 +377,7 @@ | |||
margin: 20px 0; | |||
padding: 10px 10px; | |||
border: 2px solid #d8dde7; | |||
border: 2px solid $operational-filter-input-border-color; | |||
} | |||
} | |||
@@ -420,7 +420,7 @@ | |||
content: ''; | |||
background: rgba(#000,.2); | |||
background: rgba($tab-list-item-first-background-color,.2); | |||
} | |||
} | |||
@@ -525,7 +525,7 @@ | |||
{ | |||
font-size: 11px; | |||
@include text_code(#999); | |||
@include text_code($response-col-status-undocumented-font-color); | |||
} | |||
} | |||
@@ -541,7 +541,7 @@ | |||
{ | |||
font-size: 11px; | |||
@include text_code(#999); | |||
@include text_code($response-col-links-font-color); | |||
} | |||
} | |||
@@ -558,9 +558,9 @@ | |||
padding: 10px; | |||
border-radius: 4px; | |||
background: #41444e; | |||
background: $response-col-description-inner-markdown-background-color; | |||
@include text_code(#fff); | |||
@include text_code($response-col-description-inner-markdown-font-color); | |||
p | |||
{ | |||
@@ -569,10 +569,10 @@ | |||
a | |||
{ | |||
@include text_code(#89bf04); | |||
@include text_code($response-col-description-inner-markdown-link-font-color); | |||
text-decoration: underline; | |||
&:hover { | |||
color: #81b10c; | |||
color: $response-col-description-inner-markdown-link-font-color-hover; | |||
} | |||
} | |||
} | |||
@@ -593,13 +593,13 @@ | |||
hyphens: auto; | |||
border-radius: 4px; | |||
background: #41444e; | |||
background: $opblock-body-background-color; | |||
overflow-wrap: break-word; | |||
@include text_code(#fff); | |||
@include text_code($opblock-body-font-color); | |||
span | |||
{ | |||
color: #fff !important; | |||
color: $opblock-body-font-color !important; | |||
} | |||
.headerline | |||
@@ -613,8 +613,8 @@ | |||
margin: 0 0 20px 0; | |||
padding: 30px 0; | |||
background: #fff; | |||
box-shadow: 0 1px 2px 0 rgba(0,0,0,.15); | |||
background: $scheme-container-background-color; | |||
box-shadow: 0 1px 2px 0 rgba($scheme-container-box-shadow-color,.15); | |||
.schemes | |||
{ | |||
@@ -648,14 +648,14 @@ | |||
margin: 0 0 20px 0; | |||
padding: 30px 0; | |||
background: #fff; | |||
box-shadow: 0 1px 2px 0 rgba(0,0,0,.15); | |||
background: $server-container-background-color; | |||
box-shadow: 0 1px 2px 0 rgba($server-container-box-shadow-color,.15); | |||
.computed-url { | |||
margin: 2em 0; | |||
code { | |||
color: grey; | |||
color: $server-container-computed-url-code-font-color; | |||
display: inline-block; | |||
padding: 4px; | |||
font-size: 16px; | |||
@@ -755,8 +755,8 @@ | |||
animation: rotation 1s infinite linear, opacity .5s; | |||
opacity: 1; | |||
border: 2px solid rgba(#555, .1); | |||
border-top-color: rgba(#000, .6); | |||
border: 2px solid rgba($loading-container-before-border-color, .1); | |||
border-top-color: rgba($loading-container-before-border-top-color, .6); | |||
border-radius: 100%; | |||
backface-visibility: hidden; | |||
@@ -777,11 +777,11 @@ | |||
&.controls-accept-header { | |||
select { | |||
border-color: green; | |||
border-color: $response-content-type-controls-accept-header-select-border-color; | |||
} | |||
small { | |||
color: green; | |||
color: $response-content-type-controls-accept-header-small-font-color; | |||
font-size: .7em; | |||
} | |||
} | |||
@@ -15,7 +15,7 @@ | |||
bottom: 0; | |||
left: 0; | |||
background: rgba(#000,.8); | |||
background: rgba($dialog-ux-backdrop-background-color,.8); | |||
} | |||
.modal-ux | |||
@@ -31,10 +31,10 @@ | |||
transform: translate(-50%,-50%); | |||
border: 1px solid #ebebeb; | |||
border: 1px solid $dialog-ux-modal-border-color; | |||
border-radius: 4px; | |||
background: #fff; | |||
box-shadow: 0 10px 30px 0 rgba(0,0,0,.20); | |||
background: $dialog-ux-modal-background-color; | |||
box-shadow: 0 10px 30px 0 rgba($dialog-ux-modal-box-shadow-color,.20); | |||
} | |||
.modal-ux-content | |||
@@ -50,7 +50,7 @@ | |||
margin: 0 0 5px 0; | |||
color: #41444e; | |||
color: $dialog-ux-modal-content-font-color; | |||
@include text_body(); | |||
} | |||
@@ -72,7 +72,7 @@ | |||
padding: 12px 0; | |||
border-bottom: 1px solid #ebebeb; | |||
border-bottom: 1px solid $dialog-ux-modal-header-border-bottom-color; | |||
align-items: center; | |||
@@ -3,14 +3,16 @@ | |||
font-size: 12px; | |||
font-weight: 300; | |||
@include text_code(); | |||
.deprecated | |||
{ | |||
span, td { | |||
color: #aaa !important; | |||
} | |||
span, | |||
td | |||
{ | |||
color: $model-deprecated-font-color !important; | |||
} | |||
} | |||
@include text_code(); | |||
&-toggle | |||
{ | |||
font-size: 10px; | |||
@@ -82,12 +84,13 @@ | |||
white-space: nowrap; | |||
color: #ebebeb; | |||
color: $model-hint-font-color; | |||
border-radius: 4px; | |||
background: rgba(#000,.7); | |||
background: rgba($model-hint-background-color,.7); | |||
} | |||
p { | |||
p | |||
{ | |||
margin: 0 0 1em 0; | |||
} | |||
} | |||
@@ -97,7 +100,7 @@ section.models | |||
{ | |||
margin: 30px 0; | |||
border: 1px solid rgba(#3b4151, .3); | |||
border: 1px solid rgba($section-models-border-color, .3); | |||
border-radius: 4px; | |||
&.is-open | |||
@@ -106,7 +109,8 @@ section.models | |||
h4 | |||
{ | |||
margin: 0 0 5px 0; | |||
border-bottom: 1px solid rgba(#3b4151, .3); | |||
border-bottom: 1px solid rgba($section-models-isopen-h4-border-bottom-color, .3); | |||
} | |||
} | |||
h4 | |||
@@ -114,6 +118,7 @@ section.models | |||
font-size: 16px; | |||
display: flex; | |||
align-items: center; | |||
margin: 0; | |||
padding: 10px 20px 10px 10px; | |||
@@ -121,8 +126,7 @@ section.models | |||
cursor: pointer; | |||
transition: all .2s; | |||
@include text_headline(#777); | |||
align-items: center; | |||
@include text_headline($section-models-h4-font-color); | |||
svg | |||
{ | |||
@@ -136,7 +140,7 @@ section.models | |||
&:hover | |||
{ | |||
background: rgba(#000,.02); | |||
background: rgba($section-models-h4-background-color-hover,.02); | |||
} | |||
} | |||
@@ -146,7 +150,7 @@ section.models | |||
margin: 0 0 10px 0; | |||
@include text_headline(#777); | |||
@include text_headline($section-models-h5-font-color); | |||
} | |||
.model-jump-to-path | |||
@@ -162,11 +166,11 @@ section.models | |||
transition: all .5s; | |||
border-radius: 4px; | |||
background: rgba(#000,.05); | |||
background: rgba($section-models-model-container-background-color,.05); | |||
&:hover | |||
{ | |||
background: rgba(#000,.07); | |||
background: rgba($section-models-model-container-background-color,.07); | |||
} | |||
&:first-of-type | |||
@@ -192,7 +196,7 @@ section.models | |||
padding: 10px; | |||
border-radius: 4px; | |||
background: rgba(#000,.1); | |||
background: rgba($section-models-model-box-background-color,.1); | |||
.model-jump-to-path | |||
{ | |||
@@ -202,7 +206,7 @@ section.models | |||
&.deprecated | |||
{ | |||
opacity: .5; | |||
opacity: .5; | |||
} | |||
} | |||
@@ -211,21 +215,23 @@ section.models | |||
{ | |||
font-size: 16px; | |||
@include text_headline(#555); | |||
@include text_headline($section-models-model-title-font-color); | |||
} | |||
.model-deprecated-warning | |||
{ | |||
font-size: 16px; | |||
font-weight: 600; | |||
margin-right: 1em; | |||
@include text_headline($_color-delete); | |||
} | |||
span | |||
{ | |||
> span.model | |||
> span.model | |||
{ | |||
.brace-close | |||
{ | |||
@@ -237,13 +243,13 @@ span | |||
.prop-name | |||
{ | |||
display: inline-block; | |||
margin-right: 1em; | |||
width: 8em; | |||
} | |||
.prop-type | |||
{ | |||
color: #55a; | |||
color: $prop-type-font-color; | |||
} | |||
.prop-enum | |||
@@ -252,5 +258,5 @@ span | |||
} | |||
.prop-format | |||
{ | |||
color: #999; | |||
color: $prop-format-font-color; | |||
} |
@@ -74,7 +74,7 @@ table | |||
text-align: left; | |||
border-bottom: 1px solid rgba(#3b4151, .2); | |||
border-bottom: 1px solid rgba($table-thead-td-border-bottom-color, .2); | |||
@include text_body(); | |||
} | |||
@@ -126,7 +126,7 @@ table | |||
content: 'required'; | |||
color: rgba(#f00, .6); | |||
color: rgba($table-parameter-name-required-font-color, .6); | |||
} | |||
} | |||
} | |||
@@ -136,7 +136,7 @@ table | |||
font-size: 12px; | |||
font-style: italic; | |||
@include text_code(#888); | |||
@include text_code($table-parameter-in-font-color); | |||
} | |||
.parameter__deprecated | |||
@@ -144,7 +144,7 @@ table | |||
font-size: 12px; | |||
font-style: italic; | |||
@include text_code(#f00); | |||
@include text_code($table-parameter-deprecated-font-color); | |||
} | |||
@@ -2,7 +2,7 @@ | |||
{ | |||
padding: 8px 0; | |||
background-color: #89bf04; | |||
background-color: $topbar-background-color; | |||
.topbar-wrapper | |||
{ | |||
display: flex; | |||
@@ -21,7 +21,7 @@ | |||
text-decoration: none; | |||
@include text_headline(#fff); | |||
@include text_headline($topbar-link-font-color); | |||
span | |||
{ | |||
@@ -41,7 +41,7 @@ | |||
width: 100%; | |||
margin: 0; | |||
border: 2px solid #547f00; | |||
border: 2px solid $topbar-download-url-wrapper-element-border-color; | |||
border-radius: 4px 0 0 4px; | |||
outline: none; | |||
} | |||
@@ -71,7 +71,7 @@ | |||
width: 100%; | |||
border: 2px solid #547f00; | |||
border: 2px solid $topbar-download-url-wrapper-element-border-color; | |||
outline: none; | |||
box-shadow: none; | |||
} | |||
@@ -87,9 +87,9 @@ | |||
border: none; | |||
border-radius: 0 4px 4px 0; | |||
background: #547f00; | |||
background: $topbar-download-url-button-background-color; | |||
@include text_headline(#fff); | |||
@include text_headline($topbar-download-url-button-font-color); | |||
} | |||
} | |||
} |
@@ -1,11 +1,11 @@ | |||
@mixin text_body($color: #3b4151) | |||
@mixin text_body($color: $text-body-default-font-color) | |||
{ | |||
font-family: 'Open Sans', sans-serif; | |||
color: $color; | |||
} | |||
@mixin text_code($color: #3b4151) | |||
@mixin text_code($color: $text-code-default-font-color) | |||
{ | |||
font-family: 'Source Code Pro', monospace; | |||
font-weight: 600; | |||
@@ -13,7 +13,7 @@ | |||
color: $color; | |||
} | |||
@mixin text_headline($color: #3b4151) | |||
@mixin text_headline($color: $text-headline-default-font-color) | |||
{ | |||
font-family: 'Titillium Web', sans-serif; | |||
@@ -0,0 +1,218 @@ | |||
$gray-base: #000 !default; | |||
$white: #fff !default; | |||
$gray-50: #ebebeb !default; | |||
$gray-100: #d8dde7 !default; | |||
$gray-200: lighten($gray-base, 62.75%) !default; // #aaa | |||
$gray-300: lighten($gray-base, 56.5%) !default; // #999 | |||
$gray-400: lighten($gray-base, 50%) !default; // #888 | |||
$gray-500: lighten($gray-base, 43.75%) !default; // #777 | |||
$gray-600: lighten($gray-base, 37.5%) !default; // #666 | |||
$gray-650: lighten($gray-base, 33.3%) !default; // ##555555 | |||
$gray-700: lighten($gray-base, 31.25%) !default; // #555 | |||
$gray-800: lighten($gray-base, 25%) !default; // #444 | |||
$gray-900: lighten($gray-base, 18.75%) !default; // #333 | |||
$gray-custom-1: #41444e !default; | |||
$gray-custom-2: #3b4151 !default; | |||
$color-primary: #89bf04 !default; | |||
$color-secondary: #9012fe !default; | |||
$color-info: #4990e2 !default; | |||
$color-warning: #ff6060 !default; | |||
$color-danger: #f00 !default; | |||
$_color-post: #49cc90 !default; | |||
$_color-get: #61affe !default; | |||
$_color-put: #fca130 !default; | |||
$_color-delete: #f93e3e !default; | |||
$_color-head: #9012fe !default; | |||
$_color-patch: #50e3c2 !default; | |||
$_color-disabled: #ebebeb !default; | |||
$_color-options: #0d5aa7 !default; | |||
$color-green: #008000 !default; | |||
$color-primary-hover: #81b10c !default; | |||
// Authorize | |||
$auth-container-border-color: $gray-50 !default; | |||
// Buttons | |||
$btn-background-color: transparent !default; | |||
$btn-border-color: $gray-400 !default; | |||
$btn-font-color: inherit !default; | |||
$btn-box-shadow-color: $gray-base !default; | |||
$btn-authorize-background-color: transparent !default; | |||
$btn-authorize-border-color: $_color-post !default; | |||
$btn-authorize-font-color: $_color-post !default; | |||
$btn-authorize-svg-fill-color: $_color-post !default; | |||
$btn-cancel-background-color: transparent !default; | |||
$btn-cancel-border-color: $color-warning !default; | |||
$btn-cancel-font-color: $color-warning !default; | |||
$btn-execute-background-color: transparent !default; | |||
$btn-execute-border-color: $color-info !default; | |||
$btn-execute-font-color: $white !default; | |||
$btn-execute-background-color-alt: $color-info !default; | |||
$expand-methods-svg-fill-color: $gray-500 !default; | |||
$expand-methods-svg-fill-color-hover: $gray-800 !default; | |||
// Errors | |||
$errors-wrapper-background-color: $_color-delete !default; | |||
$errors-wrapper-border-color: $_color-delete !default; | |||
$errors-wrapper-errors-small-font-color: $gray-600 !default; | |||
// Form | |||
$form-select-background-color: #f7f7f7 !default; | |||
$form-select-border-color: $gray-custom-1 !default; | |||
$form-select-box-shadow-color: $gray-base !default; | |||
$form-input-border-color: #d9d9d9 !default; | |||
$form-input-background-color: $white !default; | |||
$form-textarea-background-color: $white !default; | |||
$form-textarea-focus-border-color: $_color-get !default; | |||
$form-textarea-curl-background-color: $gray-custom-1 !default; | |||
$form-textarea-curl-font-color: $white !default; | |||
$form-checkbox-label-font-color: $gray-900 !default; | |||
$form-checkbox-background-color: #e8e8e8 !default; | |||
$form-checkbox-box-shadow-color: #e8e8e8 !default; | |||
// Information | |||
$info-code-background-color: $gray-base !default; | |||
$info-code-font-color: $_color-head !default; | |||
$info-link-font-color: $color-info !default; | |||
$info-link-font-color-hover: $info-link-font-color !default; | |||
$info-title-small-background-color: #7d8492 !default; | |||
$info-title-small-pre-font-color: $white !default; | |||
// Layout | |||
$opblock-border-color: $gray-base !default; | |||
$opblock-box-shadow-color: $gray-base !default; | |||
$opblock-tag-border-bottom-color: $gray-custom-2 !default; | |||
$opblock-tag-background-color-hover: $gray-base !default; | |||
$opblock-tab-header-tab-item-active-h4-span-after-background-color: $gray-400 !default; | |||
$opblock-isopen-summary-border-bottom-color: $gray-base !default; | |||
$opblock-isopen-section-header-background-color: $white !default; | |||
$opblock-isopen-section-header-box-shadow-color: $gray-base !default; | |||
$opblock-summary-method-background-color: $gray-base !default; | |||
$opblock-summary-method-font-color: $white !default; | |||
$opblock-summary-method-text-shadow-color: $gray-base !default; | |||
$operational-filter-input-border-color: #d8dde7 !default; | |||
$tab-list-item-first-background-color: $gray-base !default; | |||
$response-col-status-undocumented-font-color: $gray-300 !default; | |||
$response-col-links-font-color: $gray-300 !default; | |||
$response-col-description-inner-markdown-font-color: $white !default; | |||
$response-col-description-inner-markdown-background-color: $gray-custom-1 !default; | |||
$response-col-description-inner-markdown-link-font-color: $color-primary !default; | |||
$response-col-description-inner-markdown-link-font-color-hover: $color-primary-hover !default; | |||
$opblock-body-background-color: $gray-custom-1 !default; | |||
$opblock-body-font-color: $white !default; | |||
$scheme-container-background-color: $white !default; | |||
$scheme-container-box-shadow-color: $gray-base !default; | |||
$server-container-background-color: $white !default; | |||
$server-container-box-shadow-color: $gray-base !default; | |||
$server-container-computed-url-code-font-color: $gray-400 !default; | |||
$loading-container-before-border-color: $gray-650 !default; | |||
$loading-container-before-border-top-color: $gray-base !default; | |||
$response-content-type-controls-accept-header-select-border-color: $color-green !default; | |||
$response-content-type-controls-accept-header-small-font-color: $color-green !default; | |||
// Modal | |||
$dialog-ux-backdrop-background-color: $gray-base !default; | |||
$dialog-ux-modal-background-color: $white !default; | |||
$dialog-ux-modal-border-color: $gray-50 !default; | |||
$dialog-ux-modal-box-shadow-color: $gray-base !default; | |||
$dialog-ux-modal-content-font-color: $gray-custom-1 !default; | |||
$dialog-ux-modal-header-border-bottom-color: $gray-50 !default; | |||
// Models | |||
$model-deprecated-font-color: $gray-200 !default; | |||
$model-hint-font-color: $gray-50 !default; | |||
$model-hint-background-color: $gray-base !default; | |||
$section-models-border-color: $gray-custom-2 !default; | |||
$section-models-isopen-h4-border-bottom-color: $section-models-border-color !default; | |||
$section-models-h4-font-color: $gray-500 !default; | |||
$section-models-h4-background-color-hover: $gray-base !default; | |||
$section-models-h5-font-color: $gray-500 !default; | |||
$section-models-model-container-background-color: $gray-base !default; | |||
$section-models-model-box-background-color: $gray-base !default; | |||
$section-models-model-title-font-color: $gray-700 !default; | |||
$prop-type-font-color: #55a !default; | |||
$prop-format-font-color: $gray-300 !default; | |||
// Tables | |||
$table-thead-td-border-bottom-color: $gray-custom-2 !default; | |||
$table-parameter-name-required-font-color: $color-danger !default; | |||
$table-parameter-in-font-color: $gray-400 !default; | |||
$table-parameter-deprecated-font-color: $color-danger !default; | |||
// Topbar | |||
$topbar-background-color: $color-primary !default; | |||
$topbar-link-font-color: $white !default; | |||
$topbar-download-url-wrapper-element-border-color: #547f00 !default; | |||
$topbar-download-url-button-background-color: #547f00 !default; | |||
$topbar-download-url-button-font-color: $white !default; | |||
// Type | |||
$text-body-default-font-color: $gray-custom-2 !default; | |||
$text-code-default-font-color: $gray-custom-2 !default; | |||
$text-headline-default-font-color: $gray-custom-2 !default; |
@@ -0,0 +1,63 @@ | |||
import React from "react" | |||
import expect from "expect" | |||
import { shallow } from "enzyme" | |||
import { fromJS } from "immutable" | |||
import ObjectModel from "components/object-model" | |||
import ModelExample from "components/model-example" | |||
import Immutable from "immutable" | |||
import Model from "components/model" | |||
import ModelCollapse from "components/model-collapse" | |||
import { inferSchema } from "corePlugins/samples/fn" | |||
describe("<ObjectModel />", function() { | |||
const dummyComponent = () => null | |||
const components = { | |||
"JumpToPath" : dummyComponent, | |||
"Markdown" : dummyComponent, | |||
"Model" : Model, | |||
"ModelCollapse" : ModelCollapse | |||
} | |||
const props = { | |||
getComponent: c => components[c], | |||
isRef : false, | |||
schema: Immutable.fromJS( | |||
{ | |||
"properties": { | |||
// Note reverse order: c, b, a | |||
c: { | |||
type: "integer", | |||
name: "c" | |||
}, | |||
b: { | |||
type: "boolean", | |||
name: "b" | |||
}, | |||
a: { | |||
type: "string", | |||
name: "a" | |||
} | |||
} | |||
} | |||
), | |||
specSelectors: { | |||
isOAS3(){ | |||
return false | |||
} | |||
}, | |||
className: "for-test" | |||
} | |||
it("renders a collapsible header", function(){ | |||
const wrapper = shallow(<ObjectModel {...props}/>) | |||
const renderedModelCollapse = wrapper.find(ModelCollapse) | |||
expect(renderedModelCollapse.length).toEqual(1) | |||
}) | |||
it("renders the object properties in order", function() { | |||
const wrapper = shallow(<ObjectModel {...props}/>) | |||
const renderedModel = wrapper.find(Model) | |||
expect(renderedModel.length).toEqual(3) | |||
expect(renderedModel.get(0).props.schema.get("name")).toEqual("c") | |||
expect(renderedModel.get(1).props.schema.get("name")).toEqual("b") | |||
expect(renderedModel.get(2).props.schema.get("name")).toEqual("a") | |||
}) | |||
}) |
@@ -0,0 +1,133 @@ | |||
/* eslint-env mocha */ | |||
import expect from "expect" | |||
import { fromJS } from "immutable" | |||
import { definitionsToAuthorize, definitionsForRequirements } from "corePlugins/auth/selectors" | |||
describe("auth plugin - selectors", () => { | |||
describe("definitionsToAuthorize", () => { | |||
it("should return securityDefinitions as a List", () => { | |||
const securityDefinitions = { | |||
"petstore_auth": { | |||
"type": "oauth2", | |||
"authorizationUrl": "http://petstore.swagger.io/oauth/dialog", | |||
"flow": "implicit", | |||
"scopes": { | |||
"write:pets": "modify pets in your account", | |||
"read:pets": "read your pets" | |||
} | |||
}, | |||
"api_key": { | |||
"type": "apiKey", | |||
"name": "api_key", | |||
"in": "header" | |||
} | |||
} | |||
const system = { | |||
specSelectors: { | |||
securityDefinitions() { | |||
return fromJS(securityDefinitions) | |||
} | |||
} | |||
} | |||
const res = definitionsToAuthorize({})(system) | |||
expect(res.toJS()).toEqual([ | |||
{ | |||
"petstore_auth": securityDefinitions["petstore_auth"] | |||
}, | |||
{ | |||
"api_key": securityDefinitions["api_key"] | |||
}, | |||
]) | |||
}) | |||
it("should fail gracefully with bad data", () => { | |||
const securityDefinitions = null | |||
const system = { | |||
specSelectors: { | |||
securityDefinitions() { | |||
return fromJS(securityDefinitions) | |||
} | |||
} | |||
} | |||
const res = definitionsToAuthorize({})(system) | |||
expect(res.toJS()).toEqual([]) | |||
}) | |||
}) | |||
describe("definitionsForRequirements", () => { | |||
it("should return applicable securityDefinitions as a List", () => { | |||
const securityDefinitions = { | |||
"petstore_auth": { | |||
"type": "oauth2", | |||
"authorizationUrl": "http://petstore.swagger.io/oauth/dialog", | |||
"flow": "implicit", | |||
"scopes": { | |||
"write:pets": "modify pets in your account", | |||
"read:pets": "read your pets" | |||
} | |||
}, | |||
"api_key": { | |||
"type": "apiKey", | |||
"name": "api_key", | |||
"in": "header" | |||
} | |||
} | |||
const system = { | |||
authSelectors: { | |||
definitionsToAuthorize() { | |||
return fromJS([ | |||
{ | |||
"petstore_auth": securityDefinitions["petstore_auth"] | |||
}, | |||
{ | |||
"api_key": securityDefinitions["api_key"] | |||
}, | |||
]) | |||
} | |||
} | |||
} | |||
const securities = fromJS([ | |||
{ | |||
"petstore_auth": [ | |||
"write:pets", | |||
"read:pets" | |||
] | |||
} | |||
]) | |||
const res = definitionsForRequirements({}, securities)(system) | |||
expect(res.toJS()).toEqual([ | |||
{ | |||
"petstore_auth": securityDefinitions["petstore_auth"] | |||
} | |||
]) | |||
}) | |||
it("should fail gracefully with bad data", () => { | |||
const securityDefinitions = null | |||
const system = { | |||
authSelectors: { | |||
definitionsToAuthorize() { | |||
return null | |||
} | |||
} | |||
} | |||
const securities = null | |||
const res = definitionsForRequirements({}, securities)(system) | |||
expect(res.toJS()).toEqual([]) | |||
}) | |||
}) | |||
}) |
@@ -3,6 +3,7 @@ import expect from "expect" | |||
import { fromJS, OrderedMap } from "immutable" | |||
import { | |||
mapToList, | |||
validatePattern, | |||
validateMinLength, | |||
validateMaxLength, | |||
validateDateTime, | |||
@@ -16,7 +17,8 @@ import { | |||
fromJSOrdered, | |||
getAcceptControllingResponse, | |||
createDeepLinkPath, | |||
escapeDeepLinkPath | |||
escapeDeepLinkPath, | |||
sanitizeUrl | |||
} from "core/utils" | |||
import win from "core/window" | |||
@@ -215,9 +217,9 @@ describe("utils", function() { | |||
expect(validateFile(1)).toEqual(errorMessage) | |||
expect(validateFile("string")).toEqual(errorMessage) | |||
}) | |||
}) | |||
}) | |||
describe("validateDateTime", function() { | |||
describe("validateDateTime", function() { | |||
let errorMessage = "Value must be a DateTime" | |||
it("doesn't return for valid dates", function() { | |||
@@ -228,7 +230,7 @@ describe("utils", function() { | |||
expect(validateDateTime(null)).toEqual(errorMessage) | |||
expect(validateDateTime("string")).toEqual(errorMessage) | |||
}) | |||
}) | |||
}) | |||
describe("validateGuid", function() { | |||
let errorMessage = "Value must be a Guid" | |||
@@ -242,9 +244,9 @@ describe("utils", function() { | |||
expect(validateGuid(1)).toEqual(errorMessage) | |||
expect(validateGuid("string")).toEqual(errorMessage) | |||
}) | |||
}) | |||
}) | |||
describe("validateMaxLength", function() { | |||
describe("validateMaxLength", function() { | |||
let errorMessage = "Value must be less than MaxLength" | |||
it("doesn't return for valid guid", function() { | |||
@@ -257,9 +259,9 @@ describe("utils", function() { | |||
expect(validateMaxLength("abc", 1)).toEqual(errorMessage) | |||
expect(validateMaxLength("abc", 2)).toEqual(errorMessage) | |||
}) | |||
}) | |||
}) | |||
describe("validateMinLength", function() { | |||
describe("validateMinLength", function() { | |||
let errorMessage = "Value must be greater than MinLength" | |||
it("doesn't return for valid guid", function() { | |||
@@ -271,7 +273,29 @@ describe("utils", function() { | |||
expect(validateMinLength("abc", 5)).toEqual(errorMessage) | |||
expect(validateMinLength("abc", 8)).toEqual(errorMessage) | |||
}) | |||
}) | |||
}) | |||
describe("validatePattern", function() { | |||
let rxPattern = "^(red|blue)" | |||
let errorMessage = "Value must follow pattern " + rxPattern | |||
it("doesn't return for a match", function() { | |||
expect(validatePattern("red", rxPattern)).toBeFalsy() | |||
expect(validatePattern("blue", rxPattern)).toBeFalsy() | |||
}) | |||
it("returns a message for invalid pattern", function() { | |||
expect(validatePattern("pink", rxPattern)).toEqual(errorMessage) | |||
expect(validatePattern("123", rxPattern)).toEqual(errorMessage) | |||
}) | |||
it("fails gracefully when an invalid regex value is passed", function() { | |||
expect(() => validatePattern("aValue", "---")).toNotThrow() | |||
expect(() => validatePattern("aValue", 1234)).toNotThrow() | |||
expect(() => validatePattern("aValue", null)).toNotThrow() | |||
expect(() => validatePattern("aValue", [])).toNotThrow() | |||
}) | |||
}) | |||
describe("validateParam", function() { | |||
let param = null | |||
@@ -524,7 +548,7 @@ describe("utils", function() { | |||
type: "boolean", | |||
value: "test string" | |||
} | |||
assertValidateParam(param, ["Required field is not provided"]) | |||
assertValidateParam(param, ["Value must be a boolean"]) | |||
// valid boolean value | |||
param = { | |||
@@ -584,7 +608,7 @@ describe("utils", function() { | |||
type: "number", | |||
value: "test" | |||
} | |||
assertValidateParam(param, ["Required field is not provided"]) | |||
assertValidateParam(param, ["Value must be a number"]) | |||
// invalid number, undefined value | |||
param = { | |||
@@ -666,7 +690,7 @@ describe("utils", function() { | |||
type: "integer", | |||
value: "test" | |||
} | |||
assertValidateParam(param, ["Required field is not provided"]) | |||
assertValidateParam(param, ["Value must be an integer"]) | |||
// invalid integer, undefined value | |||
param = { | |||
@@ -676,6 +700,14 @@ describe("utils", function() { | |||
} | |||
assertValidateParam(param, ["Required field is not provided"]) | |||
// valid integer, but 0 is falsy in JS | |||
param = { | |||
required: true, | |||
type: "integer", | |||
value: 0 | |||
} | |||
assertValidateParam(param, []) | |||
// valid integer | |||
param = { | |||
required: true, | |||
@@ -885,4 +917,44 @@ describe("utils", function() { | |||
expect(result).toEqual("hello\\#world") | |||
}) | |||
}) | |||
describe("sanitizeUrl", function() { | |||
it("should sanitize a `javascript:` url", function() { | |||
const res = sanitizeUrl("javascript:alert('bam!')") | |||
expect(res).toEqual("about:blank") | |||
}) | |||
it("should sanitize a `data:` url", function() { | |||
const res = sanitizeUrl(`data:text/html;base64,PHNjcmlwdD5hbGVydCgiSGV | |||
sbG8iKTs8L3NjcmlwdD4=`) | |||
expect(res).toEqual("about:blank") | |||
}) | |||
it("should not modify a `http:` url", function() { | |||
const res = sanitizeUrl(`http://swagger.io/`) | |||
expect(res).toEqual("http://swagger.io/") | |||
}) | |||
it("should not modify a `https:` url", function() { | |||
const res = sanitizeUrl(`https://swagger.io/`) | |||
expect(res).toEqual("https://swagger.io/") | |||
}) | |||
it("should gracefully handle empty strings", function() { | |||
expect(sanitizeUrl("")).toEqual("") | |||
}) | |||
it("should gracefully handle non-string values", function() { | |||
expect(sanitizeUrl(123)).toEqual("") | |||
expect(sanitizeUrl(null)).toEqual("") | |||
expect(sanitizeUrl(undefined)).toEqual("") | |||
expect(sanitizeUrl([])).toEqual("") | |||
expect(sanitizeUrl({})).toEqual("") | |||
}) | |||
}) | |||
}) |
@@ -93,6 +93,7 @@ module.exports = { | |||
petAPIWrapperBar: { | |||
selector: ".swagger-ui .opblock-tag-section:nth-child(1) .opblock-tag" | |||
}, | |||
/** | |||
* Post pet/ api | |||
*/ | |||
@@ -141,6 +142,7 @@ module.exports = { | |||
petOperationPostStatus: { | |||
selector: ".swagger-ui .opblock-tag-section:nth-child(1) div#operations-pet-addPet pre.microlight span:nth-child(70)" | |||
}, | |||
/** | |||
* Put pet/ api | |||
*/ | |||
@@ -189,8 +191,9 @@ module.exports = { | |||
petOperationPutStatus: { | |||
selector: ".swagger-ui .opblock-tag-section:nth-child(1) div#operations-pet-updatePet pre.microlight span:nth-child(70)" | |||
}, | |||
/** | |||
* Get pet/ | |||
* Get /pet/findByTags | |||
*/ | |||
petOperationGetByTagContainer: { | |||
selector: ".swagger-ui .opblock-tag-section:nth-child(1) div#operations-pet-findPetsByTags" | |||
@@ -237,6 +240,34 @@ module.exports = { | |||
petOperationGetByTagStatus: { | |||
selector: ".swagger-ui .opblock-tag-section:nth-child(1) div#operations-pet-findPetsByTags pre.microlight span:nth-child(70)" | |||
}, | |||
/** | |||
* Get /pet/{petId} | |||
*/ | |||
petOperationGetByIdContainer: { | |||
selector: ".swagger-ui .opblock-tag-section:nth-child(1) div#operations-pet-getPetById" | |||
}, | |||
petOperationGetByIdTitle: { | |||
selector: ".swagger-ui .opblock-tag-section:nth-child(1) div#operations-pet-getPetById .opblock-summary-get span.opblock-summary-path span" | |||
}, | |||
petOperationGetByIdCollpase: { | |||
selector: ".swagger-ui .opblock-tag-section:nth-child(1) div#operations-pet-getPetById .opblock-summary-get" | |||
}, | |||
petOperationGetByIdCollapseContainer: { | |||
selector: ".swagger-ui .opblock-tag-section:nth-child(1) div#operations-pet-getPetById .ReactCollapse--collapse" | |||
}, | |||
petOperationGetByIdTryBtn: { | |||
selector: ".swagger-ui .opblock-tag-section:nth-child(1) div#operations-pet-getPetById button.try-out__btn" | |||
}, | |||
petOperationGetByIdExecuteBtn: { | |||
selector: ".swagger-ui .opblock-tag-section:nth-child(1) div#operations-pet-getPetById button.execute" | |||
}, | |||
petOperationGetByIdParameter: { | |||
selector: ".swagger-ui .opblock-tag-section:nth-child(3) div#operations-pet-getPetById div.parameters-col_description input" | |||
}, | |||
petOperationGetByIdResultsBox: { | |||
selector: ".swagger-ui .opblock-tag-section:nth-child(1) div#operations-pet-getPetById pre.microlight" | |||
}, | |||
/** | |||
* Delete pet/ | |||
@@ -497,9 +528,5 @@ module.exports = { | |||
}, | |||
} | |||
} | |||
} | |||
} |
@@ -84,6 +84,7 @@ describe("render pet api container", function () { | |||
client.end() | |||
}) | |||
it("Testing put /pet api Mock data", function (client) { | |||
apiWrapper.waitForElementVisible("@petOperationPutContainer", 5000) | |||
.click("@petOperationPutCollpase") | |||
@@ -137,6 +138,38 @@ describe("render pet api container", function () { | |||
client.end() | |||
}) | |||
it("render get by ID /pet/{petId} api container", function (client) { | |||
apiWrapper.waitForElementVisible("@petOperationGetByIdContainer", 5000) | |||
.assert.containsText("@petOperationGetByIdTitle", "/pet/{petId}") | |||
.click("@petOperationGetByIdCollpase") | |||
.waitForElementVisible("@petOperationGetByIdCollapseContainer", 3000) | |||
.click("@petOperationGetByIdTryBtn") | |||
.waitForElementVisible("@petOperationGetByTagExecuteBtn", 1000) | |||
.click("@petOperationGetByTagTryBtn") | |||
.assert.cssClassNotPresent("@petOperationGetByTagTryBtn", "cancel") | |||
client.end() | |||
}) | |||
it("render get by ID /pet/{petId} api Mock data", function (client) { | |||
apiWrapper.waitForElementVisible("@petOperationGetByIdContainer", 5000) | |||
.assert.containsText("@petOperationGetByIdTitle", "/pet/{petId}") | |||
.click("@petOperationGetByIdCollpase") | |||
.waitForElementVisible("@petOperationGetByIdCollapseContainer", 3000) | |||
.click("@petOperationGetByIdTryBtn") | |||
.waitForElementVisible("@petOperationGetByTagExecuteBtn", 1000) | |||
.setValue("@petOperationGetByIdParameter", "abc") | |||
.click("@petOperationGetByIdExecuteBtn") | |||
.waitForElementVisible("@petOperationGetByIdResultsBox") | |||
.assert.containsText("@petOperationGetByIdParameter", "abc") | |||
.assert.cssClassPresent("@petOperationGetByIdParameter", "invalid") | |||
.assert.attributeEquals("@petOperationGetByIdParameter", "title", "Value must be an integer") | |||
.click("@petOperationGetByTagTryBtn") | |||
.assert.cssClassNotPresent("@petOperationGetByTagTryBtn", "cancel") | |||
client.end() | |||
}) | |||
it("render delete /pet api container", function (client) { | |||
apiWrapper.waitForElementVisible("@petOperationDeleteContainer") | |||
@@ -150,6 +183,7 @@ describe("render pet api container", function () { | |||
client.end() | |||
}) | |||
it("Testing delete /pet api Mock data", function (client) { | |||
apiWrapper.waitForElementVisible("@petOperationDeleteContainer", 3000) | |||
.click("@petOperationDeleteCollpase") | |||