Compare commits

..
4 Commits
36 changed files with 215 additions and 595 deletions
-1
View File
@@ -6,7 +6,6 @@
],
"plugins": [
"transform-runtime",
"babel-plugin-transform-es2015-constants",
[
"module-alias",
[
-72
View File
@@ -1,72 +0,0 @@
---
name: Bug report
about: Report an issue you're experiencing
---
<!---
Thanks for filing a bug report 😄 ! Before you submit, please read the following:
If you're here to report a security issue, please STOP writing an issue and
contact us at security@swagger.io instead!
Search open/closed issues before submitting!
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/OpenAPIspecifications themselves,
or anything that violates the specifications.
-->
## Q&A (please complete the following information)
- OS: [e.g. macOS]
- Browser: [e.g. chrome, safari]
- Version: [e.g. 22]
- Method of installation: [e.g. npm, dist assets]
- Swagger-UI version: [e.g. 3.10.0]
- Swagger/OpenAPI version: [e.g. Swagger 2.0, OpenAPI 3.0]
### Content & configuration
<!--
Provide us with a way to see what you're seeing,
so that we can fix your issue.
-->
Example Swagger/OpenAPI definition:
```yaml
# your YAML here
```
Swagger-UI configuration options:
```js
SwaggerUI({
// your config options here
})
```
```
?yourQueryStringConfig
```
### Describe the bug you're encountering
<!-- A clear and concise description of what the bug is. -->
### To reproduce...
Steps to reproduce the behavior:
1. Go to '...'
2. Click on '....'
3. Scroll down to '....'
4. See error
### Expected behavior
<!-- A clear and concise description of what you expected to happen. -->
### Screenshots
<!-- If applicable, add screenshots to help explain your problem. -->
### Additional context or thoughts
<!-- Add any other context about the problem here. -->
-50
View File
@@ -1,50 +0,0 @@
---
name: Feature request
about: Suggest an new feature or enhancement for this project
---
## Q&A (please complete the following information)
- OS: [e.g. macOS]
- Browser: [e.g. chrome, safari]
- Version: [e.g. 22]
- Method of installation: [e.g. npm, dist assets]
- Swagger-UI version: [e.g. 3.10.0]
- Swagger/OpenAPI version: [e.g. Swagger 2.0, OpenAPI 3.0]
### Content & configuration
Swagger/OpenAPI definition:
```yaml
# your YAML here
```
Swagger-UI configuration options:
```js
SwaggerUI({
// your config options here
})
```
```
?yourQueryStringConfig
```
### Is your feature request related to a problem?
<!--
Please provide a clear and concise description of what the problem is.
"I'm always frustrated when..."
-->
### Describe the solution you'd like
<!-- A clear and concise description of what you want to happen. -->
### Describe alternatives you've considered
<!--
A clear and concise description of any alternative solutions or features
you've considered.
-->
### Additional context
<!-- Add any other context or screenshots about the feature request here. -->
-46
View File
@@ -1,46 +0,0 @@
---
name: Support
about: Ask a question or request help with your implementation.
---
<!--
We can only offer support for Swagger-UI itself.
If you're having a problem with a library that uses Swagger-UI
(for example, Springfox or swagger-node), please open an issue
in that project's repository instead.
-->
### Q&A (please complete the following information)
- OS: [e.g. macOS]
- Browser: [e.g. chrome, safari]
- Version: [e.g. 22]
- Method of installation: [e.g. npm, dist assets]
- Swagger-UI version: [e.g. 3.10.0]
- Swagger/OpenAPI version: [e.g. Swagger 2.0, OpenAPI 3.0]
### Content & configuration
<!-- Provide us with a way to see what you're seeing, so that we can help. -->
Swagger/OpenAPI definition:
```yaml
# your YAML here
```
Swagger-UI configuration options:
```js
SwaggerUI({
// your config options here
})
```
```
?yourQueryStringConfig
```
### Screenshots
<!-- If applicable, add screenshots to help give context to your problem. -->
### How can we help?
<!-- Your question or problem goes here! -->
+70
View File
@@ -0,0 +1,70 @@
<!---
Thanks for filing an issue 😄 ! Before you submit, please read the following:
If you're here to report a security issue, please STOP writing an issue and contact us
at security@swagger.io instead!
Search open/closed issues before submitting since someone might have asked the same thing before!
Issues on GitHub are only related to problems of Swagger-UI itself. We'll try to offer support
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 features or bugs in the Swagger/OpenAPI specifications themselves,
or anything that violates the specifications.
-->
<!--- Provide a general summary of the issue in the title above -->
<!---
If you aren't sure what Swagger-UI version, see this guide: https://github.com/swagger-api/swagger-ui/blob/master/docs/usage/version-detection.md
--->
| Q | A
| ------------------------------- | -------
| Bug or feature request? |
| Which Swagger/OpenAPI version? |
| Which Swagger-UI version? |
| How did you install Swagger-UI? |
| Which browser & version? |
| Which operating system? |
### Demonstration API definition
<!--- If you're describing a bug, please provide an API definition that reproduces your problem -->
<!--- If you have link to a demo repo please link that! -->
<!--- If your spec is large, please put it into a Gist (https://gist.github.com) instead of pasting it here. -->
```yaml
your: "API definition goes here"
```
### Configuration (browser query string, constructor, config.yaml)
<!--- If describing a bug, tell us what your configuration looks like -->
```js
{
"your": { "constructorConfig": "here" }
}
```
`?yourQueryStringConfig=here`
### Expected Behavior
<!--- If you're describing a bug, tell us what should happen -->
<!--- If you're suggesting a change/improvement, tell us how it should work -->
### Current Behavior
<!--- If describing a bug, tell us what happens instead of the expected behavior -->
<!--- If suggesting a change/improvement, explain the difference from current behavior -->
### Possible Solution
<!--- Not obligatory, but suggest a fix/reason for the bug, -->
<!--- or ideas how to implement the addition or change -->
### Context
<!--- How has this issue affected you? What are you trying to accomplish? -->
<!--- Providing context helps us come up with a solution that is most useful in the real world -->
+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.1 | 2018-05-04 | 2.0, 3.0 | [tag v3.14.1](https://github.com/swagger-api/swagger-ui/tree/v3.14.1)
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)
+33 -71
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
+2 -3
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
+10 -10
View File
@@ -68,7 +68,7 @@ There is no dependency management built into the plugin system, so if you create
### Interfaces
#### Actions
##### Actions
```javascript
const MyActionPlugin = () => {
@@ -102,7 +102,7 @@ This action creator function will be exposed to container components as `example
For more information about the concept of actions in Redux, see the [Redux Actions documentation](http://redux.js.org/docs/basics/Actions.html).
#### Reducers
##### Reducers
Reducers take a state (which is an [Immutable.js map](https://facebook.github.io/immutable-js/docs/#/Map)) and an action, and return a new state.
@@ -126,7 +126,7 @@ const MyReducerPlugin = function(system) {
}
```
#### Selectors
##### Selectors
Selectors reach into their namespace's state to retrieve or derive data from the state.
@@ -172,7 +172,7 @@ Once a selector has been defined, you can use it anywhere that you can get a sys
system.exampleSelectors.myFavoriteColor() // gets `favColor` in state for you
```
#### Components
##### Components
You can provide a map of components to be integrated into the system.
@@ -214,7 +214,7 @@ const NeverShowInfoPlugin = function(system) {
}
```
#### Wrap-Actions
##### Wrap-Actions
Wrap Actions allow you to override the behavior of an action in the system.
@@ -262,7 +262,7 @@ const MyWrapActionPlugin = function(system) {
}
```
#### Wrap-Selectors
##### Wrap-Selectors
Wrap Selectors allow you to override the behavior of a selector in the system.
@@ -307,7 +307,7 @@ const MyWrapSelectorsPlugin = function(system) {
}
```
#### Wrap-Components
##### Wrap-Components
Wrap Components allow you to override a component registered within the system.
@@ -381,7 +381,7 @@ const MyWrapComponentPlugin = function(system) {
}
```
#### `rootInjects`
##### `rootInjects`
The `rootInjects` interface allows you to inject values at the top level of the system.
@@ -398,7 +398,7 @@ const MyRootInjectsPlugin = function(system) {
}
```
#### `afterLoad`
##### `afterLoad`
The `afterLoad` plugin method allows you to get a reference to the system after your plugin has been registered.
@@ -431,7 +431,7 @@ const MyMethodProvidingPlugin = function() {
}
```
#### fn
##### fn
The fn interface allows you to add helper functions to the system for use elsewhere.
-1
View File
@@ -58,7 +58,6 @@ Parameter Name | Description
`maxDisplayedTags` | `Number`. If set, limits the number of tagged operations displayed to at most this many. The default is to show all operations.
`operationsSorter` | `Function=(a => a)`. Apply a sort to the operation list of each API. It can be 'alpha' (sort by paths alphanumerically), 'method' (sort by HTTP method) or a function (see Array.prototype.sort() to know how sort function works). Default is the order returned by the server unchanged.
`showExtensions` | `Boolean=false`. Controls the display of vendor extension (`x-`) fields and values for Operations, Parameters, and Schema.
`showCommonExtensions` | `Boolean=false`. Controls the display of extensions (`pattern`, `maxLength`, `minLength`, `maximum`, `minimum`) fields and values for Parameters.
`tagsSorter` | `Function=(a => a)`. Apply a sort to the tag list of each API. It can be 'alpha' (sort by paths alphanumerically) or a function (see [Array.prototype.sort()](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/sort) to learn how to write a sort function). Two tag name strings are passed to the sorter for each pass. Default is the order determined by Swagger-UI.
`onComplete` | `Function=NOOP`. Provides a mechanism to be notified when Swagger-UI has finished rendering a newly provided definition.
+10 -14
View File
@@ -1,11 +1,10 @@
var path = require("path")
var webpack = require("webpack")
var ExtractTextPlugin = require("extract-text-webpack-plugin")
const CopyWebpackPlugin = require("copy-webpack-plugin")
const UglifyJsPlugin = require("uglifyjs-webpack-plugin")
var deepExtend = require("deep-extend")
const {gitDescribeSync} = require("git-describe")
var webpack = require('webpack')
var ExtractTextPlugin = require('extract-text-webpack-plugin')
const CopyWebpackPlugin = require('copy-webpack-plugin')
var deepExtend = require('deep-extend')
const {gitDescribeSync} = require('git-describe')
const os = require("os")
var pkg = require("./package.json")
@@ -29,10 +28,7 @@ var commonRules = [
retainLines: true
}
}],
include: [
path.join(__dirname, "src"),
path.join(__dirname, "node_modules", "object-assign-deep"),
]
include: [ path.join(__dirname, "src") ]
},
{ test: /\.(txt|yaml)(\?.*)?$/,
loader: "raw-loader" },
@@ -65,10 +61,10 @@ module.exports = function(rules, options) {
}))
}
if( specialOptions.minimize ) { // production mode
if( specialOptions.minimize ) { // production mode
plugins.push(
new UglifyJsPlugin({
new webpack.optimize.UglifyJsPlugin({
sourceMap: true,
}),
new webpack.LoaderOptionsPlugin({
@@ -80,8 +76,8 @@ module.exports = function(rules, options) {
plugins.push( new webpack.NoEmitOnErrorsPlugin())
} else { // development mode
plugins.push(new CopyWebpackPlugin([ { from: "test/e2e/specs", to: "test-specs" } ]))
} else { // development mode
plugins.push(new CopyWebpackPlugin([ { from: 'test/e2e/specs', to: 'test-specs' } ]))
}
plugins.push(
+4 -7
View File
@@ -1,6 +1,6 @@
{
"name": "swagger-ui",
"version": "3.14.1",
"version": "3.13.4",
"main": "dist/swagger-ui.js",
"repository": "git@github.com:swagger-api/swagger-ui.git",
"contributors": [
@@ -31,7 +31,7 @@
"test": "npm run lint-errors && npm run just-test-in-node",
"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",
"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",
@@ -48,7 +48,6 @@
"core-js": "^2.5.1",
"css.escape": "1.5.1",
"deep-extend": "0.4.1",
"dompurify": "^1.0.4",
"expect": "1.20.2",
"getbase": "^2.8.2",
"ieee754": "^1.1.8",
@@ -81,10 +80,11 @@
"redux-logger": "*",
"remarkable": "^1.7.1",
"reselect": "2.5.3",
"sanitize-html": "^1.14.1",
"scroll-to-element": "^2.0.0",
"serialize-error": "2.0.0",
"shallowequal": "0.2.2",
"swagger-client": "^3.8.1",
"swagger-client": "^3.7.0",
"url-parse": "^1.1.8",
"whatwg-fetch": "0.11.1",
"worker-loader": "^0.7.1",
@@ -99,7 +99,6 @@
"babel-eslint": "^7.1.1",
"babel-loader": "^7.1.0",
"babel-plugin-module-alias": "^1.6.0",
"babel-plugin-transform-es2015-constants": "^6.1.4",
"babel-plugin-transform-runtime": "^6.23.0",
"babel-preset-es2015": "^6.22.0",
"babel-preset-es2015-ie": "^6.6.2",
@@ -120,7 +119,6 @@
"file-loader": "0.11.2",
"git-describe": "^4.0.1",
"imports-loader": "0.7.1",
"jsdom": "^11.10.0",
"json-loader": "0.5.4",
"json-server": "^0.11.0",
"karma": "^1.7.0",
@@ -148,7 +146,6 @@
"standard-loader": "^6.0.1",
"style-loader": "0.18.2",
"tachyons-sass": "^4.9.2",
"uglifyjs-webpack-plugin": "^1.2.5",
"url-loader": "0.5.9",
"webpack": "^2.6.1",
"webpack-bundle-size-analyzer": "^2.5.0"
+3 -5
View File
@@ -7,8 +7,7 @@ export default class HighlightCode extends Component {
static propTypes = {
value: PropTypes.string.isRequired,
className: PropTypes.string,
downloadable: PropTypes.bool,
fileName: PropTypes.string
downloadable: PropTypes.bool
}
componentDidMount() {
@@ -24,7 +23,7 @@ export default class HighlightCode extends Component {
}
downloadText = () => {
saveAs(this.props.value, this.props.fileName || "response.txt")
saveAs(this.props.value, "response.txt")
}
preventYScrollingBeyondElement = (e) => {
@@ -37,11 +36,10 @@ export default class HighlightCode extends Component {
const scrollOffset = visibleHeight + scrollTop
const isElementScrollable = contentHeight > visibleHeight
const isScrollingPastTop = scrollTop === 0 && deltaY < 0
const isScrollingPastBottom = scrollOffset >= contentHeight && deltaY > 0
if (isElementScrollable && (isScrollingPastTop || isScrollingPastBottom)) {
if (isScrollingPastTop || isScrollingPastBottom) {
e.preventDefault()
}
}
+5 -12
View File
@@ -3,7 +3,7 @@ import { Map } from "immutable"
import PropTypes from "prop-types"
import ImPropTypes from "react-immutable-proptypes"
import win from "core/window"
import { getExtensions, getCommonExtensions } from "core/utils"
import { getExtensions } from "core/utils"
export default class ParameterRow extends Component {
static propTypes = {
@@ -82,7 +82,7 @@ export default class ParameterRow extends Component {
let { isOAS3 } = specSelectors
const { showExtensions, showCommonExtensions } = getConfigs()
const { showExtensions } = getConfigs()
// const onChangeWrapper = (value) => onChange(param, value)
const JsonSchemaForm = getComponent("JsonSchemaForm")
@@ -106,17 +106,15 @@ export default class ParameterRow extends Component {
const ParameterExt = getComponent("ParameterExt")
let paramWithMeta = specSelectors.parameterWithMeta(pathMethod, param.get("name"), param.get("in"))
let format = param.get("format")
let schema = isOAS3 && isOAS3() ? param.get("schema") : param
let type = schema.get("type")
let isFormData = inType === "formData"
let isFormDataSupported = "FormData" in win
let required = param.get("required")
let itemType = schema.getIn(["items", "type"])
let value = paramWithMeta ? paramWithMeta.get("value") : ""
let commonExt = showCommonExtensions ? getCommonExtensions(param) : null
let extensions = showExtensions ? getExtensions(param) : null
let extensions = getExtensions(param)
let paramItems // undefined
let paramEnum // undefined
@@ -155,16 +153,11 @@ export default class ParameterRow extends Component {
{ param.get("name") }
{ !required ? null : <span style={{color: "red"}}>&nbsp;*</span> }
</div>
<div className="parameter__type">
{ type }
{ itemType && `[${itemType}]` }
{ format && <span className="prop-format">(${format})</span>}
</div>
<div className="parameter__type">{ type } { itemType && `[${itemType}]` }</div>
<div className="parameter__deprecated">
{ isOAS3 && isOAS3() && param.get("deprecated") ? "deprecated": null }
</div>
<div className="parameter__in">({ param.get("in") })</div>
{ !showCommonExtensions || !commonExt.size ? null : commonExt.map((v, key) => <ParameterExt key={`${key}-${v}`} xKey={key} xVal={v} /> )}
{ !showExtensions || !extensions.size ? null : extensions.map((v, key) => <ParameterExt key={`${key}-${v}`} xKey={key} xVal={v} /> )}
</td>
+17 -5
View File
@@ -1,7 +1,7 @@
import React from "react"
import PropTypes from "prop-types"
import Remarkable from "remarkable"
import DomPurify from "dompurify"
import sanitize from "sanitize-html"
import cx from "classnames"
// eslint-disable-next-line no-useless-escape
@@ -35,13 +35,25 @@ function Markdown({ source, className = "" }) {
Markdown.propTypes = {
source: PropTypes.string.isRequired,
className: PropTypes.string
className: PropTypes.string.isRequired
}
export default Markdown
const sanitizeOptions = {
allowedTags: sanitize.defaults.allowedTags.concat([ "h1", "h2", "img", "span" ]),
allowedAttributes: {
...sanitize.defaults.allowedAttributes,
"img": sanitize.defaults.allowedAttributes.img.concat(["title"]),
"td": [ "colspan" ],
"*": [ "class" ]
},
allowedSchemesByTag: { img: [ "http", "https", "data" ] },
textFilter: function(text) {
return text.replace(/&quot;/g, "\"")
}
}
export function sanitizer(str) {
return DomPurify.sanitize(str, {
ADD_ATTR: ["target"]
})
return sanitize(str, sanitizeOptions)
}
+5 -6
View File
@@ -52,7 +52,6 @@ export default class ResponseBody extends React.PureComponent {
let { content, contentType, url, headers={}, getComponent } = this.props
const { parsedContent } = this.state
const HighlightCode = getComponent("highlightCode")
const downloadName = "response_" + new Date().getTime()
let body, bodyEl
url = url || ""
@@ -101,7 +100,7 @@ export default class ResponseBody extends React.PureComponent {
body = "can't parse JSON. Raw result:\n\n" + content
}
bodyEl = <HighlightCode downloadable fileName={`${downloadName}.json`} value={ body } />
bodyEl = <HighlightCode downloadable value={ body } />
// XML
} else if (/xml/i.test(contentType)) {
@@ -109,11 +108,11 @@ export default class ResponseBody extends React.PureComponent {
textNodesOnSameLine: true,
indentor: " "
})
bodyEl = <HighlightCode downloadable fileName={`${downloadName}.xml`} value={ body } />
bodyEl = <HighlightCode downloadable value={ body } />
// HTML or Plain Text
} else if (lowerCase(contentType) === "text/html" || /text\/plain/.test(contentType)) {
bodyEl = <HighlightCode downloadable fileName={`${downloadName}.html`} value={ content } />
bodyEl = <HighlightCode downloadable value={ content } />
// Image
} else if (/^image\//i.test(contentType)) {
@@ -127,7 +126,7 @@ export default class ResponseBody extends React.PureComponent {
} else if (/^audio\//i.test(contentType)) {
bodyEl = <pre><audio controls><source src={ url } type={ contentType } /></audio></pre>
} else if (typeof content === "string") {
bodyEl = <HighlightCode downloadable fileName={`${downloadName}.txt`} value={ content } />
bodyEl = <HighlightCode downloadable value={ content } />
} else if ( content.size > 0 ) {
// We don't know the contentType, but there was some content returned
if(parsedContent) {
@@ -137,7 +136,7 @@ export default class ResponseBody extends React.PureComponent {
<p className="i">
Unrecognized response type; displaying content as text.
</p>
<HighlightCode downloadable fileName={`${downloadName}.txt`} value={ parsedContent } />
<HighlightCode downloadable value={ parsedContent } />
</div>
} else {
+1 -7
View File
@@ -49,7 +49,6 @@ module.exports = function SwaggerUI(opts) {
defaultModelExpandDepth: 1,
defaultModelsExpandDepth: 1,
showExtensions: false,
showCommonExtensions: false,
supportedSubmitMethods: [
"get",
"put",
@@ -173,12 +172,7 @@ module.exports = function SwaggerUI(opts) {
let configUrl = queryConfig.config || constructorConfig.configUrl
if (!configUrl || !system.specActions.getConfigByUrl || system.specActions.getConfigByUrl && !system.specActions.getConfigByUrl({
url: configUrl,
loadRemoteConfig: true,
requestInterceptor: constructorConfig.requestInterceptor,
responseInterceptor: constructorConfig.responseInterceptor,
}, downloadSpec)) {
if (!configUrl || !system.specActions.getConfigByUrl || system.specActions.getConfigByUrl && !system.specActions.getConfigByUrl(configUrl, downloadSpec)) {
return downloadSpec()
}
-12
View File
@@ -1,12 +0,0 @@
import YAML from "js-yaml"
export const parseYamlConfig = (yaml, system) => {
try {
return YAML.safeLoad(yaml)
} catch(e) {
if (system) {
system.errActions.newThrownErr( new Error(e) )
}
return {}
}
}
+38 -2
View File
@@ -1,10 +1,46 @@
import YAML from "js-yaml"
import yamlConfig from "root/swagger-config.yaml"
import { parseYamlConfig } from "./helpers"
import * as actions from "./actions"
import * as specActions from "./spec-actions"
import * as selectors from "./selectors"
import reducers from "./reducers"
const parseYamlConfig = (yaml, system) => {
try {
return YAML.safeLoad(yaml)
} catch(e) {
if (system) {
system.errActions.newThrownErr( new Error(e) )
}
return {}
}
}
const specActions = {
downloadConfig: (url) => ({fn}) => {
let {fetch} = fn
return fetch(url)
},
getConfigByUrl: (configUrl, cb)=> ({ specActions }) => {
if (configUrl) {
return specActions.downloadConfig(configUrl).then(next, next)
}
function next(res) {
if (res instanceof Error || res.status >= 400) {
specActions.updateLoadingStatus("failedConfig")
specActions.updateLoadingStatus("failedConfig")
specActions.updateUrl("")
console.error(res.statusText + " " + configUrl)
cb(null)
} else {
cb(parseYamlConfig(res.text))
}
}
}
}
const specSelectors = {
getLocalConfig: () => {
return parseYamlConfig(yamlConfig)
-25
View File
@@ -1,25 +0,0 @@
import { parseYamlConfig } from "./helpers"
export const downloadConfig = (req) => (system) => {
const {fn: { fetch }} = system
return fetch(req)
}
export const getConfigByUrl = (req, cb)=> ({ specActions }) => {
if (req) {
return specActions.downloadConfig(req).then(next, next)
}
function next(res) {
if (res instanceof Error || res.status >= 400) {
specActions.updateLoadingStatus("failedConfig")
specActions.updateLoadingStatus("failedConfig")
specActions.updateUrl("")
console.error(res.statusText + " " + req.url)
cb(null)
} else {
cb(parseYamlConfig(res.text))
}
}
}
@@ -16,14 +16,8 @@ const Callbacks = (props) => {
return <div key={callbackName}>
<h2>{callbackName}</h2>
{ callback.map((pathItem, pathItemName) => {
if(pathItemName === "$$ref") {
return null
}
return <div key={pathItemName}>
{ pathItem.map((operation, method) => {
if(method === "$$ref") {
return null
}
let op = fromJS({
operation
})
+1 -5
View File
@@ -118,11 +118,7 @@ export default {
let operationPath = ["paths", ...path]
let metaPath = ["meta", "paths", ...path]
if(
!state.getIn(["json", ...operationPath])
&& !state.getIn(["resolved", ...operationPath])
&& !state.getIn(["resolvedSubtrees", ...operationPath])
) {
if(!state.getIn(["json", ...operationPath]) && !state.getIn(["resolved", ...operationPath])) {
// do nothing if the operation does not exist
return state
}
-1
View File
@@ -712,7 +712,6 @@ export const createDeepLinkPath = (str) => typeof str == "string" || str instanc
export const escapeDeepLinkPath = (str) => cssEscape( createDeepLinkPath(str) )
export const getExtensions = (defObj) => defObj.filter((v, k) => /^x-/.test(k))
export const getCommonExtensions = (defObj) => defObj.filter((v, k) => /^pattern|maxLength|minLength|maximum|minimum/.test(k))
// Deeply strips a specific key from an object.
//
+7 -7
View File
@@ -16,19 +16,19 @@ describe("Markdown component", function() {
it("allows td elements with colspan attrib", function() {
const str = `<table><tr><td>ABC</td></tr></table>`
const el = render(<Markdown source={str} />)
expect(el.html()).toEqual(`<div class="markdown"><table><tbody><tr><td>ABC</td></tr></tbody></table></div>`)
expect(el.html()).toEqual(`<div class="markdown"><table><tr><td>ABC</td></tr></table></div>`)
})
it("allows image elements", function() {
const str = `![Image alt text](http://image.source "Image title")`
const el = render(<Markdown source={str} />)
expect(el.html()).toEqual(`<div class="markdown"><p><img title="Image title" alt="Image alt text" src="http://image.source"></p>\n</div>`)
expect(el.html()).toEqual(`<div class="markdown"><p><img src="http://image.source" title="Image title"></p>\n</div>`)
})
it("allows image elements with https scheme", function() {
const str = `![Image alt text](https://image.source "Image title")`
const el = render(<Markdown source={str} />)
expect(el.html()).toEqual(`<div class="markdown"><p><img title="Image title" alt="Image alt text" src="https://image.source"></p>\n</div>`)
expect(el.html()).toEqual(`<div class="markdown"><p><img src="https://image.source" title="Image title"></p>\n</div>`)
})
it("allows image elements with data scheme", function() {
@@ -52,7 +52,7 @@ describe("Markdown component", function() {
it("allows links", function() {
const str = `[Link](https://example.com/)`
const el = render(<Markdown source={str} />)
expect(el.html()).toEqual(`<div class="markdown"><p><a target="_blank" href="https://example.com/">Link</a></p>\n</div>`)
expect(el.html()).toEqual(`<div class="markdown"><p><a href="https://example.com/" target="_blank">Link</a></p>\n</div>`)
})
})
@@ -60,13 +60,13 @@ describe("Markdown component", function() {
it("allows image elements", function() {
const str = `![Image alt text](http://image.source "Image title")`
const el = render(<OAS3Markdown source={str} />)
expect(el.html()).toEqual(`<div class="renderedMarkdown"><div><p><img title="Image title" alt="Image alt text" src="http://image.source"></p></div></div>`)
expect(el.html()).toEqual(`<div class="renderedMarkdown"><div><p><img src="http://image.source" title="Image title"></p></div></div>`)
})
it("allows image elements with https scheme", function() {
const str = `![Image alt text](https://image.source "Image title")`
const el = render(<OAS3Markdown source={str} />)
expect(el.html()).toEqual(`<div class="renderedMarkdown"><div><p><img title="Image title" alt="Image alt text" src="https://image.source"></p></div></div>`)
expect(el.html()).toEqual(`<div class="renderedMarkdown"><div><p><img src="https://image.source" title="Image title"></p></div></div>`)
})
it("allows image elements with data scheme", function() {
-27
View File
@@ -1,27 +0,0 @@
/* eslint-env mocha */
import expect, { createSpy } from "expect"
import { downloadConfig } from "corePlugins/configs/spec-actions"
describe("configs plugin - actions", () => {
describe("downloadConfig", () => {
it("should call the system fetch helper with a provided request", () => {
const fetchSpy = createSpy(async () => {}).andCallThrough()
const system = {
fn: {
fetch: fetchSpy
}
}
const req = {
url: "http://swagger.io/one",
requestInterceptor: a => a,
responseInterceptor: a => a,
}
downloadConfig(req)(system)
expect(fetchSpy).toHaveBeenCalledWith(req)
})
})
})
+1 -21
View File
@@ -1,6 +1,6 @@
/* eslint-env mocha */
import expect from "expect"
import { Map, fromJS, OrderedMap } from "immutable"
import { fromJS, OrderedMap } from "immutable"
import {
mapToList,
parseSearch,
@@ -20,8 +20,6 @@ import {
getAcceptControllingResponse,
createDeepLinkPath,
escapeDeepLinkPath,
getExtensions,
getCommonExtensions,
sanitizeUrl,
extractFileNameFromContentDispositionHeader,
deeplyStripKey
@@ -945,24 +943,6 @@ describe("utils", function() {
})
})
describe("getExtensions", function() {
const objTest = Map([[ "x-test", "a"], ["minimum", "b"]])
it("does not error on empty array", function() {
const result1 = getExtensions([])
expect(result1).toEqual([])
const result2 = getCommonExtensions([])
expect(result2).toEqual([])
})
it("gets only the x- keys", function() {
const result = getExtensions(objTest)
expect(result).toEqual(Map([[ "x-test", "a"]]))
})
it("gets the common keys", function() {
const result = getCommonExtensions(objTest, true)
expect(result).toEqual(Map([[ "minimum", "b"]]))
})
})
describe("deeplyStripKey", function() {
it("should filter out a specified key", function() {
const input = {
-32
View File
@@ -1,32 +0,0 @@
describe("bug #4445: callback-via-$ref rendering", function () {
let mainPage
beforeEach(function (client, done) {
mainPage = client
.url("localhost:3230")
.page.main()
client.waitForElementVisible(".download-url-input", 5000)
.pause(5000)
.clearValue(".download-url-input")
.setValue(".download-url-input", "http://localhost:3230/test-specs/bugs/4445.yaml")
.click("button.download-url-button")
.pause(1000)
done()
})
afterEach(function (client, done) {
done()
})
it("expands an operation that has a visible callback", function (client) {
client.waitForElementVisible(".opblock-tag-section", 10000)
.click(".opblock")
.waitForElementVisible(".opblock-body", 5000)
.click(".opblock-section-header > .tab-header > div.tab-item:nth-of-type(2)")
.waitForElementVisible(".callbacks-container .opblock", 5000)
.click(".callbacks-container .opblock")
.waitForElementVisible(".callbacks-container .opblock-body", 5000)
.assert.containsText(".callbacks-container .opblock-description-wrapper:nth-of-type(2) p", "subscription payload")
client.end()
})
})
-31
View File
@@ -1,31 +0,0 @@
describe("bug #4485: operation metadata storage when referenced via path item $ref", function () {
let mainPage
beforeEach(function (client, done) {
mainPage = client
.url("localhost:3230")
.page.main()
client.waitForElementVisible(".download-url-input", 5000)
.pause(2000)
.clearValue(".download-url-input")
.setValue(".download-url-input", "http://localhost:3230/test-specs/bugs/4485/main.yaml")
.click("button.download-url-button")
.pause(1000)
done()
})
afterEach(function (client, done) {
done()
})
it("sets a consumes value for a body parameter correctly", function (client) {
client.waitForElementVisible(".opblock-tag-section", 10000)
.click(".opblock")
.waitForElementVisible(".opblock-body", 5000)
.click("button.btn.try-out__btn")
.click("select.content-type [value=\"application/xml\"]")
.pause(500)
.assert.value("select.content-type", "application/xml")
client.end()
})
})
-64
View File
@@ -1,64 +0,0 @@
openapi: 3.0.0
info:
title: Callback Example
version: 1.0.0
paths:
/streams:
post:
description: subscribes a client to receive out-of-band data
parameters:
- name: callbackUrl
in: query
required: true
description: |
the location where data will be sent. Must be network accessible
by the source server
schema:
type: string
format: uri
example: https://tonys-server.com
responses:
'201':
description: subscription successfully created
content:
application/json:
schema:
description: subscription information
required:
- subscriptionId
properties:
subscriptionId:
description: this unique identifier allows management of the subscription
type: string
example: 2531329f-fb09-4ef7-887e-84e648214436
callbacks:
# the name `onData` is a convenience locator
onData:
$ref: '#/components/callbacks/onData'
components:
callbacks:
onData:
# when data is sent, it will be sent to the `callbackUrl` provided
# when making the subscription PLUS the suffix `/data`
'{$request.query.callbackUrl}/data':
post:
requestBody:
description: subscription payload
content:
application/json:
schema:
properties:
timestamp:
type: string
format: date-time
userData:
type: string
responses:
'202':
description: |
Your server implementation should return this HTTP status code
if the data was received successfully
'204':
description: |
Your server should return this HTTP status code if no longer interested
in further updates
-15
View File
@@ -1,15 +0,0 @@
---
post:
description: Book
operationId: buy
summary: Buy a book
tags:
- Book
consumes:
- application/json
- application/xml
parameters:
- name: requestBody
in: body
description: Buy a Book
required: true
-5
View File
@@ -1,5 +0,0 @@
---
swagger: '2.0'
paths:
"/v1/book":
"$ref": "./book.yaml"
-23
View File
@@ -1,23 +0,0 @@
const { JSDOM } = require("jsdom")
const win = require("core/window")
const jsdom = new JSDOM("<!doctype html><html><body></body></html>")
const { window } = jsdom
function copyProps(src, target) {
const props = Object.getOwnPropertyNames(src)
.filter(prop => typeof target[prop] === "undefined")
.reduce((result, prop) => ({
...result,
[prop]: Object.getOwnPropertyDescriptor(src, prop),
}), {})
Object.defineProperties(target, props)
}
global.window = window
global.document = window.document
global.navigator = {
userAgent: "node.js",
}
copyProps(win, window) // use UI's built-in window wrapper
copyProps(window, global)