Compare commits
10
Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
f23be7d8f5 | ||
|
|
1be0a6df60 | ||
|
|
8a8aeeb119 | ||
|
|
5f855e56bb | ||
|
|
3f6e21e3b1 | ||
|
|
26d0ad7684 | ||
|
|
9a121ea445 | ||
|
|
c55f22575a | ||
|
|
2795518340 | ||
|
|
abe17f92ef |
@@ -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.13.3 | 2018-03-23 | 2.0, 3.0 | [tag v3.13.3](https://github.com/swagger-api/swagger-ui/tree/v3.13.3)
|
||||
3.13.4 | 2018-04-15 | 2.0, 3.0 | [tag v3.13.4](https://github.com/swagger-api/swagger-ui/tree/v3.13.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
+14
-14
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
+3
-3
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
+3
-3
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "swagger-ui",
|
||||
"version": "3.13.3",
|
||||
"version": "3.13.4",
|
||||
"main": "dist/swagger-ui.js",
|
||||
"repository": "git@github.com:swagger-api/swagger-ui.git",
|
||||
"contributors": [
|
||||
@@ -52,6 +52,7 @@
|
||||
"getbase": "^2.8.2",
|
||||
"ieee754": "^1.1.8",
|
||||
"immutable": "^3.x.x",
|
||||
"js-file-download": "^0.4.1",
|
||||
"js-yaml": "^3.5.5",
|
||||
"lodash": "4.17.5",
|
||||
"matcher": "^0.1.2",
|
||||
@@ -83,7 +84,7 @@
|
||||
"scroll-to-element": "^2.0.0",
|
||||
"serialize-error": "2.0.0",
|
||||
"shallowequal": "0.2.2",
|
||||
"swagger-client": "^3.6.0",
|
||||
"swagger-client": "^3.7.0",
|
||||
"url-parse": "^1.1.8",
|
||||
"whatwg-fetch": "0.11.1",
|
||||
"worker-loader": "^0.7.1",
|
||||
@@ -116,7 +117,6 @@
|
||||
"eslint-plugin-react": "^7.1.0",
|
||||
"extract-text-webpack-plugin": "^2.1.2",
|
||||
"file-loader": "0.11.2",
|
||||
"file-saver": "^1.3.8",
|
||||
"git-describe": "^4.0.1",
|
||||
"imports-loader": "0.7.1",
|
||||
"json-loader": "0.5.4",
|
||||
|
||||
@@ -1,12 +1,13 @@
|
||||
import React, { Component } from "react"
|
||||
import PropTypes from "prop-types"
|
||||
import { highlight } from "core/utils"
|
||||
import { saveAs } from "file-saver"
|
||||
import saveAs from "js-file-download"
|
||||
|
||||
export default class HighlightCode extends Component {
|
||||
static propTypes = {
|
||||
value: PropTypes.string.isRequired,
|
||||
className: PropTypes.string
|
||||
className: PropTypes.string,
|
||||
downloadable: PropTypes.bool
|
||||
}
|
||||
|
||||
componentDidMount() {
|
||||
@@ -22,8 +23,7 @@ export default class HighlightCode extends Component {
|
||||
}
|
||||
|
||||
downloadText = () => {
|
||||
let fileToSave = new Blob([this.props.value], {type: "text/plain"})
|
||||
saveAs(fileToSave, "response")
|
||||
saveAs(this.props.value, "response.txt")
|
||||
}
|
||||
|
||||
preventYScrollingBeyondElement = (e) => {
|
||||
@@ -45,12 +45,16 @@ export default class HighlightCode extends Component {
|
||||
}
|
||||
|
||||
render () {
|
||||
let { value, className } = this.props
|
||||
let { value, className, downloadable } = this.props
|
||||
className = className || ""
|
||||
|
||||
return (
|
||||
<div className="highlight-code">
|
||||
<div className="download-contents" onClick={this.downloadText}>Download</div>
|
||||
{ !downloadable ? null :
|
||||
<div className="download-contents" onClick={this.downloadText}>
|
||||
Download
|
||||
</div>
|
||||
}
|
||||
<pre
|
||||
ref={this.initializeComponent}
|
||||
onWheel={this.preventYScrollingBeyondElement}
|
||||
|
||||
@@ -197,7 +197,7 @@ export default class ParameterRow extends Component {
|
||||
getConfigs={ getConfigs }
|
||||
isExecute={ isExecute }
|
||||
specSelectors={ specSelectors }
|
||||
schema={ schema }
|
||||
schema={ param.get("schema") }
|
||||
example={ bodyParam }/>
|
||||
: null
|
||||
}
|
||||
|
||||
@@ -5,7 +5,10 @@ import lowerCase from "lodash/lowerCase"
|
||||
import { extractFileNameFromContentDispositionHeader } from "core/utils"
|
||||
import win from "core/window"
|
||||
|
||||
export default class ResponseBody extends React.Component {
|
||||
export default class ResponseBody extends React.PureComponent {
|
||||
state = {
|
||||
parsedContent: null
|
||||
}
|
||||
|
||||
static propTypes = {
|
||||
content: PropTypes.any.isRequired,
|
||||
@@ -15,8 +18,39 @@ export default class ResponseBody extends React.Component {
|
||||
url: PropTypes.string
|
||||
}
|
||||
|
||||
updateParsedContent = (prevContent) => {
|
||||
const { content } = this.props
|
||||
|
||||
if(prevContent === content) {
|
||||
return
|
||||
}
|
||||
|
||||
if(content && content instanceof Blob) {
|
||||
var reader = new FileReader()
|
||||
reader.onload = () => {
|
||||
this.setState({
|
||||
parsedContent: reader.result
|
||||
})
|
||||
}
|
||||
reader.readAsText(content)
|
||||
} else {
|
||||
this.setState({
|
||||
parsedContent: content.toString()
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
componentDidMount() {
|
||||
this.updateParsedContent(null)
|
||||
}
|
||||
|
||||
componentDidUpdate(prevProps) {
|
||||
this.updateParsedContent(prevProps.content)
|
||||
}
|
||||
|
||||
render() {
|
||||
let { content, contentType, url, headers={}, getComponent } = this.props
|
||||
const { parsedContent } = this.state
|
||||
const HighlightCode = getComponent("highlightCode")
|
||||
let body, bodyEl
|
||||
url = url || ""
|
||||
@@ -66,7 +100,7 @@ export default class ResponseBody extends React.Component {
|
||||
body = "can't parse JSON. Raw result:\n\n" + content
|
||||
}
|
||||
|
||||
bodyEl = <HighlightCode value={ body } />
|
||||
bodyEl = <HighlightCode downloadable value={ body } />
|
||||
|
||||
// XML
|
||||
} else if (/xml/i.test(contentType)) {
|
||||
@@ -74,11 +108,11 @@ export default class ResponseBody extends React.Component {
|
||||
textNodesOnSameLine: true,
|
||||
indentor: " "
|
||||
})
|
||||
bodyEl = <HighlightCode value={ body } />
|
||||
bodyEl = <HighlightCode downloadable value={ body } />
|
||||
|
||||
// HTML or Plain Text
|
||||
} else if (lowerCase(contentType) === "text/html" || /text\/plain/.test(contentType)) {
|
||||
bodyEl = <HighlightCode value={ content } />
|
||||
bodyEl = <HighlightCode downloadable value={ content } />
|
||||
|
||||
// Image
|
||||
} else if (/^image\//i.test(contentType)) {
|
||||
@@ -92,10 +126,25 @@ export default class ResponseBody extends React.Component {
|
||||
} else if (/^audio\//i.test(contentType)) {
|
||||
bodyEl = <pre><audio controls><source src={ url } type={ contentType } /></audio></pre>
|
||||
} else if (typeof content === "string") {
|
||||
bodyEl = <HighlightCode value={ content } />
|
||||
bodyEl = <HighlightCode downloadable value={ content } />
|
||||
} else if ( content.size > 0 ) {
|
||||
// We don't know the contentType, but there was some content returned
|
||||
bodyEl = <div>Unknown response type</div>
|
||||
if(parsedContent) {
|
||||
// We were able to squeeze something out of content
|
||||
// in `updateParsedContent`, so let's display it
|
||||
bodyEl = <div>
|
||||
<p className="i">
|
||||
Unrecognized response type; displaying content as text.
|
||||
</p>
|
||||
<HighlightCode downloadable value={ parsedContent } />
|
||||
</div>
|
||||
|
||||
} else {
|
||||
// Give up
|
||||
bodyEl = <p className="i">
|
||||
Unrecognized response type; unable to display.
|
||||
</p>
|
||||
}
|
||||
} else {
|
||||
// We don't know the contentType and there was no content returned
|
||||
bodyEl = null
|
||||
|
||||
@@ -37,12 +37,12 @@ export default class Schemes extends React.Component {
|
||||
}
|
||||
|
||||
render() {
|
||||
let { schemes } = this.props
|
||||
let { schemes, currentScheme } = this.props
|
||||
|
||||
return (
|
||||
<label htmlFor="schemes">
|
||||
<span className="schemes-title">Schemes</span>
|
||||
<select onChange={ this.onChange }>
|
||||
<select onChange={ this.onChange } value={currentScheme}>
|
||||
{ schemes.valueSeq().map(
|
||||
( scheme ) => <option value={ scheme } key={ scheme }>{ scheme }</option>
|
||||
).toArray()}
|
||||
|
||||
@@ -33,7 +33,8 @@ export default class HttpAuth extends React.Component {
|
||||
let { onChange } = this.props
|
||||
let { value, name } = e.target
|
||||
|
||||
let newValue = this.state.value || {}
|
||||
let newValue = Object.assign({}, this.state.value)
|
||||
|
||||
if(name) {
|
||||
newValue[name] = value
|
||||
} else {
|
||||
@@ -53,7 +54,7 @@ export default class HttpAuth extends React.Component {
|
||||
const Markdown = getComponent( "Markdown" )
|
||||
const JumpToPath = getComponent("JumpToPath", true)
|
||||
|
||||
const scheme = schema.get("scheme")
|
||||
const scheme = (schema.get("scheme") || "").toLowerCase()
|
||||
let value = this.getValue()
|
||||
let errors = errSelectors.allErrors().filter( err => err.get("authId") === name)
|
||||
|
||||
@@ -125,7 +126,7 @@ export default class HttpAuth extends React.Component {
|
||||
)
|
||||
}
|
||||
return <div>
|
||||
<em><b>{name}</b> HTTP authentication: unsupported or missing scheme</em>
|
||||
<em><b>{name}</b> HTTP authentication: unsupported scheme {`'${scheme}'`}</em>
|
||||
</div>
|
||||
}
|
||||
}
|
||||
|
||||
@@ -632,6 +632,7 @@
|
||||
> .microlight {
|
||||
overflow-y: auto;
|
||||
max-height: 400px;
|
||||
min-height: 6em;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -0,0 +1,44 @@
|
||||
describe("bug #4196: HTTP basic auth credential retention", function () {
|
||||
let mainPage
|
||||
beforeEach(function (client, done) {
|
||||
mainPage = client
|
||||
.url("localhost:3230")
|
||||
.page.main()
|
||||
|
||||
client.waitForElementVisible(".download-url-input", 5000)
|
||||
.pause(80)
|
||||
.clearValue(".download-url-input")
|
||||
.setValue(".download-url-input", "http://localhost:3230/test-specs/bugs/4196.yaml")
|
||||
.click("button.download-url-button")
|
||||
.pause(1000)
|
||||
|
||||
done()
|
||||
})
|
||||
afterEach(function (client, done) {
|
||||
done()
|
||||
})
|
||||
it("should display the most recent auth data across modal close/opens", function (client) {
|
||||
client.waitForElementVisible(".opblock-tag-section", 10000)
|
||||
.click("button.btn.authorize") // Open modal
|
||||
.waitForElementVisible("section>input", 5000)
|
||||
.setValue("section>input", "aaa") // Set user
|
||||
.waitForElementVisible(`section>input[type="password"]`, 5000)
|
||||
.setValue(`section>input[type="password"]`, "aaa") // Set password
|
||||
.click(".auth-btn-wrapper button:nth-child(1)") // Click Authorize
|
||||
.assert.containsText("div.wrapper:nth-child(4)>code", "aaa")
|
||||
.click(".auth-btn-wrapper button:nth-child(2)") // Close modal
|
||||
.pause(50)
|
||||
.click("button.btn.authorize") // Open modal
|
||||
.pause(50)
|
||||
.click(".auth-btn-wrapper button:nth-child(1)") // Logout
|
||||
.waitForElementVisible("section>input", 5000)
|
||||
.setValue("section>input", "bbb") // Set user
|
||||
.waitForElementVisible(`section>input[type="password"]`, 5000)
|
||||
.setValue(`section>input[type="password"]`, "bbb") // Set password
|
||||
.click(".auth-btn-wrapper button:nth-child(1)") // Click Authorize
|
||||
.pause(5000)
|
||||
.assert.containsText("div.wrapper:nth-child(4)>code", "bbb")
|
||||
|
||||
client.end()
|
||||
})
|
||||
})
|
||||
@@ -71,6 +71,16 @@ describe("render pet api container", function () {
|
||||
client.end()
|
||||
})
|
||||
|
||||
it("Testing post /pet api model values", function (client) {
|
||||
apiWrapper.waitForElementVisible("@petOperationPostContainer", 5000)
|
||||
.click("@petOperationPostCollpase")
|
||||
.waitForElementVisible("@petOperationPostCollapseContainer", 5000)
|
||||
.click("a.tablinks[data-name=model]")
|
||||
.assert.containsText("span.model-title > .model-title__text", `Pet`)
|
||||
|
||||
client.end()
|
||||
})
|
||||
|
||||
it("render put /pet api container", function (client) {
|
||||
apiWrapper.waitForElementVisible("@petOperationPutContainer", 5000)
|
||||
.assert.containsText("@petOperationPutTitle", "/pet")
|
||||
@@ -81,10 +91,10 @@ describe("render pet api container", function () {
|
||||
.waitForElementVisible("@petOperationPutExecuteBtn", 1000)
|
||||
.click("@petOperationPutTryBtn")
|
||||
.assert.cssClassNotPresent("@petOperationPutTryBtn", "cancel")
|
||||
|
||||
|
||||
client.end()
|
||||
})
|
||||
|
||||
|
||||
it("Testing put /pet api Mock data", function (client) {
|
||||
apiWrapper.waitForElementVisible("@petOperationPutContainer", 5000)
|
||||
.click("@petOperationPutCollpase")
|
||||
@@ -115,7 +125,7 @@ describe("render pet api container", function () {
|
||||
.waitForElementVisible("@petOperationGetByTagExecuteBtn", 1000)
|
||||
.click("@petOperationGetByTagTryBtn")
|
||||
.assert.cssClassNotPresent("@petOperationGetByTagTryBtn", "cancel")
|
||||
|
||||
|
||||
client.end()
|
||||
})
|
||||
|
||||
@@ -138,7 +148,7 @@ 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}")
|
||||
@@ -148,7 +158,7 @@ describe("render pet api container", function () {
|
||||
.waitForElementVisible("@petOperationGetByTagExecuteBtn", 1000)
|
||||
.click("@petOperationGetByTagTryBtn")
|
||||
.assert.cssClassNotPresent("@petOperationGetByTagTryBtn", "cancel")
|
||||
|
||||
|
||||
client.end()
|
||||
})
|
||||
|
||||
@@ -167,7 +177,7 @@ describe("render pet api container", function () {
|
||||
.assert.attributeEquals("@petOperationGetByIdParameter", "title", "Value must be an integer")
|
||||
.click("@petOperationGetByTagTryBtn")
|
||||
.assert.cssClassNotPresent("@petOperationGetByTagTryBtn", "cancel")
|
||||
|
||||
|
||||
client.end()
|
||||
})
|
||||
|
||||
@@ -180,10 +190,10 @@ describe("render pet api container", function () {
|
||||
.waitForElementVisible("@petOperationDeleteExecuteBtn", 1000)
|
||||
.click("@petOperationDeleteTryBtn")
|
||||
.assert.cssClassNotPresent("@petOperationDeleteTryBtn", "cancel")
|
||||
|
||||
|
||||
client.end()
|
||||
})
|
||||
|
||||
|
||||
it("Testing delete /pet api Mock data", function (client) {
|
||||
apiWrapper.waitForElementVisible("@petOperationDeleteContainer", 3000)
|
||||
.click("@petOperationDeleteCollpase")
|
||||
@@ -203,4 +213,4 @@ describe("render pet api container", function () {
|
||||
|
||||
client.end()
|
||||
})
|
||||
})
|
||||
})
|
||||
|
||||
@@ -0,0 +1,85 @@
|
||||
openapi: 3.0.0
|
||||
info:
|
||||
title: Demo API
|
||||
description: First test
|
||||
termsOfService: 'http://demo.io/terms-of-service/'
|
||||
contact:
|
||||
name: Demo Support
|
||||
email: support@demo.io
|
||||
version: 1.0.0
|
||||
servers:
|
||||
- url: '{server}/v1'
|
||||
variables:
|
||||
server:
|
||||
default: https://api.demo.io
|
||||
description: the API endpoint
|
||||
|
||||
paths:
|
||||
/session:
|
||||
put:
|
||||
summary: Returns a new authentication token
|
||||
tags:
|
||||
- session
|
||||
security:
|
||||
- basicAuth: []
|
||||
responses:
|
||||
'201':
|
||||
description: A session object
|
||||
content:
|
||||
application/json:
|
||||
schema:
|
||||
allOf:
|
||||
- type: object
|
||||
properties:
|
||||
user_id:
|
||||
type: string
|
||||
format: uuid
|
||||
readOnly: true
|
||||
example: 110e8400-e29b-11d4-a716-446655440000
|
||||
- $ref: '#/components/schemas/Session'
|
||||
'401':
|
||||
$ref: '#/components/responses/Unauthorized'
|
||||
|
||||
components:
|
||||
securitySchemes:
|
||||
basicAuth:
|
||||
type: http
|
||||
scheme: basic
|
||||
bearerAuth:
|
||||
type: http
|
||||
scheme: bearer
|
||||
bearerFormat: JWT
|
||||
schemas:
|
||||
Session:
|
||||
required:
|
||||
- token
|
||||
properties:
|
||||
token:
|
||||
type: string
|
||||
readOnly: true
|
||||
example: >-
|
||||
eyJhbGciOiJSUzI1NiIsInR5cCI6IkpXVCJ9.eyJzdWIiOiIxMjM0NTY3ODkwIiwibmFtZSI6IkpvaG4gRG9lIiwiYWRtaW4iOnRydWV9.EkN-DOsnsuRjRO6BxXemmJDm3HbxrbRzXglbN2S4sOkopdU4IsDxTI8jO19W_A4K8ZPJijNLis4EZsHeY559a4DFOd50_OqgHGuERTqYZyuhtF39yxJPAjUESwxk2J5k_4zM3O-vtd1Ghyo4IbqKKSy6J9mTniYJPenn5-HIirE
|
||||
|
||||
Error:
|
||||
required:
|
||||
- message
|
||||
properties:
|
||||
message:
|
||||
description: a human readable message explaining the error
|
||||
type: string
|
||||
reason:
|
||||
description: a functionnal key about the error
|
||||
type: string
|
||||
responses:
|
||||
Unauthorized:
|
||||
description: Not authenticated
|
||||
content:
|
||||
application/json:
|
||||
schema:
|
||||
$ref: '#/components/schemas/Error'
|
||||
Default:
|
||||
description: unexpected error
|
||||
content:
|
||||
application/json:
|
||||
schema:
|
||||
$ref: '#/components/schemas/Error'
|
||||
Reference in New Issue
Block a user