Compare commits

..
63 Commits
Author SHA1 Message Date
kyle 859edbf7f7 Merge pull request #3892 from swagger-api/v/3.4.4
v3.4.4
2017-11-10 23:25:31 -08:00
Kyle Shockey 81e7193eaf Build for v3.4.4 2017-11-10 23:21:20 -08:00
Kyle Shockey fadc522f56 v3.4.4 2017-11-10 23:16:51 -08:00
Kyle Shockey e45b9b82a8 Fix docExpansion: full regression 2017-11-10 22:34:55 -08:00
kyle b0420729c9 Merge pull request #3825 from heldersepu/feature/validation_tooltips
Add validation error tooltips
2017-11-10 19:12:07 -08:00
kyle b2c41e1e07 Merge branch 'master' into feature/validation_tooltips 2017-11-10 18:40:14 -08:00
kyle 0432828c56 Merge pull request #3885 from swagger-api/ft/big-spec-performance
Improve performance of big API definitions
2017-11-10 18:11:17 -08:00
Kyle Shockey 82a2ee9a34 Add safe string method access for toTitleCase 2017-11-10 16:57:14 -08:00
kyle c3b7f071c8 Merge branch 'master' into ft/big-spec-performance 2017-11-10 16:45:20 -08:00
kyle 9020ee1efa Merge pull request #3884 from swagger-api/fix/model-longtext-fix
Removed set width from Model prop
2017-11-10 16:30:01 -08:00
kyle 12fd5d7c8d Merge branch 'master' into fix/model-longtext-fix 2017-11-10 16:23:31 -08:00
kyle e83344e0a2 Merge pull request #3889 from swagger-api/bug/3299-param-validation-regression
Validate number and integer parameter value `0` correctly
2017-11-10 11:25:24 -08:00
kyle 4041689c1d Merge branch 'master' into bug/3299-param-validation-regression 2017-11-10 10:52:56 -08:00
Kyle Shockey 365585ceea Add check for 0 value for number and integer parameter values 2017-11-10 10:45:19 -08:00
Kyle Shockey d92a27bdab Add failing tests 2017-11-10 10:40:03 -08:00
kyle bfe2667326 Remove unused Immutable.List import 2017-11-09 19:28:20 -08:00
kyle 6a2659c5d0 Merge branch 'master' into ft/big-spec-performance 2017-11-09 19:17:37 -08:00
Kyle Shockey f4f3b25d8f Create newSpecErrBatch for more wealth and prosperity 2017-11-09 16:48:22 -08:00
Kyle Shockey e33de3049f Refactor Operation component to not trigger its own re-render 2017-11-09 16:28:53 -08:00
Helder Sepulveda 61a9fa0fcc Merge branch 'master' into feature/validation_tooltips 2017-11-09 15:41:15 -05:00
Minasokoni 5b6cd88557 removed set width 2017-11-09 12:18:10 -08:00
kyle 75d482f27f Merge pull request #3869 from feenr/bug/3658-add-enzyme-test-for-objectmodel
Bug/3658 add enzyme test for objectmodel
2017-11-08 22:53:46 -08:00
kyle 49457fe089 Correct typo in test description 2017-11-08 22:48:20 -08:00
kyle f7be20f42c Merge branch 'master' into bug/3658-add-enzyme-test-for-objectmodel 2017-11-08 22:47:13 -08:00
kyle fdc8313433 Merge pull request #3872 from ninja-inc/bug/solve-react-warning
adding a key prop to solve React.js warning
2017-11-08 22:45:51 -08:00
Kyle Shockey d063987883 Use React.cloneElement to give array elements keys instead of hardcoding 2017-11-08 22:41:29 -08:00
kyle c0f80ebdf2 Merge branch 'master' into bug/solve-react-warning 2017-11-08 22:34:46 -08:00
kyle 76617a5ee7 Merge pull request #3875 from thompsongl/bug/misc-proptype-fixes
Bug/misc proptype fixes
2017-11-08 22:32:04 -08:00
kyle 1d6b8e3892 Merge branch 'master' into bug/misc-proptype-fixes 2017-11-08 22:28:24 -08:00
kyle 4fa4e0f3e3 Merge pull request #3880 from legrego/ft/3714-dependencies-not-compatible-with-React-16
Fixes #3714: Update react-collapse and react-motion for React 16 support
2017-11-08 22:26:25 -08:00
Greg Thompson a7531a245c Merge branch 'master' into bug/misc-proptype-fixes 2017-11-08 16:09:31 -06:00
Ryan Feeney 1f11b3e4ac Merge branch 'master' into bug/3658-add-enzyme-test-for-objectmodel 2017-11-08 16:16:12 -05:00
Larry Gregory 57a3be28b0 Update react-collapse and react-motion 2017-11-08 07:41:23 -05:00
Iida, Takaaki | Tak | TRVDD 6fb9d0b465 Merge remote-tracking branch 'upstream/master' into bug/solve-react-warning 2017-11-08 15:57:46 +09:00
kyle 362f1392b5 Merge pull request #3878 from swagger-api/bug/3219-parameter-value-performance
Make `Model` a PureComponent
2017-11-07 21:24:02 -08:00
Kyle Shockey 8b8c9b744d Make Model a PureComponent 2017-11-07 20:12:19 -08:00
Ryan Feeney 1aabdded97 Merge branch 'master' into bug/3658-add-enzyme-test-for-objectmodel 2017-11-07 15:06:22 -05:00
Greg Thompson f2cbfd0e51 contentType prop not required 2017-11-07 11:17:05 -06:00
Greg Thompson d96bd29d0c pass required getConfig to parameter-row 2017-11-07 11:16:41 -06:00
Greg Thompson 16e756bed7 disallow null value 2017-11-07 11:15:37 -06:00
takaaki.iida 6664058dbe https://github.com/swagger-api/swagger-ui/issues/3871 adding a key prop to solve React.js warning 2017-11-07 20:03:56 +09:00
kyle 076f32b1f0 Merge pull request #3870 from swagger-api/bug/auth-operation-btn-error
Bug/auth operation btn error
2017-11-06 22:46:24 -08:00
Kyle Shockey 531d0337ac Remove describe.only 2017-11-06 22:13:29 -08:00
Kyle Shockey 8f7b582f95 Improve junk data handling 2017-11-06 22:09:20 -08:00
Kyle Shockey 3536f2d518 Add tests for modified selectors 2017-11-06 22:08:42 -08:00
Kyle Shockey 533fd75501 Deprecate authSelectors.getDefinitionsByNames 2017-11-06 21:53:57 -08:00
Kyle Shockey ed34a8dae9 Linter: Remove unused import 2017-11-06 21:24:16 -08:00
Kyle Shockey cfc030d07d Rework filtering logic for definitionsForRequirements 2017-11-06 21:13:14 -08:00
Kyle Shockey 86db21515e Save nyc as a devDependency 2017-11-06 21:01:46 -08:00
Kyle Shockey 21bf5919a9 Rewire AuthorizeOperationBtn; create new selector for filtering definitions 2017-11-06 20:42:47 -08:00
Kyle Shockey cca8ddb5d5 Add nyc coverage reporting 2017-11-06 14:39:21 -08:00
feenr bcad5b583e Remove commented out and debug code 2017-11-06 12:41:14 -05:00
Ryan Feeney d291d75d2c Merge branch 'master' into bug/3658-add-enzyme-test-for-objectmodel 2017-11-06 12:38:50 -05:00
feenr 7fe07591b2 Update the pre-req version of node in CONTRIBUTING.md 2017-11-06 12:32:32 -05:00
feenr e9d94e02d8 Add new tests for object-model 2017-11-06 10:43:43 -05:00
HelderSepu 58dcce497e e2e test for the validation 2017-11-04 18:40:46 -04:00
Helder Sepulveda e10b01c6ff Merge branch 'master' into feature/validation_tooltips 2017-11-04 09:19:41 -04:00
Helder Sepulveda 59464de58e Merge branch 'master' into feature/validation_tooltips 2017-11-03 21:43:27 -04:00
Helder Sepulveda 8731ff7512 Merge branch 'master' into feature/validation_tooltips 2017-11-01 09:32:30 -04:00
Helder Sepulveda 24cd95cf54 Merge branch 'master' into feature/validation_tooltips 2017-10-28 12:30:05 -04:00
Helder Sepulveda 6f876bcb12 Merge branch 'master' into feature/validation_tooltips 2017-10-27 15:51:20 -04:00
Helder Sepulveda 866e4d5a9e Merge branch 'master' into feature/validation_tooltips 2017-10-25 21:07:50 -04:00
HelderSepu ba32f60dec Add validation error tooltips
If there is an error put it on the tooltip
2017-10-25 21:02:14 -04:00
34 changed files with 428 additions and 123 deletions
+1
View File
@@ -2,6 +2,7 @@ node_modules
.idea
.deps_check
.DS_Store
.nyc_output
npm-debug.log*
.eslintcache
package-lock.json
+1 -1
View File
@@ -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.
+1 -1
View File
@@ -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)
+16 -16
View File
File diff suppressed because one or more lines are too long
+1 -1
View File
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
+1 -1
View File
File diff suppressed because one or more lines are too long
+2 -2
View File
File diff suppressed because one or more lines are too long
+1 -1
View File
File diff suppressed because one or more lines are too long
+12 -4
View File
@@ -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
}
}
+1 -1
View File
@@ -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 -1
View File
@@ -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"
+2 -2
View File
@@ -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 -1
View File
@@ -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()
+5 -5
View File
@@ -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
+4
View File
@@ -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")
+19 -34
View File
@@ -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 &&
+6 -4
View File
@@ -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}
+20 -7
View File
@@ -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 }
+9 -1
View File
@@ -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()
+8
View File
@@ -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,
+10
View File
@@ -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
View File
@@ -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")
+2 -2
View File
@@ -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
View File
@@ -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
+63
View File
@@ -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")
})
})
+133
View File
@@ -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([])
})
})
})
+8
View File
@@ -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
View File
@@ -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 = {
},
}
}
}
}
+34
View File
@@ -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")