Compare commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
11c586309f | ||
|
|
a37d637061 | ||
|
|
75747424cf | ||
|
|
8055129dd2 | ||
|
|
7049de6201 | ||
|
|
8cef3adfe6 | ||
|
|
cbff0251ae | ||
|
|
62354568a9 | ||
|
|
d981f0f26e | ||
|
|
44c3f09abe | ||
|
|
0c50c7e99f | ||
|
|
62ed4db110 | ||
|
|
553acee07d | ||
|
|
932cc9838c | ||
|
|
d3c9ceceef | ||
|
|
5f855e56bb | ||
|
|
3f6e21e3b1 | ||
|
|
26d0ad7684 | ||
|
|
9a121ea445 | ||
|
|
c55f22575a | ||
|
|
2795518340 | ||
|
|
2bf2167a18 | ||
|
|
dc7d7054bf | ||
|
|
14473dd51d |
@@ -6,6 +6,7 @@
|
||||
],
|
||||
"plugins": [
|
||||
"transform-runtime",
|
||||
"babel-plugin-transform-es2015-constants",
|
||||
[
|
||||
"module-alias",
|
||||
[
|
||||
|
||||
@@ -0,0 +1,72 @@
|
||||
---
|
||||
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. -->
|
||||
@@ -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 -->
|
||||
@@ -22,7 +22,7 @@ The OpenAPI Specification has undergone 5 revisions since initial creation in 20
|
||||
|
||||
Swagger UI Version | Release Date | OpenAPI Spec compatibility | Notes
|
||||
------------------ | ------------ | -------------------------- | -----
|
||||
3.13.3 | 2018-03-23 | 2.0, 3.0 | [tag v3.13.3](https://github.com/swagger-api/swagger-ui/tree/v3.13.3)
|
||||
3.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.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)
|
||||
|
||||
+35
-67
@@ -16,13 +16,16 @@
|
||||
overflow: -moz-scrollbars-vertical;
|
||||
overflow-y: scroll;
|
||||
}
|
||||
|
||||
*,
|
||||
*:before,
|
||||
*:after
|
||||
{
|
||||
box-sizing: inherit;
|
||||
}
|
||||
body {
|
||||
|
||||
body
|
||||
{
|
||||
margin:0;
|
||||
background: #fafafa;
|
||||
}
|
||||
@@ -30,75 +33,40 @@
|
||||
</head>
|
||||
|
||||
<body>
|
||||
<div id="swagger-ui"></div>
|
||||
|
||||
<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" style="position:absolute;width:0;height:0">
|
||||
<defs>
|
||||
<symbol viewBox="0 0 20 20" id="unlocked">
|
||||
<path d="M15.8 8H14V5.6C14 2.703 12.665 1 10 1 7.334 1 6 2.703 6 5.6V6h2v-.801C8 3.754 8.797 3 10 3c1.203 0 2 .754 2 2.199V8H4c-.553 0-1 .646-1 1.199V17c0 .549.428 1.139.951 1.307l1.197.387C5.672 18.861 6.55 19 7.1 19h5.8c.549 0 1.428-.139 1.951-.307l1.196-.387c.524-.167.953-.757.953-1.306V9.199C17 8.646 16.352 8 15.8 8z"></path>
|
||||
</symbol>
|
||||
<script src="./swagger-ui-bundle.js"> </script>
|
||||
<script src="./swagger-ui-standalone-preset.js"> </script>
|
||||
<script>
|
||||
window.onload = function() {
|
||||
window["SwaggerUIBundle"] = window["swagger-ui-bundle"]
|
||||
window["SwaggerUIStandalonePreset"] = window["swagger-ui-standalone-preset"]
|
||||
// Build a system
|
||||
const ui = SwaggerUIBundle({
|
||||
url: "http://petstore.swagger.io/v2/swagger.json",
|
||||
dom_id: '#swagger-ui',
|
||||
presets: [
|
||||
SwaggerUIBundle.presets.apis,
|
||||
SwaggerUIStandalonePreset
|
||||
],
|
||||
plugins: [
|
||||
SwaggerUIBundle.plugins.DownloadUrl
|
||||
],
|
||||
layout: "StandaloneLayout"
|
||||
})
|
||||
|
||||
<symbol viewBox="0 0 20 20" id="locked">
|
||||
<path d="M15.8 8H14V5.6C14 2.703 12.665 1 10 1 7.334 1 6 2.703 6 5.6V8H4c-.553 0-1 .646-1 1.199V17c0 .549.428 1.139.951 1.307l1.197.387C5.672 18.861 6.55 19 7.1 19h5.8c.549 0 1.428-.139 1.951-.307l1.196-.387c.524-.167.953-.757.953-1.306V9.199C17 8.646 16.352 8 15.8 8zM12 8H8V5.199C8 3.754 8.797 3 10 3c1.203 0 2 .754 2 2.199V8z"/>
|
||||
</symbol>
|
||||
window.ui = ui
|
||||
|
||||
<symbol viewBox="0 0 20 20" id="close">
|
||||
<path d="M14.348 14.849c-.469.469-1.229.469-1.697 0L10 11.819l-2.651 3.029c-.469.469-1.229.469-1.697 0-.469-.469-.469-1.229 0-1.697l2.758-3.15-2.759-3.152c-.469-.469-.469-1.228 0-1.697.469-.469 1.228-.469 1.697 0L10 8.183l2.651-3.031c.469-.469 1.228-.469 1.697 0 .469.469.469 1.229 0 1.697l-2.758 3.152 2.758 3.15c.469.469.469 1.229 0 1.698z"/>
|
||||
</symbol>
|
||||
|
||||
<symbol viewBox="0 0 20 20" id="large-arrow">
|
||||
<path d="M13.25 10L6.109 2.58c-.268-.27-.268-.707 0-.979.268-.27.701-.27.969 0l7.83 7.908c.268.271.268.709 0 .979l-7.83 7.908c-.268.271-.701.27-.969 0-.268-.269-.268-.707 0-.979L13.25 10z"/>
|
||||
</symbol>
|
||||
|
||||
<symbol viewBox="0 0 20 20" id="large-arrow-down">
|
||||
<path d="M17.418 6.109c.272-.268.709-.268.979 0s.271.701 0 .969l-7.908 7.83c-.27.268-.707.268-.979 0l-7.908-7.83c-.27-.268-.27-.701 0-.969.271-.268.709-.268.979 0L10 13.25l7.418-7.141z"/>
|
||||
</symbol>
|
||||
|
||||
|
||||
<symbol viewBox="0 0 24 24" id="jump-to">
|
||||
<path d="M19 7v4H5.83l3.58-3.59L8 6l-6 6 6 6 1.41-1.41L5.83 13H21V7z"/>
|
||||
</symbol>
|
||||
|
||||
<symbol viewBox="0 0 24 24" id="expand">
|
||||
<path d="M10 18h4v-2h-4v2zM3 6v2h18V6H3zm3 7h12v-2H6v2z"/>
|
||||
</symbol>
|
||||
|
||||
</defs>
|
||||
</svg>
|
||||
|
||||
<div id="swagger-ui"></div>
|
||||
|
||||
<script src="./swagger-ui-bundle.js"> </script>
|
||||
<script src="./swagger-ui-standalone-preset.js"> </script>
|
||||
<script>
|
||||
window.onload = function() {
|
||||
window["SwaggerUIBundle"] = window["swagger-ui-bundle"]
|
||||
window["SwaggerUIStandalonePreset"] = window["swagger-ui-standalone-preset"]
|
||||
// Build a system
|
||||
const ui = SwaggerUIBundle({
|
||||
url: "http://petstore.swagger.io/v2/swagger.json",
|
||||
dom_id: '#swagger-ui',
|
||||
presets: [
|
||||
SwaggerUIBundle.presets.apis,
|
||||
SwaggerUIStandalonePreset
|
||||
],
|
||||
plugins: [
|
||||
SwaggerUIBundle.plugins.DownloadUrl
|
||||
],
|
||||
layout: "StandaloneLayout"
|
||||
})
|
||||
|
||||
window.ui = ui
|
||||
|
||||
ui.initOAuth({
|
||||
clientId: "your-client-id",
|
||||
clientSecret: "your-client-secret-if-required",
|
||||
realm: "your-realms",
|
||||
appName: "your-app-name",
|
||||
scopeSeparator: " ",
|
||||
additionalQueryStringParams: {}
|
||||
})
|
||||
}
|
||||
</script>
|
||||
ui.initOAuth({
|
||||
clientId: "your-client-id",
|
||||
clientSecret: "your-client-secret-if-required",
|
||||
realm: "your-realms",
|
||||
appName: "your-app-name",
|
||||
scopeSeparator: " ",
|
||||
additionalQueryStringParams: {}
|
||||
})
|
||||
}
|
||||
</script>
|
||||
</body>
|
||||
|
||||
</html>
|
||||
|
||||
Vendored
+56
-90
@@ -1,95 +1,61 @@
|
||||
<!-- HTML for static distribution bundle build -->
|
||||
<!DOCTYPE html>
|
||||
<html lang="en">
|
||||
<head>
|
||||
<meta charset="UTF-8">
|
||||
<title>Swagger UI</title>
|
||||
<link href="https://fonts.googleapis.com/css?family=Open+Sans:400,700|Source+Code+Pro:300,600|Titillium+Web:400,600,700" rel="stylesheet">
|
||||
<link rel="stylesheet" type="text/css" href="./swagger-ui.css" >
|
||||
<link rel="icon" type="image/png" href="./favicon-32x32.png" sizes="32x32" />
|
||||
<link rel="icon" type="image/png" href="./favicon-16x16.png" sizes="16x16" />
|
||||
<style>
|
||||
html
|
||||
{
|
||||
box-sizing: border-box;
|
||||
overflow: -moz-scrollbars-vertical;
|
||||
overflow-y: scroll;
|
||||
<head>
|
||||
<meta charset="UTF-8">
|
||||
<title>Swagger UI</title>
|
||||
<link href="https://fonts.googleapis.com/css?family=Open+Sans:400,700|Source+Code+Pro:300,600|Titillium+Web:400,600,700" rel="stylesheet">
|
||||
<link rel="stylesheet" type="text/css" href="./swagger-ui.css" >
|
||||
<link rel="icon" type="image/png" href="./favicon-32x32.png" sizes="32x32" />
|
||||
<link rel="icon" type="image/png" href="./favicon-16x16.png" sizes="16x16" />
|
||||
<style>
|
||||
html
|
||||
{
|
||||
box-sizing: border-box;
|
||||
overflow: -moz-scrollbars-vertical;
|
||||
overflow-y: scroll;
|
||||
}
|
||||
|
||||
*,
|
||||
*:before,
|
||||
*:after
|
||||
{
|
||||
box-sizing: inherit;
|
||||
}
|
||||
|
||||
body
|
||||
{
|
||||
margin:0;
|
||||
background: #fafafa;
|
||||
}
|
||||
</style>
|
||||
</head>
|
||||
|
||||
<body>
|
||||
<div id="swagger-ui"></div>
|
||||
|
||||
<script src="./swagger-ui-bundle.js"> </script>
|
||||
<script src="./swagger-ui-standalone-preset.js"> </script>
|
||||
<script>
|
||||
window.onload = function() {
|
||||
|
||||
// Build a system
|
||||
const ui = SwaggerUIBundle({
|
||||
url: "http://petstore.swagger.io/v2/swagger.json",
|
||||
dom_id: '#swagger-ui',
|
||||
deepLinking: true,
|
||||
presets: [
|
||||
SwaggerUIBundle.presets.apis,
|
||||
SwaggerUIStandalonePreset
|
||||
],
|
||||
plugins: [
|
||||
SwaggerUIBundle.plugins.DownloadUrl
|
||||
],
|
||||
layout: "StandaloneLayout"
|
||||
})
|
||||
|
||||
window.ui = ui
|
||||
}
|
||||
*,
|
||||
*:before,
|
||||
*:after
|
||||
{
|
||||
box-sizing: inherit;
|
||||
}
|
||||
|
||||
body {
|
||||
margin:0;
|
||||
background: #fafafa;
|
||||
}
|
||||
</style>
|
||||
</head>
|
||||
|
||||
<body>
|
||||
|
||||
<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" style="position:absolute;width:0;height:0">
|
||||
<defs>
|
||||
<symbol viewBox="0 0 20 20" id="unlocked">
|
||||
<path d="M15.8 8H14V5.6C14 2.703 12.665 1 10 1 7.334 1 6 2.703 6 5.6V6h2v-.801C8 3.754 8.797 3 10 3c1.203 0 2 .754 2 2.199V8H4c-.553 0-1 .646-1 1.199V17c0 .549.428 1.139.951 1.307l1.197.387C5.672 18.861 6.55 19 7.1 19h5.8c.549 0 1.428-.139 1.951-.307l1.196-.387c.524-.167.953-.757.953-1.306V9.199C17 8.646 16.352 8 15.8 8z"></path>
|
||||
</symbol>
|
||||
|
||||
<symbol viewBox="0 0 20 20" id="locked">
|
||||
<path d="M15.8 8H14V5.6C14 2.703 12.665 1 10 1 7.334 1 6 2.703 6 5.6V8H4c-.553 0-1 .646-1 1.199V17c0 .549.428 1.139.951 1.307l1.197.387C5.672 18.861 6.55 19 7.1 19h5.8c.549 0 1.428-.139 1.951-.307l1.196-.387c.524-.167.953-.757.953-1.306V9.199C17 8.646 16.352 8 15.8 8zM12 8H8V5.199C8 3.754 8.797 3 10 3c1.203 0 2 .754 2 2.199V8z"/>
|
||||
</symbol>
|
||||
|
||||
<symbol viewBox="0 0 20 20" id="close">
|
||||
<path d="M14.348 14.849c-.469.469-1.229.469-1.697 0L10 11.819l-2.651 3.029c-.469.469-1.229.469-1.697 0-.469-.469-.469-1.229 0-1.697l2.758-3.15-2.759-3.152c-.469-.469-.469-1.228 0-1.697.469-.469 1.228-.469 1.697 0L10 8.183l2.651-3.031c.469-.469 1.228-.469 1.697 0 .469.469.469 1.229 0 1.697l-2.758 3.152 2.758 3.15c.469.469.469 1.229 0 1.698z"/>
|
||||
</symbol>
|
||||
|
||||
<symbol viewBox="0 0 20 20" id="large-arrow">
|
||||
<path d="M13.25 10L6.109 2.58c-.268-.27-.268-.707 0-.979.268-.27.701-.27.969 0l7.83 7.908c.268.271.268.709 0 .979l-7.83 7.908c-.268.271-.701.27-.969 0-.268-.269-.268-.707 0-.979L13.25 10z"/>
|
||||
</symbol>
|
||||
|
||||
<symbol viewBox="0 0 20 20" id="large-arrow-down">
|
||||
<path d="M17.418 6.109c.272-.268.709-.268.979 0s.271.701 0 .969l-7.908 7.83c-.27.268-.707.268-.979 0l-7.908-7.83c-.27-.268-.27-.701 0-.969.271-.268.709-.268.979 0L10 13.25l7.418-7.141z"/>
|
||||
</symbol>
|
||||
|
||||
|
||||
<symbol viewBox="0 0 24 24" id="jump-to">
|
||||
<path d="M19 7v4H5.83l3.58-3.59L8 6l-6 6 6 6 1.41-1.41L5.83 13H21V7z"/>
|
||||
</symbol>
|
||||
|
||||
<symbol viewBox="0 0 24 24" id="expand">
|
||||
<path d="M10 18h4v-2h-4v2zM3 6v2h18V6H3zm3 7h12v-2H6v2z"/>
|
||||
</symbol>
|
||||
|
||||
</defs>
|
||||
</svg>
|
||||
|
||||
<div id="swagger-ui"></div>
|
||||
|
||||
<script src="./swagger-ui-bundle.js"> </script>
|
||||
<script src="./swagger-ui-standalone-preset.js"> </script>
|
||||
<script>
|
||||
window.onload = function() {
|
||||
|
||||
// Build a system
|
||||
const ui = SwaggerUIBundle({
|
||||
url: "http://petstore.swagger.io/v2/swagger.json",
|
||||
dom_id: '#swagger-ui',
|
||||
deepLinking: true,
|
||||
presets: [
|
||||
SwaggerUIBundle.presets.apis,
|
||||
SwaggerUIStandalonePreset
|
||||
],
|
||||
plugins: [
|
||||
SwaggerUIBundle.plugins.DownloadUrl
|
||||
],
|
||||
layout: "StandaloneLayout"
|
||||
})
|
||||
|
||||
window.ui = ui
|
||||
}
|
||||
</script>
|
||||
</body>
|
||||
|
||||
</script>
|
||||
</body>
|
||||
</html>
|
||||
|
||||
Vendored
+71
-33
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
@@ -18,7 +18,7 @@ class OperationsLayout extends React.Component {
|
||||
getComponent
|
||||
} = this.props
|
||||
|
||||
const Operations = getComponent("Operations", true)
|
||||
const Operations = getComponent("operations", true)
|
||||
|
||||
return (
|
||||
<div>
|
||||
|
||||
@@ -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.
|
||||
|
||||
|
||||
@@ -58,6 +58,7 @@ 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.
|
||||
|
||||
|
||||
+14
-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" },
|
||||
@@ -61,10 +65,10 @@ module.exports = function(rules, options) {
|
||||
}))
|
||||
}
|
||||
|
||||
if( specialOptions.minimize ) { // production mode
|
||||
if( specialOptions.minimize ) { // production mode
|
||||
|
||||
plugins.push(
|
||||
new webpack.optimize.UglifyJsPlugin({
|
||||
new UglifyJsPlugin({
|
||||
sourceMap: true,
|
||||
}),
|
||||
new webpack.LoaderOptionsPlugin({
|
||||
@@ -76,8 +80,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(
|
||||
|
||||
+8
-4
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "swagger-ui",
|
||||
"version": "3.13.3",
|
||||
"version": "3.14.1",
|
||||
"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 --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",
|
||||
@@ -48,10 +48,12 @@
|
||||
"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",
|
||||
"immutable": "^3.x.x",
|
||||
"js-file-download": "^0.4.1",
|
||||
"js-yaml": "^3.5.5",
|
||||
"lodash": "4.17.5",
|
||||
"matcher": "^0.1.2",
|
||||
@@ -79,11 +81,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.6.0",
|
||||
"swagger-client": "^3.8.1",
|
||||
"url-parse": "^1.1.8",
|
||||
"whatwg-fetch": "0.11.1",
|
||||
"worker-loader": "^0.7.1",
|
||||
@@ -98,6 +99,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",
|
||||
@@ -118,6 +120,7 @@
|
||||
"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",
|
||||
@@ -145,6 +148,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"
|
||||
|
||||
@@ -1,11 +1,14 @@
|
||||
import React, { Component } from "react"
|
||||
import PropTypes from "prop-types"
|
||||
import { highlight } from "core/utils"
|
||||
import saveAs from "js-file-download"
|
||||
|
||||
export default class HighlightCode extends Component {
|
||||
static propTypes = {
|
||||
value: PropTypes.string.isRequired,
|
||||
className: PropTypes.string
|
||||
className: PropTypes.string,
|
||||
downloadable: PropTypes.bool,
|
||||
fileName: PropTypes.string
|
||||
}
|
||||
|
||||
componentDidMount() {
|
||||
@@ -20,10 +23,47 @@ export default class HighlightCode extends Component {
|
||||
this.el = c
|
||||
}
|
||||
|
||||
downloadText = () => {
|
||||
saveAs(this.props.value, this.props.fileName || "response.txt")
|
||||
}
|
||||
|
||||
preventYScrollingBeyondElement = (e) => {
|
||||
const target = e.target
|
||||
|
||||
var deltaY = e.nativeEvent.deltaY
|
||||
var contentHeight = target.scrollHeight
|
||||
var visibleHeight = target.offsetHeight
|
||||
var scrollTop = target.scrollTop
|
||||
|
||||
const scrollOffset = visibleHeight + scrollTop
|
||||
|
||||
const isElementScrollable = contentHeight > visibleHeight
|
||||
const isScrollingPastTop = scrollTop === 0 && deltaY < 0
|
||||
const isScrollingPastBottom = scrollOffset >= contentHeight && deltaY > 0
|
||||
|
||||
if (isElementScrollable && (isScrollingPastTop || isScrollingPastBottom)) {
|
||||
e.preventDefault()
|
||||
}
|
||||
}
|
||||
|
||||
render () {
|
||||
let { value, className } = this.props
|
||||
let { value, className, downloadable } = this.props
|
||||
className = className || ""
|
||||
|
||||
return <pre ref={this.initializeComponent} className={className + " microlight"}>{ value }</pre>
|
||||
return (
|
||||
<div className="highlight-code">
|
||||
{ !downloadable ? null :
|
||||
<div className="download-contents" onClick={this.downloadText}>
|
||||
Download
|
||||
</div>
|
||||
}
|
||||
<pre
|
||||
ref={this.initializeComponent}
|
||||
onWheel={this.preventYScrollingBeyondElement}
|
||||
className={className + " microlight"}>
|
||||
{value}
|
||||
</pre>
|
||||
</div>
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -39,6 +39,7 @@ export default class BaseLayout extends React.Component {
|
||||
let schemes = specSelectors.schemes()
|
||||
let servers = specSelectors.servers()
|
||||
|
||||
let SvgAssets = getComponent("SvgAssets")
|
||||
let Info = getComponent("info")
|
||||
let Operations = getComponent("operations", true)
|
||||
let Models = getComponent("Models", true)
|
||||
@@ -78,6 +79,7 @@ export default class BaseLayout extends React.Component {
|
||||
return (
|
||||
|
||||
<div className='swagger-ui'>
|
||||
<SvgAssets />
|
||||
<div>
|
||||
<Errors/>
|
||||
<Row className="information-container">
|
||||
|
||||
@@ -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 } from "core/utils"
|
||||
import { getExtensions, getCommonExtensions } 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 } = getConfigs()
|
||||
const { showExtensions, showCommonExtensions } = getConfigs()
|
||||
|
||||
// const onChangeWrapper = (value) => onChange(param, value)
|
||||
const JsonSchemaForm = getComponent("JsonSchemaForm")
|
||||
@@ -106,15 +106,17 @@ 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 extensions = getExtensions(param)
|
||||
let commonExt = showCommonExtensions ? getCommonExtensions(param) : null
|
||||
let extensions = showExtensions ? getExtensions(param) : null
|
||||
|
||||
let paramItems // undefined
|
||||
let paramEnum // undefined
|
||||
@@ -153,11 +155,16 @@ export default class ParameterRow extends Component {
|
||||
{ param.get("name") }
|
||||
{ !required ? null : <span style={{color: "red"}}> *</span> }
|
||||
</div>
|
||||
<div className="parameter__type">{ type } { itemType && `[${itemType}]` }</div>
|
||||
<div className="parameter__type">
|
||||
{ type }
|
||||
{ itemType && `[${itemType}]` }
|
||||
{ format && <span className="prop-format">(${format})</span>}
|
||||
</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>
|
||||
|
||||
@@ -197,7 +204,7 @@ export default class ParameterRow extends Component {
|
||||
getConfigs={ getConfigs }
|
||||
isExecute={ isExecute }
|
||||
specSelectors={ specSelectors }
|
||||
schema={ schema }
|
||||
schema={ param.get("schema") }
|
||||
example={ bodyParam }/>
|
||||
: null
|
||||
}
|
||||
|
||||
@@ -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
|
||||
@@ -35,25 +35,13 @@ function Markdown({ source, className = "" }) {
|
||||
|
||||
Markdown.propTypes = {
|
||||
source: PropTypes.string.isRequired,
|
||||
className: PropTypes.string.isRequired
|
||||
className: PropTypes.string
|
||||
}
|
||||
|
||||
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"]
|
||||
})
|
||||
}
|
||||
|
||||
@@ -5,7 +5,10 @@ import lowerCase from "lodash/lowerCase"
|
||||
import { extractFileNameFromContentDispositionHeader } from "core/utils"
|
||||
import win from "core/window"
|
||||
|
||||
export default class ResponseBody extends React.Component {
|
||||
export default class ResponseBody extends React.PureComponent {
|
||||
state = {
|
||||
parsedContent: null
|
||||
}
|
||||
|
||||
static propTypes = {
|
||||
content: PropTypes.any.isRequired,
|
||||
@@ -15,9 +18,41 @@ export default class ResponseBody extends React.Component {
|
||||
url: PropTypes.string
|
||||
}
|
||||
|
||||
updateParsedContent = (prevContent) => {
|
||||
const { content } = this.props
|
||||
|
||||
if(prevContent === content) {
|
||||
return
|
||||
}
|
||||
|
||||
if(content && content instanceof Blob) {
|
||||
var reader = new FileReader()
|
||||
reader.onload = () => {
|
||||
this.setState({
|
||||
parsedContent: reader.result
|
||||
})
|
||||
}
|
||||
reader.readAsText(content)
|
||||
} else {
|
||||
this.setState({
|
||||
parsedContent: content.toString()
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
componentDidMount() {
|
||||
this.updateParsedContent(null)
|
||||
}
|
||||
|
||||
componentDidUpdate(prevProps) {
|
||||
this.updateParsedContent(prevProps.content)
|
||||
}
|
||||
|
||||
render() {
|
||||
let { content, contentType, url, headers={}, getComponent } = this.props
|
||||
const { parsedContent } = this.state
|
||||
const HighlightCode = getComponent("highlightCode")
|
||||
const downloadName = "response_" + new Date().getTime()
|
||||
let body, bodyEl
|
||||
url = url || ""
|
||||
|
||||
@@ -66,7 +101,7 @@ export default class ResponseBody extends React.Component {
|
||||
body = "can't parse JSON. Raw result:\n\n" + content
|
||||
}
|
||||
|
||||
bodyEl = <HighlightCode value={ body } />
|
||||
bodyEl = <HighlightCode downloadable fileName={`${downloadName}.json`} value={ body } />
|
||||
|
||||
// XML
|
||||
} else if (/xml/i.test(contentType)) {
|
||||
@@ -74,11 +109,11 @@ export default class ResponseBody extends React.Component {
|
||||
textNodesOnSameLine: true,
|
||||
indentor: " "
|
||||
})
|
||||
bodyEl = <HighlightCode 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 value={ content } />
|
||||
bodyEl = <HighlightCode downloadable fileName={`${downloadName}.html`} value={ content } />
|
||||
|
||||
// Image
|
||||
} else if (/^image\//i.test(contentType)) {
|
||||
@@ -92,10 +127,25 @@ export default class ResponseBody extends React.Component {
|
||||
} else if (/^audio\//i.test(contentType)) {
|
||||
bodyEl = <pre><audio controls><source src={ url } type={ contentType } /></audio></pre>
|
||||
} else if (typeof content === "string") {
|
||||
bodyEl = <HighlightCode value={ content } />
|
||||
bodyEl = <HighlightCode downloadable fileName={`${downloadName}.txt`} value={ content } />
|
||||
} else if ( content.size > 0 ) {
|
||||
// We don't know the contentType, but there was some content returned
|
||||
bodyEl = <div>Unknown response type</div>
|
||||
if(parsedContent) {
|
||||
// We were able to squeeze something out of content
|
||||
// in `updateParsedContent`, so let's display it
|
||||
bodyEl = <div>
|
||||
<p className="i">
|
||||
Unrecognized response type; displaying content as text.
|
||||
</p>
|
||||
<HighlightCode downloadable fileName={`${downloadName}.txt`} value={ parsedContent } />
|
||||
</div>
|
||||
|
||||
} else {
|
||||
// Give up
|
||||
bodyEl = <p className="i">
|
||||
Unrecognized response type; unable to display.
|
||||
</p>
|
||||
}
|
||||
} else {
|
||||
// We don't know the contentType and there was no content returned
|
||||
bodyEl = null
|
||||
|
||||
@@ -37,12 +37,12 @@ export default class Schemes extends React.Component {
|
||||
}
|
||||
|
||||
render() {
|
||||
let { schemes } = this.props
|
||||
let { schemes, currentScheme } = this.props
|
||||
|
||||
return (
|
||||
<label htmlFor="schemes">
|
||||
<span className="schemes-title">Schemes</span>
|
||||
<select onChange={ this.onChange }>
|
||||
<select onChange={ this.onChange } value={currentScheme}>
|
||||
{ schemes.valueSeq().map(
|
||||
( scheme ) => <option value={ scheme } key={ scheme }>{ scheme }</option>
|
||||
).toArray()}
|
||||
|
||||
@@ -0,0 +1,43 @@
|
||||
import React from "react"
|
||||
const SvgAssets = () =>
|
||||
<div>
|
||||
<svg xmlns="http://www.w3.org/2000/svg" xmlnsXlink="http://www.w3.org/1999/xlink" style={{
|
||||
position: "absolute",
|
||||
width: 0,
|
||||
height: 0
|
||||
}}>
|
||||
<defs>
|
||||
<symbol viewBox="0 0 20 20" id="unlocked">
|
||||
<path d="M15.8 8H14V5.6C14 2.703 12.665 1 10 1 7.334 1 6 2.703 6 5.6V6h2v-.801C8 3.754 8.797 3 10 3c1.203 0 2 .754 2 2.199V8H4c-.553 0-1 .646-1 1.199V17c0 .549.428 1.139.951 1.307l1.197.387C5.672 18.861 6.55 19 7.1 19h5.8c.549 0 1.428-.139 1.951-.307l1.196-.387c.524-.167.953-.757.953-1.306V9.199C17 8.646 16.352 8 15.8 8z"></path>
|
||||
</symbol>
|
||||
|
||||
<symbol viewBox="0 0 20 20" id="locked">
|
||||
<path d="M15.8 8H14V5.6C14 2.703 12.665 1 10 1 7.334 1 6 2.703 6 5.6V8H4c-.553 0-1 .646-1 1.199V17c0 .549.428 1.139.951 1.307l1.197.387C5.672 18.861 6.55 19 7.1 19h5.8c.549 0 1.428-.139 1.951-.307l1.196-.387c.524-.167.953-.757.953-1.306V9.199C17 8.646 16.352 8 15.8 8zM12 8H8V5.199C8 3.754 8.797 3 10 3c1.203 0 2 .754 2 2.199V8z"/>
|
||||
</symbol>
|
||||
|
||||
<symbol viewBox="0 0 20 20" id="close">
|
||||
<path d="M14.348 14.849c-.469.469-1.229.469-1.697 0L10 11.819l-2.651 3.029c-.469.469-1.229.469-1.697 0-.469-.469-.469-1.229 0-1.697l2.758-3.15-2.759-3.152c-.469-.469-.469-1.228 0-1.697.469-.469 1.228-.469 1.697 0L10 8.183l2.651-3.031c.469-.469 1.228-.469 1.697 0 .469.469.469 1.229 0 1.697l-2.758 3.152 2.758 3.15c.469.469.469 1.229 0 1.698z"/>
|
||||
</symbol>
|
||||
|
||||
<symbol viewBox="0 0 20 20" id="large-arrow">
|
||||
<path d="M13.25 10L6.109 2.58c-.268-.27-.268-.707 0-.979.268-.27.701-.27.969 0l7.83 7.908c.268.271.268.709 0 .979l-7.83 7.908c-.268.271-.701.27-.969 0-.268-.269-.268-.707 0-.979L13.25 10z"/>
|
||||
</symbol>
|
||||
|
||||
<symbol viewBox="0 0 20 20" id="large-arrow-down">
|
||||
<path d="M17.418 6.109c.272-.268.709-.268.979 0s.271.701 0 .969l-7.908 7.83c-.27.268-.707.268-.979 0l-7.908-7.83c-.27-.268-.27-.701 0-.969.271-.268.709-.268.979 0L10 13.25l7.418-7.141z"/>
|
||||
</symbol>
|
||||
|
||||
|
||||
<symbol viewBox="0 0 24 24" id="jump-to">
|
||||
<path d="M19 7v4H5.83l3.58-3.59L8 6l-6 6 6 6 1.41-1.41L5.83 13H21V7z"/>
|
||||
</symbol>
|
||||
|
||||
<symbol viewBox="0 0 24 24" id="expand">
|
||||
<path d="M10 18h4v-2h-4v2zM3 6v2h18V6H3zm3 7h12v-2H6v2z"/>
|
||||
</symbol>
|
||||
|
||||
</defs>
|
||||
</svg>
|
||||
</div>
|
||||
|
||||
export default SvgAssets
|
||||
+7
-1
@@ -49,6 +49,7 @@ module.exports = function SwaggerUI(opts) {
|
||||
defaultModelExpandDepth: 1,
|
||||
defaultModelsExpandDepth: 1,
|
||||
showExtensions: false,
|
||||
showCommonExtensions: false,
|
||||
supportedSubmitMethods: [
|
||||
"get",
|
||||
"put",
|
||||
@@ -172,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()
|
||||
}
|
||||
|
||||
|
||||
@@ -81,8 +81,8 @@ export function getLineNumberForPath(yaml, path) {
|
||||
* YAML or JSON string
|
||||
* @param {array} path
|
||||
* an array of stings that constructs a
|
||||
* JSON Path similiar to JSON Pointers(RFC 6901). The difference is, each
|
||||
* component of path is an item of the array intead of beinf seperated with
|
||||
* JSON Path similar to JSON Pointers(RFC 6901). The difference is, each
|
||||
* component of path is an item of the array instead of being separated with
|
||||
* slash(/) in a string
|
||||
*/
|
||||
export function positionRangeForPath(yaml, path) {
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
import React from "react"
|
||||
|
||||
// Nothing by default- component can be overriden by another plugin.
|
||||
// Nothing by default- component can be overridden by another plugin.
|
||||
|
||||
export default class JumpToPath extends React.Component {
|
||||
render() {
|
||||
|
||||
@@ -0,0 +1,12 @@
|
||||
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 {}
|
||||
}
|
||||
}
|
||||
@@ -1,46 +1,10 @@
|
||||
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)
|
||||
|
||||
@@ -0,0 +1,25 @@
|
||||
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,8 +16,14 @@ 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
|
||||
})
|
||||
|
||||
@@ -33,7 +33,8 @@ export default class HttpAuth extends React.Component {
|
||||
let { onChange } = this.props
|
||||
let { value, name } = e.target
|
||||
|
||||
let newValue = this.state.value || {}
|
||||
let newValue = Object.assign({}, this.state.value)
|
||||
|
||||
if(name) {
|
||||
newValue[name] = value
|
||||
} else {
|
||||
@@ -53,7 +54,7 @@ export default class HttpAuth extends React.Component {
|
||||
const Markdown = getComponent( "Markdown" )
|
||||
const JumpToPath = getComponent("JumpToPath", true)
|
||||
|
||||
const scheme = schema.get("scheme")
|
||||
const scheme = (schema.get("scheme") || "").toLowerCase()
|
||||
let value = this.getValue()
|
||||
let errors = errSelectors.allErrors().filter( err => err.get("authId") === name)
|
||||
|
||||
@@ -125,7 +126,7 @@ export default class HttpAuth extends React.Component {
|
||||
)
|
||||
}
|
||||
return <div>
|
||||
<em><b>{name}</b> HTTP authentication: unsupported or missing scheme</em>
|
||||
<em><b>{name}</b> HTTP authentication: unsupported scheme {`'${scheme}'`}</em>
|
||||
</div>
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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
|
||||
}
|
||||
|
||||
@@ -67,6 +67,7 @@ import Property from "core/components/property"
|
||||
import TryItOutButton from "core/components/try-it-out-button"
|
||||
import VersionStamp from "core/components/version-stamp"
|
||||
import DeepLink from "core/components/deep-link"
|
||||
import SvgAssets from "core/components/svg-assets"
|
||||
|
||||
import Markdown from "core/components/providers/markdown"
|
||||
|
||||
@@ -130,7 +131,8 @@ export default function() {
|
||||
OperationContainer,
|
||||
DeepLink,
|
||||
InfoUrl,
|
||||
InfoBasePath
|
||||
InfoBasePath,
|
||||
SvgAssets
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
+4
-3
@@ -10,7 +10,7 @@ import { memoizedSampleFromSchema, memoizedCreateXMLExample } from "core/plugins
|
||||
import win from "./window"
|
||||
import cssEscape from "css.escape"
|
||||
|
||||
const DEFAULT_REPONSE_KEY = "default"
|
||||
const DEFAULT_RESPONSE_KEY = "default"
|
||||
|
||||
export const isImmutable = (maybe) => Im.Iterable.isIterable(maybe)
|
||||
|
||||
@@ -128,7 +128,7 @@ export function systemThunkMiddleware(getSystem) {
|
||||
|
||||
export function defaultStatusCode ( responses ) {
|
||||
let codes = responses.keySeq()
|
||||
return codes.contains(DEFAULT_REPONSE_KEY) ? DEFAULT_REPONSE_KEY : codes.filter( key => (key+"")[0] === "2").sort().first()
|
||||
return codes.contains(DEFAULT_RESPONSE_KEY) ? DEFAULT_RESPONSE_KEY : codes.filter( key => (key+"")[0] === "2").sort().first()
|
||||
}
|
||||
|
||||
|
||||
@@ -193,7 +193,7 @@ export function highlight (el) {
|
||||
// running through characters and highlighting
|
||||
while (prev2 = prev1,
|
||||
// escaping if needed (with except for comments)
|
||||
// pervious character will not be therefore
|
||||
// previous character will not be therefore
|
||||
// recognized as a token finalize condition
|
||||
prev1 = tokenType < 7 && prev1 == "\\" ? 1 : chr
|
||||
) {
|
||||
@@ -712,6 +712,7 @@ 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.
|
||||
//
|
||||
|
||||
@@ -6,7 +6,7 @@ Plugins allow you to add
|
||||
- `statePlugins`
|
||||
- `selectors` - query the state
|
||||
- `reducers` - modify the state
|
||||
- `actions` - fire and forget, that will eventually be handled by a reducer. You *can* rely on the result of async actions. But in general its not recommended
|
||||
- `actions` - fire and forget, that will eventually be handled by a reducer. You *can* rely on the result of async actions. But in general it's not recommended
|
||||
- `wrapActions` - replace an action with a wrapped action (useful for hooking into existing `actions`)
|
||||
- `components` - React components
|
||||
- `fn` - commons functions
|
||||
|
||||
@@ -626,6 +626,33 @@
|
||||
}
|
||||
}
|
||||
|
||||
.highlight-code {
|
||||
position: relative;
|
||||
|
||||
> .microlight {
|
||||
overflow-y: auto;
|
||||
max-height: 400px;
|
||||
min-height: 6em;
|
||||
}
|
||||
}
|
||||
|
||||
.download-contents {
|
||||
position: absolute;
|
||||
bottom: 10px;
|
||||
right: 10px;
|
||||
cursor: pointer;
|
||||
background: #7d8293;
|
||||
text-align: center;
|
||||
padding: 5px;
|
||||
border-radius: 4px;
|
||||
font-family: 'Titillium Web', sans-serif;
|
||||
font-weight: 600;
|
||||
color: white;
|
||||
font-size: 14px;
|
||||
height: 30px;
|
||||
width: 75px;
|
||||
}
|
||||
|
||||
.scheme-container
|
||||
{
|
||||
margin: 0 0 20px 0;
|
||||
|
||||
@@ -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() {
|
||||
|
||||
@@ -28,7 +28,7 @@ describe("oauth2", function () {
|
||||
expect(win.open.calls[0].arguments[0]).toMatch("https://testAuthorizationUrl?response_type=code&redirect_uri=&state=")
|
||||
})
|
||||
|
||||
it("should append query paramters to authorizeUrl with query parameters", function() {
|
||||
it("should append query parameters to authorizeUrl with query parameters", function() {
|
||||
win.open = createSpy()
|
||||
mockSchema.authorizationUrl = "https://testAuthorizationUrl?param=1"
|
||||
oauth2Authorize(authConfig)
|
||||
|
||||
@@ -0,0 +1,27 @@
|
||||
/* 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)
|
||||
})
|
||||
})
|
||||
})
|
||||
+21
-1
@@ -1,6 +1,6 @@
|
||||
/* eslint-env mocha */
|
||||
import expect from "expect"
|
||||
import { fromJS, OrderedMap } from "immutable"
|
||||
import { Map, fromJS, OrderedMap } from "immutable"
|
||||
import {
|
||||
mapToList,
|
||||
parseSearch,
|
||||
@@ -20,6 +20,8 @@ import {
|
||||
getAcceptControllingResponse,
|
||||
createDeepLinkPath,
|
||||
escapeDeepLinkPath,
|
||||
getExtensions,
|
||||
getCommonExtensions,
|
||||
sanitizeUrl,
|
||||
extractFileNameFromContentDispositionHeader,
|
||||
deeplyStripKey
|
||||
@@ -943,6 +945,24 @@ 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 = {
|
||||
|
||||
@@ -0,0 +1,44 @@
|
||||
describe("bug #4196: HTTP basic auth credential retention", function () {
|
||||
let mainPage
|
||||
beforeEach(function (client, done) {
|
||||
mainPage = client
|
||||
.url("localhost:3230")
|
||||
.page.main()
|
||||
|
||||
client.waitForElementVisible(".download-url-input", 5000)
|
||||
.pause(80)
|
||||
.clearValue(".download-url-input")
|
||||
.setValue(".download-url-input", "http://localhost:3230/test-specs/bugs/4196.yaml")
|
||||
.click("button.download-url-button")
|
||||
.pause(1000)
|
||||
|
||||
done()
|
||||
})
|
||||
afterEach(function (client, done) {
|
||||
done()
|
||||
})
|
||||
it("should display the most recent auth data across modal close/opens", function (client) {
|
||||
client.waitForElementVisible(".opblock-tag-section", 10000)
|
||||
.click("button.btn.authorize") // Open modal
|
||||
.waitForElementVisible("section>input", 5000)
|
||||
.setValue("section>input", "aaa") // Set user
|
||||
.waitForElementVisible(`section>input[type="password"]`, 5000)
|
||||
.setValue(`section>input[type="password"]`, "aaa") // Set password
|
||||
.click(".auth-btn-wrapper button:nth-child(1)") // Click Authorize
|
||||
.assert.containsText("div.wrapper:nth-child(4)>code", "aaa")
|
||||
.click(".auth-btn-wrapper button:nth-child(2)") // Close modal
|
||||
.pause(50)
|
||||
.click("button.btn.authorize") // Open modal
|
||||
.pause(50)
|
||||
.click(".auth-btn-wrapper button:nth-child(1)") // Logout
|
||||
.waitForElementVisible("section>input", 5000)
|
||||
.setValue("section>input", "bbb") // Set user
|
||||
.waitForElementVisible(`section>input[type="password"]`, 5000)
|
||||
.setValue(`section>input[type="password"]`, "bbb") // Set password
|
||||
.click(".auth-btn-wrapper button:nth-child(1)") // Click Authorize
|
||||
.pause(5000)
|
||||
.assert.containsText("div.wrapper:nth-child(4)>code", "bbb")
|
||||
|
||||
client.end()
|
||||
})
|
||||
})
|
||||
@@ -0,0 +1,32 @@
|
||||
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()
|
||||
})
|
||||
})
|
||||
@@ -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()
|
||||
})
|
||||
})
|
||||
@@ -71,6 +71,16 @@ describe("render pet api container", function () {
|
||||
client.end()
|
||||
})
|
||||
|
||||
it("Testing post /pet api model values", function (client) {
|
||||
apiWrapper.waitForElementVisible("@petOperationPostContainer", 5000)
|
||||
.click("@petOperationPostCollpase")
|
||||
.waitForElementVisible("@petOperationPostCollapseContainer", 5000)
|
||||
.click("a.tablinks[data-name=model]")
|
||||
.assert.containsText("span.model-title > .model-title__text", `Pet`)
|
||||
|
||||
client.end()
|
||||
})
|
||||
|
||||
it("render put /pet api container", function (client) {
|
||||
apiWrapper.waitForElementVisible("@petOperationPutContainer", 5000)
|
||||
.assert.containsText("@petOperationPutTitle", "/pet")
|
||||
@@ -81,10 +91,10 @@ describe("render pet api container", function () {
|
||||
.waitForElementVisible("@petOperationPutExecuteBtn", 1000)
|
||||
.click("@petOperationPutTryBtn")
|
||||
.assert.cssClassNotPresent("@petOperationPutTryBtn", "cancel")
|
||||
|
||||
|
||||
client.end()
|
||||
})
|
||||
|
||||
|
||||
it("Testing put /pet api Mock data", function (client) {
|
||||
apiWrapper.waitForElementVisible("@petOperationPutContainer", 5000)
|
||||
.click("@petOperationPutCollpase")
|
||||
@@ -115,7 +125,7 @@ describe("render pet api container", function () {
|
||||
.waitForElementVisible("@petOperationGetByTagExecuteBtn", 1000)
|
||||
.click("@petOperationGetByTagTryBtn")
|
||||
.assert.cssClassNotPresent("@petOperationGetByTagTryBtn", "cancel")
|
||||
|
||||
|
||||
client.end()
|
||||
})
|
||||
|
||||
@@ -138,7 +148,7 @@ describe("render pet api container", function () {
|
||||
|
||||
client.end()
|
||||
})
|
||||
|
||||
|
||||
it("render get by ID /pet/{petId} api container", function (client) {
|
||||
apiWrapper.waitForElementVisible("@petOperationGetByIdContainer", 5000)
|
||||
.assert.containsText("@petOperationGetByIdTitle", "/pet/{petId}")
|
||||
@@ -148,7 +158,7 @@ describe("render pet api container", function () {
|
||||
.waitForElementVisible("@petOperationGetByTagExecuteBtn", 1000)
|
||||
.click("@petOperationGetByTagTryBtn")
|
||||
.assert.cssClassNotPresent("@petOperationGetByTagTryBtn", "cancel")
|
||||
|
||||
|
||||
client.end()
|
||||
})
|
||||
|
||||
@@ -167,7 +177,7 @@ describe("render pet api container", function () {
|
||||
.assert.attributeEquals("@petOperationGetByIdParameter", "title", "Value must be an integer")
|
||||
.click("@petOperationGetByTagTryBtn")
|
||||
.assert.cssClassNotPresent("@petOperationGetByTagTryBtn", "cancel")
|
||||
|
||||
|
||||
client.end()
|
||||
})
|
||||
|
||||
@@ -180,10 +190,10 @@ describe("render pet api container", function () {
|
||||
.waitForElementVisible("@petOperationDeleteExecuteBtn", 1000)
|
||||
.click("@petOperationDeleteTryBtn")
|
||||
.assert.cssClassNotPresent("@petOperationDeleteTryBtn", "cancel")
|
||||
|
||||
|
||||
client.end()
|
||||
})
|
||||
|
||||
|
||||
it("Testing delete /pet api Mock data", function (client) {
|
||||
apiWrapper.waitForElementVisible("@petOperationDeleteContainer", 3000)
|
||||
.click("@petOperationDeleteCollpase")
|
||||
@@ -203,4 +213,4 @@ describe("render pet api container", function () {
|
||||
|
||||
client.end()
|
||||
})
|
||||
})
|
||||
})
|
||||
|
||||
@@ -19,7 +19,7 @@ describe("Remote $ref rendering", function () {
|
||||
})
|
||||
|
||||
it("renders a remote $ref correctly", function (client) {
|
||||
mainPage.expect.element("#model-TestResponse > span > div > span > span > span.inner-object > table > tbody > tr:nth-child(2) > td:nth-child(2) > span > span > div > div > p").text.to.equal("this is a api2prop")
|
||||
mainPage.expect.element("#model-TestResponse > span > div > span > span > span.inner-object > table > tbody > tr:nth-child(2) > td:nth-child(2) > span > span > div > div > p").text.to.equal("this is an api2prop")
|
||||
|
||||
client.end()
|
||||
})
|
||||
|
||||
@@ -0,0 +1,85 @@
|
||||
openapi: 3.0.0
|
||||
info:
|
||||
title: Demo API
|
||||
description: First test
|
||||
termsOfService: 'http://demo.io/terms-of-service/'
|
||||
contact:
|
||||
name: Demo Support
|
||||
email: support@demo.io
|
||||
version: 1.0.0
|
||||
servers:
|
||||
- url: '{server}/v1'
|
||||
variables:
|
||||
server:
|
||||
default: https://api.demo.io
|
||||
description: the API endpoint
|
||||
|
||||
paths:
|
||||
/session:
|
||||
put:
|
||||
summary: Returns a new authentication token
|
||||
tags:
|
||||
- session
|
||||
security:
|
||||
- basicAuth: []
|
||||
responses:
|
||||
'201':
|
||||
description: A session object
|
||||
content:
|
||||
application/json:
|
||||
schema:
|
||||
allOf:
|
||||
- type: object
|
||||
properties:
|
||||
user_id:
|
||||
type: string
|
||||
format: uuid
|
||||
readOnly: true
|
||||
example: 110e8400-e29b-11d4-a716-446655440000
|
||||
- $ref: '#/components/schemas/Session'
|
||||
'401':
|
||||
$ref: '#/components/responses/Unauthorized'
|
||||
|
||||
components:
|
||||
securitySchemes:
|
||||
basicAuth:
|
||||
type: http
|
||||
scheme: basic
|
||||
bearerAuth:
|
||||
type: http
|
||||
scheme: bearer
|
||||
bearerFormat: JWT
|
||||
schemas:
|
||||
Session:
|
||||
required:
|
||||
- token
|
||||
properties:
|
||||
token:
|
||||
type: string
|
||||
readOnly: true
|
||||
example: >-
|
||||
eyJhbGciOiJSUzI1NiIsInR5cCI6IkpXVCJ9.eyJzdWIiOiIxMjM0NTY3ODkwIiwibmFtZSI6IkpvaG4gRG9lIiwiYWRtaW4iOnRydWV9.EkN-DOsnsuRjRO6BxXemmJDm3HbxrbRzXglbN2S4sOkopdU4IsDxTI8jO19W_A4K8ZPJijNLis4EZsHeY559a4DFOd50_OqgHGuERTqYZyuhtF39yxJPAjUESwxk2J5k_4zM3O-vtd1Ghyo4IbqKKSy6J9mTniYJPenn5-HIirE
|
||||
|
||||
Error:
|
||||
required:
|
||||
- message
|
||||
properties:
|
||||
message:
|
||||
description: a human readable message explaining the error
|
||||
type: string
|
||||
reason:
|
||||
description: a functionnal key about the error
|
||||
type: string
|
||||
responses:
|
||||
Unauthorized:
|
||||
description: Not authenticated
|
||||
content:
|
||||
application/json:
|
||||
schema:
|
||||
$ref: '#/components/schemas/Error'
|
||||
Default:
|
||||
description: unexpected error
|
||||
content:
|
||||
application/json:
|
||||
schema:
|
||||
$ref: '#/components/schemas/Error'
|
||||
@@ -0,0 +1,64 @@
|
||||
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
|
||||
@@ -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"
|
||||
@@ -21,7 +21,7 @@ components:
|
||||
schemas:
|
||||
Api2Prop:
|
||||
type: string
|
||||
description: this is a api2prop
|
||||
description: this is an api2prop
|
||||
example: 'api1prop-value'
|
||||
|
||||
TestResponse2:
|
||||
|
||||
@@ -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)
|
||||
Reference in New Issue
Block a user