Compare commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
859edbf7f7 | ||
|
|
81e7193eaf | ||
|
|
fadc522f56 | ||
|
|
e45b9b82a8 | ||
|
|
b0420729c9 | ||
|
|
b2c41e1e07 | ||
|
|
0432828c56 | ||
|
|
82a2ee9a34 | ||
|
|
c3b7f071c8 | ||
|
|
9020ee1efa | ||
|
|
12fd5d7c8d | ||
|
|
e83344e0a2 | ||
|
|
4041689c1d | ||
|
|
365585ceea | ||
|
|
d92a27bdab | ||
|
|
bfe2667326 | ||
|
|
6a2659c5d0 | ||
|
|
f4f3b25d8f | ||
|
|
e33de3049f | ||
|
|
61a9fa0fcc | ||
|
|
5b6cd88557 | ||
|
|
75d482f27f | ||
|
|
49457fe089 | ||
|
|
f7be20f42c | ||
|
|
fdc8313433 | ||
|
|
d063987883 | ||
|
|
c0f80ebdf2 | ||
|
|
76617a5ee7 | ||
|
|
1d6b8e3892 | ||
|
|
4fa4e0f3e3 | ||
|
|
a7531a245c | ||
|
|
1f11b3e4ac | ||
|
|
57a3be28b0 | ||
|
|
6fb9d0b465 | ||
|
|
362f1392b5 | ||
|
|
8b8c9b744d | ||
|
|
1aabdded97 | ||
|
|
f2cbfd0e51 | ||
|
|
d96bd29d0c | ||
|
|
16e756bed7 | ||
|
|
6664058dbe | ||
|
|
076f32b1f0 | ||
|
|
531d0337ac | ||
|
|
8f7b582f95 | ||
|
|
3536f2d518 | ||
|
|
533fd75501 | ||
|
|
ed34a8dae9 | ||
|
|
cfc030d07d | ||
|
|
86db21515e | ||
|
|
21bf5919a9 | ||
|
|
cca8ddb5d5 | ||
|
|
bcad5b583e | ||
|
|
d291d75d2c | ||
|
|
7fe07591b2 | ||
|
|
e9d94e02d8 | ||
|
|
58dcce497e | ||
|
|
e10b01c6ff | ||
|
|
59464de58e | ||
|
|
8731ff7512 | ||
|
|
24cd95cf54 | ||
|
|
6f876bcb12 | ||
|
|
866e4d5a9e | ||
|
|
ba32f60dec |
@@ -2,6 +2,7 @@ node_modules
|
||||
.idea
|
||||
.deps_check
|
||||
.DS_Store
|
||||
.nyc_output
|
||||
npm-debug.log*
|
||||
.eslintcache
|
||||
package-lock.json
|
||||
|
||||
+1
-1
@@ -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.3 | 2017-11-03 | 2.0, 3.0 | [tag v3.4.3](https://github.com/swagger-api/swagger-ui/tree/v3.4.3)
|
||||
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)
|
||||
|
||||
Vendored
+16
-16
File diff suppressed because one or more lines are too long
Vendored
+1
-1
File diff suppressed because one or more lines are too long
Vendored
+1
-1
File diff suppressed because one or more lines are too long
+1
-1
File diff suppressed because one or more lines are too long
Vendored
+1
-1
File diff suppressed because one or more lines are too long
Vendored
+2
-2
File diff suppressed because one or more lines are too long
Vendored
+1
-1
File diff suppressed because one or more lines are too long
+12
-4
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "swagger-ui",
|
||||
"version": "3.4.3",
|
||||
"version": "3.4.4",
|
||||
"main": "dist/swagger-ui.js",
|
||||
"repository": "git@github.com:swagger-api/swagger-ui.git",
|
||||
"contributors": [
|
||||
@@ -33,6 +33,7 @@
|
||||
"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",
|
||||
@@ -60,13 +61,13 @@
|
||||
"react-addons-perf": "^15.4.0",
|
||||
"react-addons-shallow-compare": "0.14.8",
|
||||
"react-addons-test-utils": "^15.6.2",
|
||||
"react-collapse": "2.3.1",
|
||||
"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",
|
||||
@@ -79,7 +80,7 @@
|
||||
"scroll-to-element": "^2.0.0",
|
||||
"serialize-error": "2.0.0",
|
||||
"shallowequal": "0.2.2",
|
||||
"swagger-client": "^3.3.2",
|
||||
"swagger-client": "^3.3.3",
|
||||
"url-parse": "^1.1.8",
|
||||
"whatwg-fetch": "0.11.1",
|
||||
"worker-loader": "^0.7.1",
|
||||
@@ -127,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",
|
||||
@@ -152,5 +154,11 @@
|
||||
],
|
||||
"optionalDependencies": {
|
||||
"webpack-dev-server": "2.5.0"
|
||||
},
|
||||
"nyc": {
|
||||
"all": true,
|
||||
"include": [
|
||||
"**/src/core/plugins/**.js"
|
||||
]
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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(" ")
|
||||
|
||||
@@ -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")
|
||||
|
||||
@@ -12,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,
|
||||
@@ -52,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())
|
||||
}
|
||||
let { layoutActions, tagKey, operationKey, isShown } = this.props
|
||||
const isShownKey = ["operations", tagKey, operationKey]
|
||||
|
||||
isShown =() => {
|
||||
let { layoutSelectors, isShownKey, getConfigs } = this.props
|
||||
let { docExpansion } = getConfigs()
|
||||
|
||||
return layoutSelectors.isShown(isShownKey, docExpansion === "full" ) // Here is where we set the default
|
||||
layoutActions.show(isShownKey, !isShown)
|
||||
}
|
||||
|
||||
onTryoutClick =() => {
|
||||
@@ -102,7 +82,9 @@ export default class Operation extends PureComponent {
|
||||
|
||||
render() {
|
||||
let {
|
||||
isShownKey,
|
||||
operationKey,
|
||||
tagKey,
|
||||
isShown,
|
||||
jumpToKey,
|
||||
path,
|
||||
method,
|
||||
@@ -156,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} />
|
||||
@@ -183,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 &&
|
||||
|
||||
@@ -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}
|
||||
|
||||
@@ -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))
|
||||
|
||||
|
||||
@@ -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
|
||||
}
|
||||
|
||||
@@ -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 }
|
||||
|
||||
+2
-2
@@ -494,8 +494,8 @@ export const validateParam = (param, isXml, isOAS3 = false) => {
|
||||
let listCheck = type === "array" && Im.List.isList(value) && value.count()
|
||||
let fileCheck = type === "file" && value instanceof win.File
|
||||
let booleanCheck = type === "boolean" && (value || value === false)
|
||||
let numberCheck = type === "number" && value
|
||||
let integerCheck = type === "integer" && value
|
||||
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")
|
||||
|
||||
@@ -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>
|
||||
|
||||
+16
-10
@@ -3,14 +3,16 @@
|
||||
font-size: 12px;
|
||||
font-weight: 300;
|
||||
|
||||
@include text_code();
|
||||
|
||||
.deprecated
|
||||
{
|
||||
span, td {
|
||||
color: $model-deprecated-font-color !important;
|
||||
}
|
||||
span,
|
||||
td
|
||||
{
|
||||
color: $model-deprecated-font-color !important;
|
||||
}
|
||||
}
|
||||
|
||||
@include text_code();
|
||||
&-toggle
|
||||
{
|
||||
font-size: 10px;
|
||||
@@ -87,7 +89,8 @@
|
||||
background: rgba($model-hint-background-color,.7);
|
||||
}
|
||||
|
||||
p {
|
||||
p
|
||||
{
|
||||
margin: 0 0 1em 0;
|
||||
}
|
||||
}
|
||||
@@ -106,6 +109,7 @@ section.models
|
||||
h4
|
||||
{
|
||||
margin: 0 0 5px 0;
|
||||
|
||||
border-bottom: 1px solid rgba($section-models-isopen-h4-border-bottom-color, .3);
|
||||
}
|
||||
}
|
||||
@@ -114,6 +118,7 @@ section.models
|
||||
font-size: 16px;
|
||||
|
||||
display: flex;
|
||||
align-items: center;
|
||||
|
||||
margin: 0;
|
||||
padding: 10px 20px 10px 10px;
|
||||
@@ -122,7 +127,6 @@ section.models
|
||||
transition: all .2s;
|
||||
|
||||
@include text_headline($section-models-h4-font-color);
|
||||
align-items: center;
|
||||
|
||||
svg
|
||||
{
|
||||
@@ -202,7 +206,7 @@ section.models
|
||||
|
||||
&.deprecated
|
||||
{
|
||||
opacity: .5;
|
||||
opacity: .5;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -218,14 +222,16 @@ section.models
|
||||
{
|
||||
font-size: 16px;
|
||||
font-weight: 600;
|
||||
|
||||
margin-right: 1em;
|
||||
|
||||
@include text_headline($_color-delete);
|
||||
}
|
||||
|
||||
|
||||
span
|
||||
{
|
||||
> span.model
|
||||
> span.model
|
||||
{
|
||||
.brace-close
|
||||
{
|
||||
@@ -237,8 +243,8 @@ span
|
||||
.prop-name
|
||||
{
|
||||
display: inline-block;
|
||||
|
||||
margin-right: 1em;
|
||||
width: 8em;
|
||||
}
|
||||
|
||||
.prop-type
|
||||
|
||||
@@ -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([])
|
||||
})
|
||||
})
|
||||
})
|
||||
@@ -700,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,
|
||||
|
||||
+32
-5
@@ -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")
|
||||
|
||||
Reference in New Issue
Block a user