Compare commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
798cc88968 | ||
|
|
1214477117 | ||
|
|
bacea7af8a | ||
|
|
43304aa80a | ||
|
|
cdbd120589 | ||
|
|
37001b38bb | ||
|
|
32ab8b3ce8 | ||
|
|
6b3aba697e | ||
|
|
aa22756641 | ||
|
|
16bf8fb3be | ||
|
|
bf5acc1f40 | ||
|
|
c1007a287b | ||
|
|
c8480a827a | ||
|
|
55fdeeb810 | ||
|
|
9e3a801750 | ||
|
|
9155eb946e | ||
|
|
66e9bd735a | ||
|
|
ae849c31ea | ||
|
|
1a95b9e9c9 | ||
|
|
073b1df730 | ||
|
|
11c586309f | ||
|
|
a37d637061 | ||
|
|
75747424cf | ||
|
|
8055129dd2 | ||
|
|
7049de6201 | ||
|
|
8cef3adfe6 |
@@ -6,6 +6,7 @@
|
||||
],
|
||||
"plugins": [
|
||||
"transform-runtime",
|
||||
"babel-plugin-transform-es2015-constants",
|
||||
[
|
||||
"module-alias",
|
||||
[
|
||||
|
||||
@@ -0,0 +1,73 @@
|
||||
---
|
||||
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/OpenAPI specifications
|
||||
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. -->
|
||||
@@ -0,0 +1,50 @@
|
||||
---
|
||||
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. -->
|
||||
@@ -0,0 +1,46 @@
|
||||
---
|
||||
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! -->
|
||||
@@ -1,70 +0,0 @@
|
||||
<!---
|
||||
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 -->
|
||||
+10
-1
@@ -11,6 +11,15 @@ branches:
|
||||
- master
|
||||
- /^v\d+\.\d+(\.\d+)?(-\S*)?$/
|
||||
install: "npm i && npm update"
|
||||
before_install:
|
||||
- | # quickly pass if only documentation is being updated
|
||||
if [ "$TRAVIS_PULL_REQUEST" != "false" ]; then
|
||||
TRAVIS_COMMIT_RANGE="FETCH_HEAD...$TRAVIS_BRANCH"
|
||||
git diff --name-only $TRAVIS_COMMIT_RANGE | grep -qvE '(\.md$)|(^(docs|examples))/' || {
|
||||
echo "Only docs were updated, stopping build process."
|
||||
exit
|
||||
}
|
||||
fi
|
||||
before_deploy:
|
||||
- npm run build
|
||||
env:
|
||||
@@ -37,7 +46,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;
|
||||
|
||||
@@ -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.5 | 2018-04-20 | 2.0, 3.0 | [tag v3.13.5](https://github.com/swagger-api/swagger-ui/tree/v3.13.5)
|
||||
3.16.0 | 2018-05-26 | 2.0, 3.0 | [tag v3.16.0](https://github.com/swagger-api/swagger-ui/tree/v3.16.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)
|
||||
|
||||
Vendored
+73
-35
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
+5
-4
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
+3
-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
@@ -30,7 +30,7 @@ Parameter Name | Description
|
||||
`domNode` | `Element`, **REQUIRED** if `dom_id` is not provided. The HTML DOM element inside which SwaggerUi will put the user interface for swagger. Overrides `dom_id`.
|
||||
`spec` | `Object={}`. A JS object describing the OpenAPI Specification. When used, the `url` parameter will not be parsed. This is useful for testing manually-generated specifications without hosting them.
|
||||
`url` | `String`. The url pointing to API definition (normally `swagger.json` or `swagger.yaml`). Will be ignored if `urls` or `spec` is used.
|
||||
`urls` | `String`. An array of API definition objects (`{url: "<url>", name: "<name>"}`) used by Topbar plugin. When used and Topbar plugin is enabled, the `url` parameter will not be parsed. Names and URLs must be unique among all items in this array, since they're used as identifiers.
|
||||
`urls` | `Array`. An array of API definition objects (`[{url: "<url1>", name: "<name1>"},{url: "<url2>", name: "<name2>"}]`) used by Topbar plugin. When used and Topbar plugin is enabled, the `url` parameter will not be parsed. Names and URLs must be unique among all items in this array, since they're used as identifiers.
|
||||
`urls.primaryName` | `String`. When using `urls`, you can use this subparameter. If the value matches the name of a spec provided in `urls`, that spec will be displayed when Swagger-UI loads, instead of defaulting to the first spec in `urls`.
|
||||
|
||||
##### Plugin system
|
||||
|
||||
+19
-10
@@ -1,10 +1,11 @@
|
||||
var path = require("path")
|
||||
|
||||
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')
|
||||
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")
|
||||
const os = require("os")
|
||||
|
||||
var pkg = require("./package.json")
|
||||
@@ -28,7 +29,10 @@ var commonRules = [
|
||||
retainLines: true
|
||||
}
|
||||
}],
|
||||
include: [ path.join(__dirname, "src") ]
|
||||
include: [
|
||||
path.join(__dirname, "src"),
|
||||
path.join(__dirname, "node_modules", "object-assign-deep"),
|
||||
]
|
||||
},
|
||||
{ test: /\.(txt|yaml)(\?.*)?$/,
|
||||
loader: "raw-loader" },
|
||||
@@ -48,6 +52,7 @@ module.exports = function(rules, options) {
|
||||
hot: false,
|
||||
separateStylesheets: true,
|
||||
minimize: false,
|
||||
mangle: false,
|
||||
longTermCaching: false,
|
||||
sourcemaps: false,
|
||||
}, options._special)
|
||||
@@ -61,10 +66,14 @@ module.exports = function(rules, options) {
|
||||
}))
|
||||
}
|
||||
|
||||
if( specialOptions.minimize ) { // production mode
|
||||
if( specialOptions.minimize ) { // production mode
|
||||
|
||||
plugins.push(
|
||||
new webpack.optimize.UglifyJsPlugin({
|
||||
new UglifyJsPlugin({
|
||||
uglifyOptions: {
|
||||
mangle: specialOptions.mangle,
|
||||
beautify: !specialOptions.mangle,
|
||||
},
|
||||
sourceMap: true,
|
||||
}),
|
||||
new webpack.LoaderOptionsPlugin({
|
||||
@@ -76,8 +85,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(
|
||||
|
||||
+14
-8
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "swagger-ui",
|
||||
"version": "3.13.6",
|
||||
"version": "3.16.0",
|
||||
"main": "dist/swagger-ui.js",
|
||||
"repository": "git@github.com:swagger-api/swagger-ui.git",
|
||||
"contributors": [
|
||||
@@ -28,16 +28,19 @@
|
||||
"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 --recursive --compilers js:babel-core/register test/core test/components test/bugs test/swagger-ui-dist-package test/xss",
|
||||
"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-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",
|
||||
"hot-e2e-server": "webpack-dev-server --port 3230 --content-base test/e2e/helpers --host 0.0.0.0 --config webpack-hot-dev-server.config.js --inline --hot --progress",
|
||||
"e2e": "npm-run-all --parallel -r hot-e2e-server mock-api test-e2e"
|
||||
"e2e": "npm-run-all --parallel -r hot-e2e-server mock-api test-e2e",
|
||||
"open-static": "node -e 'require(\"open\")(\"http://localhost:3002\")'",
|
||||
"serve-static": "http-server dist/ -i -a 0.0.0.0 -p 3002",
|
||||
"start": "npm-run-all --parallel serve-static open-static"
|
||||
},
|
||||
"dependencies": {
|
||||
"@braintree/sanitize-url": "^2.0.2",
|
||||
@@ -47,7 +50,8 @@
|
||||
"commonmark": "^0.28.1",
|
||||
"core-js": "^2.5.1",
|
||||
"css.escape": "1.5.1",
|
||||
"deep-extend": "0.4.1",
|
||||
"deep-extend": "0.5.1",
|
||||
"dompurify": "^1.0.4",
|
||||
"expect": "1.20.2",
|
||||
"getbase": "^2.8.2",
|
||||
"ieee754": "^1.1.8",
|
||||
@@ -80,11 +84,10 @@
|
||||
"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.7.2",
|
||||
"swagger-client": "^3.8.5",
|
||||
"url-parse": "^1.1.8",
|
||||
"whatwg-fetch": "0.11.1",
|
||||
"worker-loader": "^0.7.1",
|
||||
@@ -99,6 +102,7 @@
|
||||
"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",
|
||||
@@ -114,11 +118,12 @@
|
||||
"eslint": "^4.1.1",
|
||||
"eslint-plugin-import": "^2.6.0",
|
||||
"eslint-plugin-mocha": "^4.11.0",
|
||||
"eslint-plugin-react": "^7.1.0",
|
||||
"eslint-plugin-react": "~7.7.0",
|
||||
"extract-text-webpack-plugin": "^2.1.2",
|
||||
"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",
|
||||
@@ -146,6 +151,7 @@
|
||||
"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"
|
||||
|
||||
@@ -11,6 +11,7 @@ export default class ArrayModel extends Component {
|
||||
getConfigs: PropTypes.func.isRequired,
|
||||
specSelectors: PropTypes.object.isRequired,
|
||||
name: PropTypes.string,
|
||||
displayName: PropTypes.string,
|
||||
required: PropTypes.bool,
|
||||
expandDepth: PropTypes.number,
|
||||
specPath: ImPropTypes.list.isRequired,
|
||||
@@ -18,10 +19,10 @@ export default class ArrayModel extends Component {
|
||||
}
|
||||
|
||||
render(){
|
||||
let { getComponent, getConfigs, schema, depth, expandDepth, name, specPath } = this.props
|
||||
let { getComponent, getConfigs, schema, depth, expandDepth, name, displayName, specPath } = this.props
|
||||
let description = schema.get("description")
|
||||
let items = schema.get("items")
|
||||
let title = schema.get("title") || name
|
||||
let title = schema.get("title") || displayName || name
|
||||
let properties = schema.filter( ( v, key) => ["type", "items", "description", "$$ref"].indexOf(key) === -1 )
|
||||
|
||||
const Markdown = getComponent("Markdown")
|
||||
|
||||
@@ -7,7 +7,8 @@ export default class HighlightCode extends Component {
|
||||
static propTypes = {
|
||||
value: PropTypes.string.isRequired,
|
||||
className: PropTypes.string,
|
||||
downloadable: PropTypes.bool
|
||||
downloadable: PropTypes.bool,
|
||||
fileName: PropTypes.string
|
||||
}
|
||||
|
||||
componentDidMount() {
|
||||
@@ -23,7 +24,7 @@ export default class HighlightCode extends Component {
|
||||
}
|
||||
|
||||
downloadText = () => {
|
||||
saveAs(this.props.value, "response.txt")
|
||||
saveAs(this.props.value, this.props.fileName || "response.txt")
|
||||
}
|
||||
|
||||
preventYScrollingBeyondElement = (e) => {
|
||||
|
||||
@@ -9,6 +9,7 @@ export default class ModelWrapper extends Component {
|
||||
static propTypes = {
|
||||
schema: PropTypes.object.isRequired,
|
||||
name: PropTypes.string,
|
||||
displayName: PropTypes.string,
|
||||
getComponent: PropTypes.func.isRequired,
|
||||
getConfigs: PropTypes.func.isRequired,
|
||||
specSelectors: PropTypes.object.isRequired,
|
||||
|
||||
@@ -10,6 +10,7 @@ export default class Model extends ImmutablePureComponent {
|
||||
getConfigs: PropTypes.func.isRequired,
|
||||
specSelectors: PropTypes.object.isRequired,
|
||||
name: PropTypes.string,
|
||||
displayName: PropTypes.string,
|
||||
isRef: PropTypes.bool,
|
||||
required: PropTypes.bool,
|
||||
expandDepth: PropTypes.number,
|
||||
@@ -33,7 +34,7 @@ export default class Model extends ImmutablePureComponent {
|
||||
}
|
||||
|
||||
render () {
|
||||
let { getComponent, getConfigs, specSelectors, schema, required, name, isRef, specPath } = this.props
|
||||
let { getComponent, getConfigs, specSelectors, schema, required, name, isRef, specPath, displayName } = this.props
|
||||
const ObjectModel = getComponent("ObjectModel")
|
||||
const ArrayModel = getComponent("ArrayModel")
|
||||
const PrimitiveModel = getComponent("PrimitiveModel")
|
||||
@@ -51,7 +52,7 @@ export default class Model extends ImmutablePureComponent {
|
||||
|
||||
if(!schema) {
|
||||
return <span className="model model-title">
|
||||
<span className="model-title__text">{ name }</span>
|
||||
<span className="model-title__text">{ displayName || name }</span>
|
||||
<img src={require("core/../img/rolling-load.svg")} height={"20px"} width={"20px"} style={{
|
||||
marginLeft: "1em",
|
||||
position: "relative",
|
||||
|
||||
@@ -51,9 +51,12 @@ export default class Models extends Component {
|
||||
</h4>
|
||||
<Collapse isOpened={showModels}>
|
||||
{
|
||||
definitions.entrySeq().map( ( [ name ])=>{
|
||||
definitions.entrySeq().map(([name])=>{
|
||||
|
||||
const schema = specSelectors.specResolvedSubtree([...specPathBase, name])
|
||||
const fullPath = [...specPathBase, name]
|
||||
const schema = specSelectors.specResolvedSubtree(fullPath)|| Im.Map()
|
||||
const rawSchema = specSelectors.specJson().getIn(fullPath, Im.Map())
|
||||
const displayName = schema.get("title") || rawSchema.get("title") || name
|
||||
|
||||
if(layoutSelectors.isShown(["models", name], false) && schema === undefined) {
|
||||
// Firing an action in a container render is not great,
|
||||
@@ -63,7 +66,8 @@ export default class Models extends Component {
|
||||
|
||||
const content = <ModelWrapper name={ name }
|
||||
expandDepth={ defaultModelsExpandDepth }
|
||||
schema={ schema || Im.Map() }
|
||||
schema={ schema || Im.Map() }
|
||||
displayName={displayName}
|
||||
specPath={Im.List([...specPathBase, name])}
|
||||
getComponent={ getComponent }
|
||||
specSelectors={ specSelectors }
|
||||
@@ -72,7 +76,9 @@ export default class Models extends Component {
|
||||
layoutActions = {layoutActions}/>
|
||||
|
||||
const title = <span className="model-box">
|
||||
<span className="model model-title">{name}</span>
|
||||
<span className="model model-title">
|
||||
{displayName}
|
||||
</span>
|
||||
</span>
|
||||
|
||||
return <div id={ `model-${name}` } className="model-container" key={ `models-section-${name}` }>
|
||||
@@ -81,6 +87,7 @@ export default class Models extends Component {
|
||||
collapsedContent={this.getCollapsedContent(name)}
|
||||
onToggle={this.handleToggle}
|
||||
title={title}
|
||||
displayName={displayName}
|
||||
modelName={name}
|
||||
hideSelfOnExpand={true}
|
||||
expanded={defaultModelsExpandDepth > 1}
|
||||
|
||||
@@ -15,6 +15,7 @@ export default class ObjectModel extends Component {
|
||||
onToggle: PropTypes.func,
|
||||
specSelectors: PropTypes.object.isRequired,
|
||||
name: PropTypes.string,
|
||||
displayName: PropTypes.string,
|
||||
isRef: PropTypes.bool,
|
||||
expandDepth: PropTypes.number,
|
||||
depth: PropTypes.number,
|
||||
@@ -22,7 +23,7 @@ export default class ObjectModel extends Component {
|
||||
}
|
||||
|
||||
render(){
|
||||
let { schema, name, isRef, getComponent, getConfigs, depth, onToggle, expanded, specPath, ...otherProps } = this.props
|
||||
let { schema, name, displayName, isRef, getComponent, getConfigs, depth, onToggle, expanded, specPath, ...otherProps } = this.props
|
||||
let { specSelectors,expandDepth } = otherProps
|
||||
const { isOAS3 } = specSelectors
|
||||
|
||||
@@ -35,7 +36,7 @@ export default class ObjectModel extends Component {
|
||||
let description = schema.get("description")
|
||||
let properties = schema.get("properties")
|
||||
let additionalProperties = schema.get("additionalProperties")
|
||||
let title = schema.get("title") || name
|
||||
let title = schema.get("title") || displayName || name
|
||||
let requiredProperties = schema.get("required")
|
||||
|
||||
const JumpToPath = getComponent("JumpToPath", true)
|
||||
@@ -78,7 +79,7 @@ export default class ObjectModel extends Component {
|
||||
{
|
||||
<table className="model"><tbody>
|
||||
{
|
||||
!description ? null : <tr style={{ color: "#999", fontStyle: "italic" }}>
|
||||
!description ? null : <tr style={{ color: "#666", fontStyle: "italic" }}>
|
||||
<td>description:</td>
|
||||
<td>
|
||||
<Markdown source={ description } />
|
||||
|
||||
@@ -1,6 +1,9 @@
|
||||
import React from "react"
|
||||
import URL from "url-parse"
|
||||
|
||||
import PropTypes from "prop-types"
|
||||
import { sanitizeUrl } from "core/utils"
|
||||
import win from "core/window"
|
||||
|
||||
export default class OnlineValidatorBadge extends React.Component {
|
||||
static propTypes = {
|
||||
@@ -11,20 +14,28 @@ export default class OnlineValidatorBadge extends React.Component {
|
||||
|
||||
constructor(props, context) {
|
||||
super(props, context)
|
||||
let { specSelectors, getConfigs } = props
|
||||
let { getConfigs } = props
|
||||
let { validatorUrl } = getConfigs()
|
||||
this.state = {
|
||||
url: specSelectors.url(),
|
||||
url: this.getDefinitionUrl(),
|
||||
validatorUrl: validatorUrl === undefined ? "https://online.swagger.io/validator" : validatorUrl
|
||||
}
|
||||
}
|
||||
|
||||
getDefinitionUrl = () => {
|
||||
// TODO: test this behavior by stubbing `window.location` in an Enzyme/JSDom env
|
||||
let { specSelectors } = this.props
|
||||
|
||||
const urlObject = new URL(specSelectors.url(), win.location)
|
||||
return urlObject.toString()
|
||||
}
|
||||
|
||||
componentWillReceiveProps(nextProps) {
|
||||
let { specSelectors, getConfigs } = nextProps
|
||||
let { getConfigs } = nextProps
|
||||
let { validatorUrl } = getConfigs()
|
||||
|
||||
this.setState({
|
||||
url: specSelectors.url(),
|
||||
url: this.getDefinitionUrl(),
|
||||
validatorUrl: validatorUrl === undefined ? "https://online.swagger.io/validator" : validatorUrl
|
||||
})
|
||||
}
|
||||
|
||||
@@ -47,7 +47,7 @@ export default class ParamBody extends PureComponent {
|
||||
|
||||
updateValues = (props) => {
|
||||
let { specSelectors, pathMethod, param, isExecute, consumesValue="" } = props
|
||||
let parameter = specSelectors ? specSelectors.parameterWithMeta(pathMethod, param.get("name"), param.get("in")) : fromJS({})
|
||||
let parameter = (specSelectors ? specSelectors.parameterWithMeta(pathMethod, param.get("name"), param.get("in")) : fromJS({})) || param
|
||||
let isXml = /xml/i.test(consumesValue)
|
||||
let isJson = /json/i.test(consumesValue)
|
||||
let paramValue = isXml ? parameter.get("value_xml") : parameter.get("value")
|
||||
|
||||
@@ -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,8 +30,7 @@ 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 parameter = specSelectors.parameterWithMeta(pathMethod, param.get("name"), param.get("in")) || param
|
||||
let enumValue
|
||||
|
||||
if(isOAS3()) {
|
||||
@@ -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
|
||||
|
||||
@@ -149,7 +156,7 @@ export default class ParameterRow extends Component {
|
||||
}
|
||||
|
||||
return (
|
||||
<tr>
|
||||
<tr className="parameters">
|
||||
<td className="col parameters-col_name">
|
||||
<div className={required ? "parameter__name required" : "parameter__name"}>
|
||||
{ param.get("name") }
|
||||
|
||||
@@ -10,11 +10,12 @@ export default class Primitive extends Component {
|
||||
getComponent: PropTypes.func.isRequired,
|
||||
getConfigs: PropTypes.func.isRequired,
|
||||
name: PropTypes.string,
|
||||
displayName: PropTypes.string,
|
||||
depth: PropTypes.number
|
||||
}
|
||||
|
||||
render(){
|
||||
let { schema, getComponent, getConfigs, name, depth } = this.props
|
||||
let { schema, getComponent, getConfigs, name, displayName, depth } = this.props
|
||||
|
||||
const { showExtensions } = getConfigs()
|
||||
|
||||
@@ -27,7 +28,7 @@ export default class Primitive extends Component {
|
||||
let format = schema.get("format")
|
||||
let xml = schema.get("xml")
|
||||
let enumArray = schema.get("enum")
|
||||
let title = schema.get("title") || name
|
||||
let title = schema.get("title") || displayName || name
|
||||
let description = schema.get("description")
|
||||
let extensions = getExtensions(schema)
|
||||
let properties = schema
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
import React from "react"
|
||||
import PropTypes from "prop-types"
|
||||
import Remarkable from "remarkable"
|
||||
import sanitize from "sanitize-html"
|
||||
import DomPurify from "dompurify"
|
||||
import cx from "classnames"
|
||||
|
||||
// eslint-disable-next-line no-useless-escape
|
||||
@@ -40,20 +40,8 @@ Markdown.propTypes = {
|
||||
|
||||
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(/"/g, "\"")
|
||||
}
|
||||
}
|
||||
|
||||
export function sanitizer(str) {
|
||||
return sanitize(str, sanitizeOptions)
|
||||
return DomPurify.sanitize(str, {
|
||||
ADD_ATTR: ["target"]
|
||||
})
|
||||
}
|
||||
|
||||
@@ -52,6 +52,7 @@ 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 || ""
|
||||
|
||||
@@ -63,9 +64,7 @@ export default class ResponseBody extends React.PureComponent {
|
||||
(headers["content-description"] && (/File Transfer/i).test(headers["content-description"]))) {
|
||||
// Download
|
||||
|
||||
const isSafari = /^((?!chrome|android).)*safari/i.test(navigator.userAgent)
|
||||
|
||||
if (!isSafari && "Blob" in window) {
|
||||
if ("Blob" in window) {
|
||||
let type = contentType || "text/html"
|
||||
let blob = (content instanceof Blob) ? content : new Blob([content], {type: type})
|
||||
let href = window.URL.createObjectURL(blob)
|
||||
@@ -100,7 +99,7 @@ export default class ResponseBody extends React.PureComponent {
|
||||
body = "can't parse JSON. Raw result:\n\n" + content
|
||||
}
|
||||
|
||||
bodyEl = <HighlightCode downloadable value={ body } />
|
||||
bodyEl = <HighlightCode downloadable fileName={`${downloadName}.json`} value={ body } />
|
||||
|
||||
// XML
|
||||
} else if (/xml/i.test(contentType)) {
|
||||
@@ -108,11 +107,11 @@ export default class ResponseBody extends React.PureComponent {
|
||||
textNodesOnSameLine: true,
|
||||
indentor: " "
|
||||
})
|
||||
bodyEl = <HighlightCode downloadable value={ body } />
|
||||
bodyEl = <HighlightCode downloadable fileName={`${downloadName}.xml`} value={ body } />
|
||||
|
||||
// HTML or Plain Text
|
||||
} else if (lowerCase(contentType) === "text/html" || /text\/plain/.test(contentType)) {
|
||||
bodyEl = <HighlightCode downloadable value={ content } />
|
||||
bodyEl = <HighlightCode downloadable fileName={`${downloadName}.html`} value={ content } />
|
||||
|
||||
// Image
|
||||
} else if (/^image\//i.test(contentType)) {
|
||||
@@ -126,7 +125,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 value={ content } />
|
||||
bodyEl = <HighlightCode downloadable fileName={`${downloadName}.txt`} value={ content } />
|
||||
} else if ( content.size > 0 ) {
|
||||
// We don't know the contentType, but there was some content returned
|
||||
if(parsedContent) {
|
||||
@@ -136,7 +135,7 @@ export default class ResponseBody extends React.PureComponent {
|
||||
<p className="i">
|
||||
Unrecognized response type; displaying content as text.
|
||||
</p>
|
||||
<HighlightCode downloadable value={ parsedContent } />
|
||||
<HighlightCode downloadable fileName={`${downloadName}.txt`} value={ parsedContent } />
|
||||
</div>
|
||||
|
||||
} else {
|
||||
|
||||
+6
-1
@@ -173,7 +173,12 @@ module.exports = function SwaggerUI(opts) {
|
||||
|
||||
let configUrl = queryConfig.config || constructorConfig.configUrl
|
||||
|
||||
if (!configUrl || !system.specActions.getConfigByUrl || system.specActions.getConfigByUrl && !system.specActions.getConfigByUrl(configUrl, downloadSpec)) {
|
||||
if (!configUrl || !system.specActions.getConfigByUrl || system.specActions.getConfigByUrl && !system.specActions.getConfigByUrl({
|
||||
url: configUrl,
|
||||
loadRemoteConfig: true,
|
||||
requestInterceptor: constructorConfig.requestInterceptor,
|
||||
responseInterceptor: constructorConfig.responseInterceptor,
|
||||
}, downloadSpec)) {
|
||||
return downloadSpec()
|
||||
}
|
||||
|
||||
|
||||
@@ -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 = ()=> {}
|
||||
@@ -15,6 +17,7 @@ const JsonSchemaPropShape = {
|
||||
schema: PropTypes.object,
|
||||
errors: ImPropTypes.list,
|
||||
required: PropTypes.bool,
|
||||
dispatchInitialValue: PropTypes.bool,
|
||||
description: PropTypes.any
|
||||
}
|
||||
|
||||
@@ -32,6 +35,13 @@ export class JsonSchemaForm extends Component {
|
||||
static propTypes = JsonSchemaPropShape
|
||||
static defaultProps = JsonSchemaDefaultProps
|
||||
|
||||
componentDidMount() {
|
||||
const { dispatchInitialValue, value, onChange } = this.props
|
||||
if(dispatchInitialValue) {
|
||||
onChange(value)
|
||||
}
|
||||
}
|
||||
|
||||
render() {
|
||||
let { schema, errors, value, onChange, getComponent, fn } = this.props
|
||||
|
||||
@@ -204,3 +214,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>
|
||||
)
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,23 +1,14 @@
|
||||
import { parseYamlConfig } from "./helpers"
|
||||
|
||||
export const downloadConfig = (url) => ({fn: { fetch }, getConfigs}) => {
|
||||
const { requestInterceptor, responseInterceptor } = getConfigs()
|
||||
let req = { url }
|
||||
if(requestInterceptor) {
|
||||
req = requestInterceptor(req)
|
||||
}
|
||||
export const downloadConfig = (req) => (system) => {
|
||||
const {fn: { fetch }} = system
|
||||
|
||||
return fetch(req)
|
||||
.then(res => {
|
||||
if(res) {
|
||||
return responseInterceptor(res)
|
||||
}
|
||||
return res
|
||||
})
|
||||
}
|
||||
|
||||
export const getConfigByUrl = (configUrl, cb)=> ({ specActions }) => {
|
||||
if (configUrl) {
|
||||
return specActions.downloadConfig(configUrl).then(next, next)
|
||||
export const getConfigByUrl = (req, cb)=> ({ specActions }) => {
|
||||
if (req) {
|
||||
return specActions.downloadConfig(req).then(next, next)
|
||||
}
|
||||
|
||||
function next(res) {
|
||||
@@ -25,7 +16,7 @@ export const getConfigByUrl = (configUrl, cb)=> ({ specActions }) => {
|
||||
specActions.updateLoadingStatus("failedConfig")
|
||||
specActions.updateLoadingStatus("failedConfig")
|
||||
specActions.updateUrl("")
|
||||
console.error(res.statusText + " " + configUrl)
|
||||
console.error(res.statusText + " " + req.url)
|
||||
cb(null)
|
||||
} else {
|
||||
cb(parseYamlConfig(res.text))
|
||||
|
||||
@@ -1,10 +1,12 @@
|
||||
import React from "react"
|
||||
import PropTypes from "prop-types"
|
||||
import ImPropTypes from "react-immutable-proptypes"
|
||||
import { OrderedMap } from "immutable"
|
||||
import { getSampleSchema } from "core/utils"
|
||||
import { Map, OrderedMap } from "immutable"
|
||||
|
||||
const RequestBody = ({
|
||||
requestBody,
|
||||
requestBodyValue,
|
||||
getComponent,
|
||||
getConfigs,
|
||||
specSelectors,
|
||||
@@ -13,6 +15,10 @@ const RequestBody = ({
|
||||
specPath,
|
||||
onChange
|
||||
}) => {
|
||||
const handleFile = (e) => {
|
||||
onChange(e.target.files[0])
|
||||
}
|
||||
|
||||
const Markdown = getComponent("Markdown")
|
||||
const ModelExample = getComponent("modelExample")
|
||||
const RequestBodyEditor = getComponent("RequestBodyEditor")
|
||||
@@ -23,10 +29,80 @@ const RequestBody = ({
|
||||
|
||||
const mediaTypeValue = requestBodyContent.get(contentType)
|
||||
|
||||
const isObjectContent = mediaTypeValue.getIn(["schema", "type"]) === "object"
|
||||
|
||||
if(!mediaTypeValue) {
|
||||
return null
|
||||
}
|
||||
|
||||
if(contentType === "application/octet-stream") {
|
||||
const Input = getComponent("Input")
|
||||
|
||||
if(!isExecute) {
|
||||
return <i>
|
||||
Example values are not available for <code>application/octet-stream</code> media types.
|
||||
</i>
|
||||
}
|
||||
|
||||
return <Input type={"file"} onChange={handleFile} />
|
||||
}
|
||||
|
||||
if(
|
||||
isObjectContent &&
|
||||
(contentType === "application/x-www-form-urlencoded"
|
||||
|| contentType.indexOf("multipart/") === 0))
|
||||
{
|
||||
const JsonSchemaForm = getComponent("JsonSchemaForm")
|
||||
const HighlightCode = getComponent("highlightCode")
|
||||
const bodyProperties = requestBody.getIn(["content", contentType, "schema", "properties"], OrderedMap())
|
||||
requestBodyValue = Map.isMap(requestBodyValue) ? requestBodyValue : OrderedMap()
|
||||
|
||||
return <div className="table-container">
|
||||
<table>
|
||||
<tbody>
|
||||
{
|
||||
bodyProperties.map((prop, key) => {
|
||||
const required = prop.get("required")
|
||||
const type = prop.get("type")
|
||||
const format = prop.get("format")
|
||||
|
||||
const isFile = type === "string" && (format === "binary" || format === "base64")
|
||||
|
||||
return <tr key={key} className="parameters">
|
||||
<td className="col parameters-col_name">
|
||||
<div className={required ? "parameter__name required" : "parameter__name"}>
|
||||
{ key }
|
||||
{ !required ? null : <span style={{color: "red"}}> *</span> }
|
||||
</div>
|
||||
<div className="parameter__type">
|
||||
{ type }
|
||||
{ format && <span className="prop-format">(${format})</span>}
|
||||
</div>
|
||||
<div className="parameter__deprecated">
|
||||
{ prop.get("deprecated") ? "deprecated": null }
|
||||
</div>
|
||||
</td>
|
||||
<td className="col parameters-col_description">
|
||||
{isExecute ?
|
||||
<JsonSchemaForm
|
||||
dispatchInitialValue={!isFile}
|
||||
schema={prop}
|
||||
getComponent={getComponent}
|
||||
value={requestBodyValue.get(key) || getSampleSchema(prop)}
|
||||
onChange={(value) => {
|
||||
onChange(value, [key])
|
||||
}}
|
||||
/>
|
||||
: <HighlightCode className="example" value={ getSampleSchema(prop) } />}
|
||||
</td>
|
||||
</tr>
|
||||
})
|
||||
}
|
||||
</tbody>
|
||||
</table>
|
||||
</div>
|
||||
}
|
||||
|
||||
return <div>
|
||||
{ requestBodyDescription &&
|
||||
<Markdown source={requestBodyDescription} />
|
||||
@@ -53,6 +129,7 @@ const RequestBody = ({
|
||||
|
||||
RequestBody.propTypes = {
|
||||
requestBody: ImPropTypes.orderedMap.isRequired,
|
||||
requestBodyValue: ImPropTypes.orderedMap.isRequired,
|
||||
getComponent: PropTypes.func.isRequired,
|
||||
getConfigs: PropTypes.func.isRequired,
|
||||
specSelectors: PropTypes.object.isRequired,
|
||||
|
||||
@@ -4,11 +4,13 @@ import parameters from "./parameters"
|
||||
import VersionStamp from "./version-stamp"
|
||||
import OnlineValidatorBadge from "./online-validator-badge"
|
||||
import Model from "./model"
|
||||
import JsonSchema_string from "./json-schema-string"
|
||||
|
||||
export default {
|
||||
Markdown,
|
||||
AuthItem,
|
||||
parameters,
|
||||
JsonSchema_string,
|
||||
VersionStamp,
|
||||
model: Model,
|
||||
onlineValidatorBadge: OnlineValidatorBadge,
|
||||
|
||||
@@ -0,0 +1,26 @@
|
||||
import React from "react"
|
||||
import { OAS3ComponentWrapFactory } from "../helpers"
|
||||
|
||||
export default OAS3ComponentWrapFactory(({ Ori, ...props }) => {
|
||||
const {
|
||||
schema,
|
||||
getComponent,
|
||||
errors,
|
||||
onChange
|
||||
} = props
|
||||
|
||||
const { type, format } = schema
|
||||
const Input = getComponent("Input")
|
||||
|
||||
if(type === "string" && (format === "binary" || format === "base64")) {
|
||||
return <Input type="file"
|
||||
className={ errors.length ? "invalid" : ""}
|
||||
title={ errors.length ? errors : ""}
|
||||
onChange={(e) => {
|
||||
onChange(e.target.files[0])
|
||||
}}
|
||||
disabled={Ori.isDisabled}/>
|
||||
} else {
|
||||
return <Ori {...props} />
|
||||
}
|
||||
})
|
||||
@@ -185,8 +185,17 @@ class Parameters extends Component {
|
||||
<RequestBody
|
||||
specPath={requestBodySpecPath}
|
||||
requestBody={requestBody}
|
||||
requestBodyValue={oas3Selectors.requestBodyValue(...pathMethod) || Map()}
|
||||
isExecute={isExecute}
|
||||
onChange={(value) => {
|
||||
onChange={(value, path) => {
|
||||
if(path) {
|
||||
const lastValue = oas3Selectors.requestBodyValue(...pathMethod)
|
||||
const usableValue = Map.isMap(lastValue) ? lastValue : Map()
|
||||
return oas3Actions.setRequestBodyValue({
|
||||
pathMethod,
|
||||
value: usableValue.setIn(path, value)
|
||||
})
|
||||
}
|
||||
oas3Actions.setRequestBodyValue({ value, pathMethod })
|
||||
}}
|
||||
contentType={oas3Selectors.requestContentType(...pathMethod)}/>
|
||||
|
||||
@@ -348,7 +348,9 @@ export const executeRequest = (req) =>
|
||||
|
||||
if(isJSONObject(requestBody)) {
|
||||
req.requestBody = JSON.parse(requestBody)
|
||||
} else {
|
||||
} else if(requestBody && requestBody.toJS) {
|
||||
req.requestBody = requestBody.toJS()
|
||||
} else{
|
||||
req.requestBody = requestBody
|
||||
}
|
||||
}
|
||||
|
||||
@@ -118,7 +118,11 @@ export default {
|
||||
let operationPath = ["paths", ...path]
|
||||
let metaPath = ["meta", "paths", ...path]
|
||||
|
||||
if(!state.getIn(["json", ...operationPath]) && !state.getIn(["resolved", ...operationPath])) {
|
||||
if(
|
||||
!state.getIn(["json", ...operationPath])
|
||||
&& !state.getIn(["resolved", ...operationPath])
|
||||
&& !state.getIn(["resolvedSubtrees", ...operationPath])
|
||||
) {
|
||||
// do nothing if the operation does not exist
|
||||
return state
|
||||
}
|
||||
|
||||
+24
-1
@@ -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
|
||||
}
|
||||
|
||||
@@ -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>
|
||||
|
||||
@@ -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")
|
||||
})
|
||||
})
|
||||
@@ -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(){
|
||||
|
||||
|
||||
@@ -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><tr><td>ABC</td></tr></table></div>`)
|
||||
expect(el.html()).toEqual(`<div class="markdown"><table><tbody><tr><td>ABC</td></tr></tbody></table></div>`)
|
||||
})
|
||||
|
||||
it("allows image elements", function() {
|
||||
const str = ``
|
||||
const el = render(<Markdown source={str} />)
|
||||
expect(el.html()).toEqual(`<div class="markdown"><p><img src="http://image.source" title="Image title"></p>\n</div>`)
|
||||
expect(el.html()).toEqual(`<div class="markdown"><p><img title="Image title" alt="Image alt text" src="http://image.source"></p>\n</div>`)
|
||||
})
|
||||
|
||||
|
||||
it("allows image elements with https scheme", function() {
|
||||
const str = ``
|
||||
const el = render(<Markdown source={str} />)
|
||||
expect(el.html()).toEqual(`<div class="markdown"><p><img src="https://image.source" title="Image title"></p>\n</div>`)
|
||||
expect(el.html()).toEqual(`<div class="markdown"><p><img title="Image title" alt="Image alt text" src="https://image.source"></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 href="https://example.com/" target="_blank">Link</a></p>\n</div>`)
|
||||
expect(el.html()).toEqual(`<div class="markdown"><p><a target="_blank" href="https://example.com/">Link</a></p>\n</div>`)
|
||||
})
|
||||
})
|
||||
|
||||
@@ -60,13 +60,13 @@ describe("Markdown component", function() {
|
||||
it("allows image elements", function() {
|
||||
const str = ``
|
||||
const el = render(<OAS3Markdown source={str} />)
|
||||
expect(el.html()).toEqual(`<div class="renderedMarkdown"><div><p><img src="http://image.source" title="Image title"></p></div></div>`)
|
||||
expect(el.html()).toEqual(`<div class="renderedMarkdown"><div><p><img title="Image title" alt="Image alt text" src="http://image.source"></p></div></div>`)
|
||||
})
|
||||
|
||||
it("allows image elements with https scheme", function() {
|
||||
const str = ``
|
||||
const el = render(<OAS3Markdown source={str} />)
|
||||
expect(el.html()).toEqual(`<div class="renderedMarkdown"><div><p><img src="https://image.source" title="Image title"></p></div></div>`)
|
||||
expect(el.html()).toEqual(`<div class="renderedMarkdown"><div><p><img title="Image title" alt="Image alt text" src="https://image.source"></p></div></div>`)
|
||||
})
|
||||
|
||||
it("allows image elements with data scheme", function() {
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
import React from "react"
|
||||
import expect, { createSpy } from "expect"
|
||||
import { shallow } from "enzyme"
|
||||
import { fromJS } from "immutable"
|
||||
import { fromJS, Map } from "immutable"
|
||||
import Models from "components/models"
|
||||
import ModelCollpase from "components/model-collapse"
|
||||
import ModelComponent from "components/model-wrapper"
|
||||
@@ -19,6 +19,7 @@ describe("<Models/>", function(){
|
||||
},
|
||||
specSelectors: {
|
||||
isOAS3: () => false,
|
||||
specJson: () => Map(),
|
||||
definitions: function() {
|
||||
return fromJS({
|
||||
def1: {},
|
||||
|
||||
@@ -5,80 +5,23 @@ import { downloadConfig } from "corePlugins/configs/spec-actions"
|
||||
describe("configs plugin - actions", () => {
|
||||
|
||||
describe("downloadConfig", () => {
|
||||
it("should call the system fetch helper with a provided url", () => {
|
||||
it("should call the system fetch helper with a provided request", () => {
|
||||
const fetchSpy = createSpy(async () => {}).andCallThrough()
|
||||
const system = {
|
||||
fn: {
|
||||
fetch: fetchSpy
|
||||
},
|
||||
getConfigs() {
|
||||
return {}
|
||||
}
|
||||
}
|
||||
|
||||
const url = "http://swagger.io/one"
|
||||
|
||||
downloadConfig(url)(system)
|
||||
|
||||
expect(fetchSpy).toHaveBeenCalledWith({
|
||||
url: url
|
||||
})
|
||||
})
|
||||
it("should allow the globally configured requestInterceptor to modify the request", () => {
|
||||
const fetchSpy = createSpy(async () => {}).andCallThrough()
|
||||
const requestInterceptorSpy = createSpy((req) => {
|
||||
req.url = "http://swagger.io/two"
|
||||
return req
|
||||
}).andCallThrough()
|
||||
const system = {
|
||||
fn: {
|
||||
fetch: fetchSpy
|
||||
},
|
||||
getConfigs() {
|
||||
return {
|
||||
requestInterceptor: requestInterceptorSpy
|
||||
}
|
||||
}
|
||||
const req = {
|
||||
url: "http://swagger.io/one",
|
||||
requestInterceptor: a => a,
|
||||
responseInterceptor: a => a,
|
||||
}
|
||||
|
||||
const url = "http://swagger.io/one"
|
||||
downloadConfig(req)(system)
|
||||
|
||||
downloadConfig(url)(system)
|
||||
|
||||
expect(fetchSpy).toHaveBeenCalledWith({
|
||||
url: "http://swagger.io/two"
|
||||
})
|
||||
})
|
||||
it("should allow the globally configured responseInterceptor to modify the response", async () => {
|
||||
const fetchSpy = createSpy(async (req) => {
|
||||
return {
|
||||
url: req.url,
|
||||
ok: true
|
||||
}
|
||||
}).andCallThrough()
|
||||
const responseInterceptorSpy = createSpy((res) => {
|
||||
res.url = "http://swagger.io/two"
|
||||
return res
|
||||
}).andCallThrough()
|
||||
const system = {
|
||||
fn: {
|
||||
fetch: fetchSpy
|
||||
},
|
||||
getConfigs() {
|
||||
return {
|
||||
responseInterceptor: responseInterceptorSpy
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
const url = "http://swagger.io/one"
|
||||
|
||||
const res = await downloadConfig(url)(system)
|
||||
|
||||
expect(res).toEqual({
|
||||
url: "http://swagger.io/two",
|
||||
ok: true
|
||||
})
|
||||
expect(fetchSpy).toHaveBeenCalledWith(req)
|
||||
})
|
||||
})
|
||||
})
|
||||
|
||||
+94
-3
@@ -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")
|
||||
})
|
||||
|
||||
@@ -0,0 +1,31 @@
|
||||
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()
|
||||
})
|
||||
})
|
||||
@@ -0,0 +1,29 @@
|
||||
describe("bug #4536: model name consistency", 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/4536.yaml")
|
||||
.click("button.download-url-button")
|
||||
.pause(1000)
|
||||
|
||||
done()
|
||||
})
|
||||
afterEach(function (client, done) {
|
||||
done()
|
||||
})
|
||||
it("consistently displays a model's name regardless of expansion state", function (client) {
|
||||
client.waitForElementVisible("span.model.model-title", 10000)
|
||||
.assert.containsText("span.model.model-title", "TitleName")
|
||||
.click("span.model.model-title")
|
||||
.pause(500)
|
||||
.assert.containsText("span.model-title__text", "TitleName")
|
||||
|
||||
client.end()
|
||||
})
|
||||
})
|
||||
@@ -0,0 +1,15 @@
|
||||
---
|
||||
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
|
||||
@@ -0,0 +1,5 @@
|
||||
---
|
||||
swagger: '2.0'
|
||||
paths:
|
||||
"/v1/book":
|
||||
"$ref": "./book.yaml"
|
||||
@@ -0,0 +1,9 @@
|
||||
swagger: '2.0'
|
||||
info:
|
||||
version: 0.0.0
|
||||
title: test
|
||||
paths: {}
|
||||
|
||||
definitions:
|
||||
ModelName:
|
||||
title: TitleName
|
||||
@@ -0,0 +1,23 @@
|
||||
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)
|
||||
@@ -20,6 +20,7 @@ module.exports = require("./make-webpack-config.js")(rules, {
|
||||
_special: {
|
||||
separateStylesheets: true,
|
||||
minimize: true,
|
||||
mangle: true,
|
||||
sourcemaps: true,
|
||||
},
|
||||
|
||||
|
||||
@@ -20,6 +20,7 @@ module.exports = require("./make-webpack-config.js")(rules, {
|
||||
_special: {
|
||||
separateStylesheets: true,
|
||||
minimize: true,
|
||||
mangle: true,
|
||||
sourcemaps: true,
|
||||
},
|
||||
|
||||
|
||||
Reference in New Issue
Block a user