Compare commits

...
6 Commits
Author SHA1 Message Date
kyle aa22756641 V/3.15.0 (#4571)
* v3.15.0

* rebuild dist
2018-05-19 00:38:16 -07:00
kyle 16bf8fb3be fix(docker-releases): trim leading v from image names (#4567)
Fixes #4497.
2018-05-17 16:24:14 -07:00
kyle bf5acc1f40 fix(topbar): remove href from Swagger logo (#4566)
Fixes #4527.

- this `href` didn't serve any visible or known purpose
- it was added before prior to 3.0.0 and has not been modified since
  - see UX 8ab65d3b
- the `Link` was kept, since the anchor was needed to preserve the current layout.
2018-05-17 16:00:26 -07:00
kyle c1007a287b feature: OAS3 object parameter support (#4563)
* render suitable interface for `type: object` parameters

* validate OAS3 object parameters correctly

* display parameter validation errors

* remove irrelevant css classes

* rm comment

* fix failing tests

* add validateParam tests

* add enzyme tests for object parameter rendering

* run actual tests first
2018-05-16 22:48:44 -07:00
kyle c8480a827a fix: respect OAS3 parameter default values (#4561)
* add test cases

* refactor default setters into own function

* reach into `schema` for default value in OAS3

* remove exclusive test
2018-05-16 00:27:14 -07:00
kyle 55fdeeb810 Issue template tweaks (#4520)
* MOAR issue templates

* ...LESS issue templates

* minor issue template tweaks
2018-05-14 21:03:00 -07:00
20 changed files with 338 additions and 63 deletions
+11 -10
View File
@@ -5,23 +5,24 @@ about: Report an issue you're experiencing
---
<!---
Thanks for filing a bug report 😄 ! Before you submit, please read the following:
Thanks for filing a bug report! 😄
If you're here to report a security issue, please STOP writing an issue and
contact us at security@swagger.io instead!
Before you submit, please read the following:
Search open/closed issues before submitting!
If you're here to report a security issue, please STOP writing an issue and
contact us at security@swagger.io instead!
Issues on GitHub are only related to problems of Swagger-UI itself. We'll try
to offer support here for your use case, but we can't offer help with projects
that use Swagger-UI indirectly, like Springfox or swagger-node.
Search open/closed issues before submitting!
Likewise, we can't accept bugs in the Swagger/OpenAPIspecifications themselves,
or anything that violates the specifications.
Issues on GitHub are only related to problems of Swagger-UI itself. We'll try
to offer support here for your use case, but we can't offer help with projects
that use Swagger-UI indirectly, like Springfox or swagger-node.
Likewise, we can't accept bugs in the Swagger/OpenAPI specifications
themselves, or anything that violates the specifications.
-->
## Q&A (please complete the following information)
### Q&A (please complete the following information)
- OS: [e.g. macOS]
- Browser: [e.g. chrome, safari]
- Version: [e.g. 22]
+1 -1
View File
@@ -4,7 +4,7 @@ about: Suggest an new feature or enhancement for this project
---
## Q&A (please complete the following information)
### Q&A (please complete the following information)
- OS: [e.g. macOS]
- Browser: [e.g. chrome, safari]
- Version: [e.g. 22]
+1 -1
View File
@@ -37,7 +37,7 @@ after_success:
docker login --username=$DOCKER_HUB_USERNAME --password=$DOCKER_HUB_PASSWORD;
if [ ! -z "$TRAVIS_TAG" ]; then
DOCKER_IMAGE_TAG=$TRAVIS_TAG;
DOCKER_IMAGE_TAG=${TRAVIS_TAG#?};
else
DOCKER_IMAGE_TAG=unstable;
fi;
+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.14.2 | 2018-05-11 | 2.0, 3.0 | [tag v3.14.2](https://github.com/swagger-api/swagger-ui/tree/v3.14.2)
3.15.0 | 2018-05-19 | 2.0, 3.0 | [tag v3.15.0](https://github.com/swagger-api/swagger-ui/tree/v3.15.0)
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)
+14 -14
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
+3 -3
View File
@@ -1,6 +1,6 @@
{
"name": "swagger-ui",
"version": "3.14.2",
"version": "3.15.0",
"main": "dist/swagger-ui.js",
"repository": "git@github.com:swagger-api/swagger-ui.git",
"contributors": [
@@ -28,7 +28,7 @@
"lint": "eslint --cache --ext '.js,.jsx' src test",
"lint-errors": "eslint --cache --quiet --ext '.js,.jsx' src test",
"lint-fix": "eslint --cache --ext '.js,.jsx' src test --fix",
"test": "npm run lint-errors && npm run just-test-in-node",
"test": "npm run just-test-in-node && npm run lint-errors",
"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 --require test/setup.js --recursive --compilers js:babel-core/register test/core test/components test/bugs test/swagger-ui-dist-package test/xss",
@@ -84,7 +84,7 @@
"scroll-to-element": "^2.0.0",
"serialize-error": "2.0.0",
"shallowequal": "0.2.2",
"swagger-client": "^3.8.1",
"swagger-client": "^3.8.4",
"url-parse": "^1.1.8",
"whatwg-fetch": "0.11.1",
"worker-loader": "^0.7.1",
+24 -17
View File
@@ -22,20 +22,7 @@ export default class ParameterRow extends Component {
constructor(props, context) {
super(props, context)
let { specSelectors, pathMethod, param } = props
let defaultValue = param.get("default")
let xExampleValue = param.get("x-example")
let parameter = specSelectors.parameterWithMeta(pathMethod, param.get("name"), param.get("in"))
let value = parameter ? parameter.get("value") : ""
if( param.get("in") !== "body" ) {
if ( xExampleValue !== undefined && value === undefined && specSelectors.isSwagger2() ) {
this.onChangeWrapper(xExampleValue)
} else if ( defaultValue !== undefined && value === undefined ) {
this.onChangeWrapper(defaultValue)
}
}
this.setDefaultValue()
}
componentWillReceiveProps(props) {
@@ -43,7 +30,6 @@ export default class ParameterRow extends Component {
let { isOAS3 } = specSelectors
let example = param.get("example")
let defaultValue = param.get("default")
let parameter = specSelectors.parameterWithMeta(pathMethod, param.get("name"), param.get("in"))
let enumValue
@@ -61,8 +47,6 @@ export default class ParameterRow extends Component {
value = paramValue
} else if ( example !== undefined ) {
value = example
} else if ( defaultValue !== undefined) {
value = defaultValue
} else if ( param.get("required") && enumValue && enumValue.size ) {
value = enumValue.first()
}
@@ -77,6 +61,29 @@ export default class ParameterRow extends Component {
return onChange(param, value)
}
setDefaultValue = () => {
let { specSelectors, pathMethod, param } = this.props
if (param.get("value") !== undefined) {
return
}
let schema = specSelectors.isOAS3() ? param.get("schema", Map({})) : param
let defaultValue = schema.get("default")
let xExampleValue = param.get("x-example") // Swagger 2 only
let parameter = specSelectors.parameterWithMeta(pathMethod, param.get("name"), param.get("in"))
let value = parameter ? parameter.get("value") : ""
if( param.get("in") !== "body" ) {
if ( xExampleValue !== undefined && value === undefined && specSelectors.isSwagger2() ) {
this.onChangeWrapper(xExampleValue)
} else if ( defaultValue !== undefined && value === undefined ) {
this.onChangeWrapper(defaultValue)
}
}
}
render() {
let {param, onChange, getComponent, getConfigs, isExecute, fn, onChangeConsumes, specSelectors, pathMethod, specPath} = this.props
+52
View File
@@ -1,8 +1,10 @@
import React, { PureComponent, Component } from "react"
import PropTypes from "prop-types"
import { List, fromJS } from "immutable"
import cx from "classnames"
import ImPropTypes from "react-immutable-proptypes"
import DebounceInput from "react-debounce-input"
import { getSampleSchema } from "core/utils"
//import "less/json-schema-form"
const noop = ()=> {}
@@ -204,3 +206,53 @@ export class JsonSchema_boolean extends Component {
onChange={ this.onEnumChange }/>)
}
}
export class JsonSchema_object extends PureComponent {
constructor() {
super()
}
static propTypes = JsonSchemaPropShape
static defaultProps = JsonSchemaDefaultProps
componentDidMount() {
if(!this.props.value && this.props.schema) {
this.resetValueToSample()
}
}
resetValueToSample = () => {
this.onChange(getSampleSchema(this.props.schema) )
}
onChange = (value) => {
this.props.onChange(value)
}
handleOnChange = e => {
const inputValue = e.target.value
this.onChange(inputValue)
}
render() {
let {
getComponent,
value,
errors
} = this.props
const TextArea = getComponent("TextArea")
return (
<div>
<TextArea
className={cx({ invalid: errors.size })}
title={ errors.size ? errors.join(", ") : ""}
value={value}
onChange={ this.handleOnChange }/>
</div>
)
}
}
+24 -1
View File
@@ -503,7 +503,30 @@ export const validateParam = (param, isXml, isOAS3 = false) => {
let numberCheck = type === "number" && (value || value === 0)
let integerCheck = type === "integer" && (value || value === 0)
if ( required && !(stringCheck || arrayCheck || listCheck || fileCheck || booleanCheck || numberCheck || integerCheck) ) {
let oas3ObjectCheck = false
if(false || isOAS3 && type === "object") {
if(typeof value === "object") {
oas3ObjectCheck = true
} else if(typeof value === "string") {
try {
JSON.parse(value)
oas3ObjectCheck = true
} catch(e) {
errors.push("Parameter string value must be valid JSON")
return errors
}
}
}
const allChecks = [
stringCheck, arrayCheck, listCheck, fileCheck, booleanCheck,
numberCheck, integerCheck, oas3ObjectCheck
]
const passedAnyCheck = allChecks.some(v => !!v)
if ( required && !passedAnyCheck ) {
errors.push("Required field is not provided")
return errors
}
+1 -1
View File
@@ -140,7 +140,7 @@ export default class Topbar extends React.Component {
<div className="topbar">
<div className="wrapper">
<div className="topbar-wrapper">
<Link href="#">
<Link>
<img height="30" width="30" src={ Logo } alt="Swagger UI"/>
<span>swagger</span>
</Link>
+2 -1
View File
@@ -51,7 +51,8 @@ input[type=text],
input[type=password],
input[type=search],
input[type=email],
input[type=file]
input[type=file],
textarea
{
min-width: 100px;
margin: 5px 0;
@@ -0,0 +1,67 @@
/* eslint-env mocha */
import React from "react"
import { List, fromJS } from "immutable"
import expect, { createSpy } from "expect"
import { render } from "enzyme"
import ParameterRow from "components/parameter-row"
describe("bug #4557: default parameter values", function(){
it("should apply a Swagger 2.0 default value", function(){
const paramValue = fromJS({
description: "a pet",
type: "string",
default: "MyDefaultValue"
})
let props = {
getComponent: ()=> "div",
specSelectors: {
security(){},
parameterWithMeta(){ return paramValue },
isOAS3(){ return false }
},
operation: {get: ()=>{}},
onChange: createSpy(),
param: paramValue,
onChangeConsumes: () => {},
pathMethod: [],
getConfigs: () => { return {} },
specPath: List([])
}
render(<ParameterRow {...props}/>)
expect(props.onChange).toHaveBeenCalledWith(paramValue, "MyDefaultValue")
})
it("should apply an OpenAPI 3.0 default value", function(){
const paramValue = fromJS({
description: "a pet",
schema: {
type: "string",
default: "MyDefaultValue"
}
})
let props = {
getComponent: ()=> "div",
specSelectors: {
security(){},
parameterWithMeta(){ return paramValue },
isOAS3(){ return true }
},
operation: {get: ()=>{}},
onChange: createSpy(),
param: paramValue,
onChangeConsumes: () => {},
pathMethod: [],
getConfigs: () => { return {} },
specPath: List([])
}
render(<ParameterRow {...props}/>)
expect(props.onChange).toHaveBeenCalledWith(paramValue, "MyDefaultValue")
})
})
+36 -3
View File
@@ -1,12 +1,13 @@
/* eslint-env mocha */
import React from "react"
import { List } from "immutable"
import expect, { createSpy } from "expect"
import { Select, Input } from "components/layout-utils"
import { render } from "enzyme"
import { Select, Input, TextArea } from "components/layout-utils"
import { mount, render } from "enzyme"
import * as JsonSchemaComponents from "core/json-schema-components"
import { JsonSchemaForm } from "core/json-schema-components"
const components = {...JsonSchemaComponents, Select, Input}
const components = {...JsonSchemaComponents, Select, Input, TextArea}
const getComponentStub = (name) => {
if(components[name]) return components[name]
@@ -107,6 +108,38 @@ describe("<JsonSchemaForm/>", function(){
expect(wrapper.find("select option").first().text()).toEqual("true")
})
})
describe("objects", function() {
it("should render the correct editor for an OAS3 object parameter", function(){
let updateQueue = []
let props = {
getComponent: getComponentStub,
value: "",
onChange: (value) => {
updateQueue.push({ value })
},
keyName: "",
fn: {},
errors: List(),
schema: {
type: "object",
properties: {
id: {
type: "string",
example: "abc123"
}
}
}
}
let wrapper = mount(<JsonSchemaForm {...props}/>)
updateQueue.forEach(newProps => wrapper.setProps(newProps))
expect(wrapper.find("textarea").length).toEqual(1)
expect(wrapper.find("textarea").text()).toEqual(`{\n "id": "abc123"\n}`)
})
})
describe("unknown types", function() {
it("should render unknown types as strings", function(){
+94 -3
View File
@@ -350,6 +350,12 @@ describe("utils", function() {
expect( result ).toEqual( expectedError )
}
const assertValidateOas3Param = (param, expectedError) => {
// for cases where you _only_ want to try OAS3
result = validateParam( fromJS(param), false, true )
expect( result ).toEqual( expectedError )
}
it("should check the isOAS3 flag when validating parameters", function() {
// This should "skip" validation because there is no `schema` property
// and we are telling `validateParam` this is an OAS3 spec
@@ -361,6 +367,92 @@ describe("utils", function() {
expect( result ).toEqual( [] )
})
it("validates required OAS3 objects", function() {
// valid object
param = {
required: true,
schema: {
type: "object"
},
value: {
abc: 123
}
}
assertValidateOas3Param(param, [])
// valid object-as-string
param = {
required: true,
schema: {
type: "object"
},
value: JSON.stringify({
abc: 123
})
}
assertValidateOas3Param(param, [])
// invalid object-as-string
param = {
required: true,
schema: {
type: "object"
},
value: "{{}"
}
assertValidateOas3Param(param, ["Parameter string value must be valid JSON"])
// missing when required
param = {
required: true,
schema: {
type: "object"
},
}
assertValidateOas3Param(param, ["Required field is not provided"])
})
it("validates optional OAS3 objects", function() {
// valid object
param = {
schema: {
type: "object"
},
value: {
abc: 123
}
}
assertValidateOas3Param(param, [])
// valid object-as-string
param = {
schema: {
type: "object"
},
value: JSON.stringify({
abc: 123
})
}
assertValidateOas3Param(param, [])
// invalid object-as-string
param = {
schema: {
type: "object"
},
value: "{{}"
}
assertValidateOas3Param(param, ["Parameter string value must be valid JSON"])
// missing when not required
param = {
schema: {
type: "object"
},
}
assertValidateOas3Param(param, [])
})
it("validates required strings", function() {
// invalid string
param = {
@@ -962,7 +1054,7 @@ describe("utils", function() {
expect(result).toEqual(Map([[ "minimum", "b"]]))
})
})
describe("deeplyStripKey", function() {
it("should filter out a specified key", function() {
const input = {
@@ -1065,8 +1157,7 @@ describe("utils", function() {
})
it("should sanitize a `data:` url", function() {
const res = sanitizeUrl(`data:text/html;base64,PHNjcmlwdD5hbGVydCgiSGV
sbG8iKTs8L3NjcmlwdD4=`)
const res = sanitizeUrl(`data:text/html;base64,PHNjcmlwdD5hbGVydCgiSGVsbG8iKTs8L3NjcmlwdD4=`)
expect(res).toEqual("about:blank")
})