Merge branch 'master' into bug/SWAGGER_JSON-doc-fix
This commit is contained in:
6
.github/issue_template.md
vendored
6
.github/issue_template.md
vendored
@@ -14,6 +14,10 @@ or anything that violates the specifications.
|
|||||||
|
|
||||||
<!--- Provide a general summary of the issue in the title above -->
|
<!--- 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/version-detection.md
|
||||||
|
--->
|
||||||
|
|
||||||
|
|
||||||
| Q | A
|
| Q | A
|
||||||
| ------------------------------- | -------
|
| ------------------------------- | -------
|
||||||
@@ -21,7 +25,7 @@ or anything that violates the specifications.
|
|||||||
| Which Swagger/OpenAPI version? |
|
| Which Swagger/OpenAPI version? |
|
||||||
| Which Swagger-UI version? |
|
| Which Swagger-UI version? |
|
||||||
| How did you install Swagger-UI? |
|
| How did you install Swagger-UI? |
|
||||||
| Which broswer & version? |
|
| Which browser & version? |
|
||||||
| Which operating system? |
|
| Which operating system? |
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@@ -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
|
Swagger UI Version | Release Date | OpenAPI Spec compatibility | Notes
|
||||||
------------------ | ------------ | -------------------------- | -----
|
------------------ | ------------ | -------------------------- | -----
|
||||||
3.1.5 | 2017-08-11 | 2.0, 3.0 | [tag v3.1.5](https://github.com/swagger-api/swagger-ui/tree/v3.1.5)
|
3.2.0 | 2017-09-08 | 2.0, 3.0 | [tag v3.2.0](https://github.com/swagger-api/swagger-ui/tree/v3.2.0)
|
||||||
3.0.21 | 2017-07-26 | 2.0 | [tag v3.0.21](https://github.com/swagger-api/swagger-ui/tree/v3.0.21)
|
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.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)
|
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)
|
||||||
@@ -160,6 +160,9 @@ displayRequestDuration | Controls the display of the request duration (in millis
|
|||||||
maxDisplayedTags | If set, limits the number of tagged operations displayed to at most this many. The default is to show all operations.
|
maxDisplayedTags | If set, limits the number of tagged operations displayed to at most this many. The default is to show all operations.
|
||||||
filter | If set, enables filtering. The top bar will show an edit box that you can use to filter the tagged operations that are shown. Can be true/false to enable or disable, or an explicit filter string in which case filtering will be enabled using that string as the filter expression. Filtering is case sensitive matching the filter expression anywhere inside the tag.
|
filter | If set, enables filtering. The top bar will show an edit box that you can use to filter the tagged operations that are shown. Can be true/false to enable or disable, or an explicit filter string in which case filtering will be enabled using that string as the filter expression. Filtering is case sensitive matching the filter expression anywhere inside the tag.
|
||||||
deepLinking | If set to `true`, enables dynamic deep linking for tags and operations. [Docs](https://github.com/swagger-api/swagger-ui/blob/master/docs/deep-linking.md)
|
deepLinking | If set to `true`, enables dynamic deep linking for tags and operations. [Docs](https://github.com/swagger-api/swagger-ui/blob/master/docs/deep-linking.md)
|
||||||
|
requestInterceptor | MUST be a function. Function to intercept try-it-out requests. Accepts one argument requestInterceptor(request) and must return the potentially modified request.
|
||||||
|
responseInterceptor | MUST be a function. Function to intercept try-it-out responses. Accepts one argument responseInterceptor(response) and must return the potentially modified response.
|
||||||
|
showMutatedRequest | If set to `true` (the default), uses the mutated request returned from a rquestInterceptor to produce the curl command in the UI, otherwise the request before the requestInterceptor was applied is used.
|
||||||
|
|
||||||
### Plugins
|
### Plugins
|
||||||
|
|
||||||
|
|||||||
@@ -11,7 +11,11 @@
|
|||||||
var redirectUrl = oauth2.redirectUrl;
|
var redirectUrl = oauth2.redirectUrl;
|
||||||
var isValid, qp, arr;
|
var isValid, qp, arr;
|
||||||
|
|
||||||
qp = (window.location.hash || location.search).substring(1);
|
if (/code|token|error/.test(window.location.hash)) {
|
||||||
|
qp = window.location.hash.substring(1);
|
||||||
|
} else {
|
||||||
|
qp = location.search.substring(1);
|
||||||
|
}
|
||||||
|
|
||||||
arr = qp.split("&")
|
arr = qp.split("&")
|
||||||
arr.forEach(function (v,i,_arr) { _arr[i] = '"' + v.replace('=', '":"') + '"';})
|
arr.forEach(function (v,i,_arr) { _arr[i] = '"' + v.replace('=', '":"') + '"';})
|
||||||
|
|||||||
6
dist/oauth2-redirect.html
vendored
6
dist/oauth2-redirect.html
vendored
@@ -11,7 +11,11 @@
|
|||||||
var redirectUrl = oauth2.redirectUrl;
|
var redirectUrl = oauth2.redirectUrl;
|
||||||
var isValid, qp, arr;
|
var isValid, qp, arr;
|
||||||
|
|
||||||
qp = (window.location.hash || location.search).substring(1);
|
if (/code|token|error/.test(window.location.hash)) {
|
||||||
|
qp = window.location.hash.substring(1);
|
||||||
|
} else {
|
||||||
|
qp = location.search.substring(1);
|
||||||
|
}
|
||||||
|
|
||||||
arr = qp.split("&")
|
arr = qp.split("&")
|
||||||
arr.forEach(function (v,i,_arr) { _arr[i] = '"' + v.replace('=', '":"') + '"';})
|
arr.forEach(function (v,i,_arr) { _arr[i] = '"' + v.replace('=', '":"') + '"';})
|
||||||
|
|||||||
22
dist/swagger-ui-bundle.js
vendored
22
dist/swagger-ui-bundle.js
vendored
File diff suppressed because one or more lines are too long
2
dist/swagger-ui-bundle.js.map
vendored
2
dist/swagger-ui-bundle.js.map
vendored
@@ -1 +1 @@
|
|||||||
{"version":3,"file":"swagger-ui-bundle.js","sources":["webpack:///swagger-ui-bundle.js"],"mappings":"AAAA;;;;;AAoyKA;;;;;;AAm/EA;;;;;;;;;;;;;;;;;;;;;;;;;;AAs6TA;;;;;;;;;;;;;;AAs8JA;;;;;;;;;AAogpBA;;;;;AAk1QA;AAm4DA;;;;;;AAo4YA;;;;;;AA8jaA;AAumvBA","sourceRoot":""}
|
{"version":3,"file":"swagger-ui-bundle.js","sources":["webpack:///swagger-ui-bundle.js"],"mappings":"AAAA;;;;;AAu7LA;;;;;;AA65DA;;;;;;;;;;;;;;;;;;;;;;;;;;AA68TA;;;;;;;;;;;;;;AAs8JA;;;;;;;;;AA69pBA;;;;;AA81QA;AAm4DA;;;;;;AAo4YA;;;;;;AA0iaA;AA4lvBA","sourceRoot":""}
|
||||||
6
dist/swagger-ui-standalone-preset.js
vendored
6
dist/swagger-ui-standalone-preset.js
vendored
File diff suppressed because one or more lines are too long
2
dist/swagger-ui-standalone-preset.js.map
vendored
2
dist/swagger-ui-standalone-preset.js.map
vendored
@@ -1 +1 @@
|
|||||||
{"version":3,"file":"swagger-ui-standalone-preset.js","sources":["webpack:///swagger-ui-standalone-preset.js"],"mappings":"AAAA;;;;;AA21CA;;;;;;AAspFA","sourceRoot":""}
|
{"version":3,"file":"swagger-ui-standalone-preset.js","sources":["webpack:///swagger-ui-standalone-preset.js"],"mappings":"AAAA;;;;;AA80CA;;;;;;AAqpFA","sourceRoot":""}
|
||||||
2
dist/swagger-ui.css
vendored
2
dist/swagger-ui.css
vendored
File diff suppressed because one or more lines are too long
4
dist/swagger-ui.js
vendored
4
dist/swagger-ui.js
vendored
File diff suppressed because one or more lines are too long
2
dist/swagger-ui.js.map
vendored
2
dist/swagger-ui.js.map
vendored
@@ -1 +1 @@
|
|||||||
{"version":3,"file":"swagger-ui.js","sources":["webpack:///swagger-ui.js"],"mappings":"AAAA;;;;;;AA0/cA","sourceRoot":""}
|
{"version":3,"file":"swagger-ui.js","sources":["webpack:///swagger-ui.js"],"mappings":"AAAA;;;;;;AAokeA","sourceRoot":""}
|
||||||
BIN
docs/images/swagger-ui2.png
Normal file
BIN
docs/images/swagger-ui2.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 390 KiB |
BIN
docs/images/swagger-ui3.png
Normal file
BIN
docs/images/swagger-ui3.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 297 KiB |
54
docs/version-detection.md
Normal file
54
docs/version-detection.md
Normal file
@@ -0,0 +1,54 @@
|
|||||||
|
# Detecting your Swagger-UI version
|
||||||
|
|
||||||
|
At times, you're going to need to know which version of Swagger-UI you use.
|
||||||
|
|
||||||
|
The first step would be to detect which major version you currently use, as the method of detecting the version has changed. If your Swagger-UI has been heavily modified and you cannot detect from the look and feel which major version you use, you'd have to try both methods to get the exact version.
|
||||||
|
|
||||||
|
To help you visually detect which version you're using, we've included supporting images.
|
||||||
|
|
||||||
|
|
||||||
|
# Swagger-UI 3.X
|
||||||
|
|
||||||
|

|
||||||
|
|
||||||
|
Some distinct identifiers to Swagger-UI 3.X:
|
||||||
|
- The API version appears as a badge next to its title.
|
||||||
|
- If there are schemes or authorizations, they'd appear in a bar above the operations.
|
||||||
|
- Try it out functionality is not enabled by default.
|
||||||
|
- All the response codes in the operations appear at after the parameters.
|
||||||
|
- There's a models section after the operations.
|
||||||
|
|
||||||
|
If you've determined this is the version you have, to find the exact version:
|
||||||
|
- Open your browser's web console (changes between browsers)
|
||||||
|
- Type `versions` in the console and execute the call.
|
||||||
|
- You might need to expand the result, until you get a string similar to `swaggerUi : Object { version: "3.1.6", gitRevision: "g786cd47", gitDirty: true, … }`.
|
||||||
|
- The version taken from that example would be `3.1.6`.
|
||||||
|
|
||||||
|
Note: This functionality was added in 3.0.8. If you're unable to execute it, you're likely to use an older version, and in that case the first step would be to upgrade.
|
||||||
|
|
||||||
|
|
||||||
|
# Swagger-UI 2.X and under
|
||||||
|
|
||||||
|

|
||||||
|
|
||||||
|
Some distinct identifiers to Swagger-UI 3.X:
|
||||||
|
- The API version appears at the bottom of the page.
|
||||||
|
- Schemes are not rendered.
|
||||||
|
- Authorization, if rendered, will appear next to the navigation bar.
|
||||||
|
- Try it out functionality is enabled by default.
|
||||||
|
- The successful response code would appear above the parameters, the rest below them.
|
||||||
|
- There's no models section after the operations.
|
||||||
|
|
||||||
|
If you've determined this is the version you have, to find the exact version:
|
||||||
|
- Navigate to the sources of the UI. Either on your disk or via the view page source functionality in your browser.
|
||||||
|
- Find an open the `swagger-ui.js`
|
||||||
|
- At the top of the page, there would be a comment containing the exact version of swagger-ui. This example shows version `2.2.9`:
|
||||||
|
|
||||||
|
```
|
||||||
|
/**
|
||||||
|
* swagger-ui - Swagger UI is a dependency-free collection of HTML, JavaScript, and CSS assets that dynamically generate beautiful documentation from a Swagger-compliant API
|
||||||
|
* @version v2.2.9
|
||||||
|
* @link http://swagger.io
|
||||||
|
* @license Apache-2.0
|
||||||
|
*/
|
||||||
|
```
|
||||||
@@ -1,6 +1,6 @@
|
|||||||
{
|
{
|
||||||
"name": "swagger-ui",
|
"name": "swagger-ui",
|
||||||
"version": "3.1.5",
|
"version": "3.2.0",
|
||||||
"main": "dist/swagger-ui.js",
|
"main": "dist/swagger-ui.js",
|
||||||
"repository": "git@github.com:swagger-api/swagger-ui.git",
|
"repository": "git@github.com:swagger-api/swagger-ui.git",
|
||||||
"contributors": [
|
"contributors": [
|
||||||
@@ -75,7 +75,7 @@
|
|||||||
"scroll-to-element": "^2.0.0",
|
"scroll-to-element": "^2.0.0",
|
||||||
"serialize-error": "2.0.0",
|
"serialize-error": "2.0.0",
|
||||||
"shallowequal": "0.2.2",
|
"shallowequal": "0.2.2",
|
||||||
"swagger-client": "3.0.20",
|
"swagger-client": "3.1.0",
|
||||||
"url-parse": "^1.1.8",
|
"url-parse": "^1.1.8",
|
||||||
"whatwg-fetch": "0.11.1",
|
"whatwg-fetch": "0.11.1",
|
||||||
"worker-loader": "^0.7.1",
|
"worker-loader": "^0.7.1",
|
||||||
|
|||||||
@@ -8,6 +8,8 @@ export default class BaseLayout extends React.Component {
|
|||||||
errActions: PropTypes.object.isRequired,
|
errActions: PropTypes.object.isRequired,
|
||||||
specActions: PropTypes.object.isRequired,
|
specActions: PropTypes.object.isRequired,
|
||||||
specSelectors: PropTypes.object.isRequired,
|
specSelectors: PropTypes.object.isRequired,
|
||||||
|
oas3Selectors: PropTypes.object.isRequired,
|
||||||
|
oas3Actions: PropTypes.object.isRequired,
|
||||||
layoutSelectors: PropTypes.object.isRequired,
|
layoutSelectors: PropTypes.object.isRequired,
|
||||||
layoutActions: PropTypes.object.isRequired,
|
layoutActions: PropTypes.object.isRequired,
|
||||||
getComponent: PropTypes.func.isRequired
|
getComponent: PropTypes.func.isRequired
|
||||||
@@ -19,7 +21,14 @@ export default class BaseLayout extends React.Component {
|
|||||||
}
|
}
|
||||||
|
|
||||||
render() {
|
render() {
|
||||||
let { specSelectors, specActions, getComponent, layoutSelectors } = this.props
|
let {
|
||||||
|
specSelectors,
|
||||||
|
specActions,
|
||||||
|
getComponent,
|
||||||
|
layoutSelectors,
|
||||||
|
oas3Selectors,
|
||||||
|
oas3Actions
|
||||||
|
} = this.props
|
||||||
|
|
||||||
let info = specSelectors.info()
|
let info = specSelectors.info()
|
||||||
let url = specSelectors.url()
|
let url = specSelectors.url()
|
||||||
@@ -28,6 +37,7 @@ export default class BaseLayout extends React.Component {
|
|||||||
let securityDefinitions = specSelectors.securityDefinitions()
|
let securityDefinitions = specSelectors.securityDefinitions()
|
||||||
let externalDocs = specSelectors.externalDocs()
|
let externalDocs = specSelectors.externalDocs()
|
||||||
let schemes = specSelectors.schemes()
|
let schemes = specSelectors.schemes()
|
||||||
|
let servers = specSelectors.servers()
|
||||||
|
|
||||||
let Info = getComponent("info")
|
let Info = getComponent("info")
|
||||||
let Operations = getComponent("operations", true)
|
let Operations = getComponent("operations", true)
|
||||||
@@ -35,6 +45,7 @@ export default class BaseLayout extends React.Component {
|
|||||||
let AuthorizeBtn = getComponent("authorizeBtn", true)
|
let AuthorizeBtn = getComponent("authorizeBtn", true)
|
||||||
let Row = getComponent("Row")
|
let Row = getComponent("Row")
|
||||||
let Col = getComponent("Col")
|
let Col = getComponent("Col")
|
||||||
|
let Servers = getComponent("Servers")
|
||||||
let Errors = getComponent("errors", true)
|
let Errors = getComponent("errors", true)
|
||||||
|
|
||||||
let isLoading = specSelectors.loadingStatus() === "loading"
|
let isLoading = specSelectors.loadingStatus() === "loading"
|
||||||
@@ -82,6 +93,22 @@ export default class BaseLayout extends React.Component {
|
|||||||
</div>
|
</div>
|
||||||
) : null }
|
) : null }
|
||||||
|
|
||||||
|
{ servers && servers.size ? (
|
||||||
|
<div className="server-container">
|
||||||
|
<Col className="servers wrapper" mobile={12}>
|
||||||
|
<Servers
|
||||||
|
servers={servers}
|
||||||
|
currentServer={oas3Selectors.selectedServer()}
|
||||||
|
setSelectedServer={oas3Actions.setSelectedServer}
|
||||||
|
setServerVariableValue={oas3Actions.setServerVariableValue}
|
||||||
|
getServerVariable={oas3Selectors.serverVariableValue}
|
||||||
|
getEffectiveServerValue={oas3Selectors.serverEffectiveValue}
|
||||||
|
/>
|
||||||
|
</Col>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
) : null}
|
||||||
|
|
||||||
{
|
{
|
||||||
filter === null || filter === false ? null :
|
filter === null || filter === false ? null :
|
||||||
<div className="filter-container">
|
<div className="filter-container">
|
||||||
|
|||||||
@@ -29,13 +29,18 @@ Duration.propTypes = {
|
|||||||
export default class LiveResponse extends React.Component {
|
export default class LiveResponse extends React.Component {
|
||||||
static propTypes = {
|
static propTypes = {
|
||||||
response: PropTypes.object.isRequired,
|
response: PropTypes.object.isRequired,
|
||||||
|
specSelectors: PropTypes.object.isRequired,
|
||||||
|
pathMethod: PropTypes.object.isRequired,
|
||||||
getComponent: PropTypes.func.isRequired,
|
getComponent: PropTypes.func.isRequired,
|
||||||
displayRequestDuration: PropTypes.bool.isRequired
|
displayRequestDuration: PropTypes.bool.isRequired,
|
||||||
|
getConfigs: PropTypes.func.isRequired
|
||||||
}
|
}
|
||||||
|
|
||||||
render() {
|
render() {
|
||||||
const { request, response, getComponent, displayRequestDuration } = this.props
|
const { response, getComponent, getConfigs, displayRequestDuration, specSelectors, pathMethod } = this.props
|
||||||
|
const { showMutatedRequest } = getConfigs()
|
||||||
|
|
||||||
|
const curlRequest = showMutatedRequest ? specSelectors.mutatedRequestFor(pathMethod[0], pathMethod[1]) : specSelectors.requestFor(pathMethod[0], pathMethod[1])
|
||||||
const status = response.get("status")
|
const status = response.get("status")
|
||||||
const url = response.get("url")
|
const url = response.get("url")
|
||||||
const headers = response.get("headers").toJS()
|
const headers = response.get("headers").toJS()
|
||||||
@@ -55,7 +60,7 @@ export default class LiveResponse extends React.Component {
|
|||||||
|
|
||||||
return (
|
return (
|
||||||
<div>
|
<div>
|
||||||
{ request && <Curl request={ request }/> }
|
{ curlRequest && <Curl request={ curlRequest }/> }
|
||||||
<h4>Server response</h4>
|
<h4>Server response</h4>
|
||||||
<table className="responses-table">
|
<table className="responses-table">
|
||||||
<thead>
|
<thead>
|
||||||
|
|||||||
@@ -163,8 +163,8 @@ export default class Operation extends PureComponent {
|
|||||||
<span className={ deprecated ? "opblock-summary-path__deprecated" : "opblock-summary-path" } >
|
<span className={ deprecated ? "opblock-summary-path__deprecated" : "opblock-summary-path" } >
|
||||||
<a
|
<a
|
||||||
className="nostyle"
|
className="nostyle"
|
||||||
onClick={(e) => e.preventDefault()}
|
onClick={isDeepLinkingEnabled ? (e) => e.preventDefault() : null}
|
||||||
href={ isDeepLinkingEnabled ? `#/${isShownKey[1]}/${isShownKey[2]}` : ""} >
|
href={isDeepLinkingEnabled ? `#/${isShownKey[1]}/${isShownKey[2]}` : null}>
|
||||||
<span>{path}</span>
|
<span>{path}</span>
|
||||||
</a>
|
</a>
|
||||||
<JumpToPath path={jumpToKey} />
|
<JumpToPath path={jumpToKey} />
|
||||||
@@ -263,6 +263,7 @@ export default class Operation extends PureComponent {
|
|||||||
request={ request }
|
request={ request }
|
||||||
tryItOutResponse={ response }
|
tryItOutResponse={ response }
|
||||||
getComponent={ getComponent }
|
getComponent={ getComponent }
|
||||||
|
getConfigs={ getConfigs }
|
||||||
specSelectors={ specSelectors }
|
specSelectors={ specSelectors }
|
||||||
specActions={ specActions }
|
specActions={ specActions }
|
||||||
produces={ produces }
|
produces={ produces }
|
||||||
|
|||||||
@@ -81,8 +81,8 @@ export default class Operations extends React.Component {
|
|||||||
id={isShownKey.join("-")}>
|
id={isShownKey.join("-")}>
|
||||||
<a
|
<a
|
||||||
className="nostyle"
|
className="nostyle"
|
||||||
onClick={(e) => e.preventDefault()}
|
onClick={isDeepLinkingEnabled ? (e) => e.preventDefault() : null}
|
||||||
href={ isDeepLinkingEnabled ? `#/${tag}` : ""}>
|
href= {isDeepLinkingEnabled ? `#/${tag}` : null}>
|
||||||
<span>{tag}</span>
|
<span>{tag}</span>
|
||||||
</a>
|
</a>
|
||||||
{ !tagDescription ? null :
|
{ !tagDescription ? null :
|
||||||
|
|||||||
@@ -16,7 +16,8 @@ export default class Responses extends React.Component {
|
|||||||
specActions: PropTypes.object.isRequired,
|
specActions: PropTypes.object.isRequired,
|
||||||
pathMethod: PropTypes.array.isRequired,
|
pathMethod: PropTypes.array.isRequired,
|
||||||
displayRequestDuration: PropTypes.bool.isRequired,
|
displayRequestDuration: PropTypes.bool.isRequired,
|
||||||
fn: PropTypes.object.isRequired
|
fn: PropTypes.object.isRequired,
|
||||||
|
getConfigs: PropTypes.func.isRequired
|
||||||
}
|
}
|
||||||
|
|
||||||
static defaultProps = {
|
static defaultProps = {
|
||||||
@@ -29,7 +30,7 @@ export default class Responses extends React.Component {
|
|||||||
onChangeProducesWrapper = ( val ) => this.props.specActions.changeProducesValue(this.props.pathMethod, val)
|
onChangeProducesWrapper = ( val ) => this.props.specActions.changeProducesValue(this.props.pathMethod, val)
|
||||||
|
|
||||||
render() {
|
render() {
|
||||||
let { responses, request, tryItOutResponse, getComponent, specSelectors, fn, producesValue, displayRequestDuration } = this.props
|
let { responses, request, tryItOutResponse, getComponent, getConfigs, specSelectors, fn, producesValue, displayRequestDuration } = this.props
|
||||||
let defaultCode = defaultStatusCode( responses )
|
let defaultCode = defaultStatusCode( responses )
|
||||||
|
|
||||||
const ContentType = getComponent( "contentType" )
|
const ContentType = getComponent( "contentType" )
|
||||||
@@ -57,6 +58,9 @@ export default class Responses extends React.Component {
|
|||||||
<LiveResponse request={ request }
|
<LiveResponse request={ request }
|
||||||
response={ tryItOutResponse }
|
response={ tryItOutResponse }
|
||||||
getComponent={ getComponent }
|
getComponent={ getComponent }
|
||||||
|
getConfigs={ getConfigs }
|
||||||
|
specSelectors={ specSelectors }
|
||||||
|
pathMethod={ this.props.pathMethod }
|
||||||
displayRequestDuration={ displayRequestDuration } />
|
displayRequestDuration={ displayRequestDuration } />
|
||||||
<h4>Responses</h4>
|
<h4>Responses</h4>
|
||||||
</div>
|
</div>
|
||||||
|
|||||||
@@ -42,6 +42,9 @@ module.exports = function SwaggerUI(opts) {
|
|||||||
displayOperationId: false,
|
displayOperationId: false,
|
||||||
displayRequestDuration: false,
|
displayRequestDuration: false,
|
||||||
deepLinking: false,
|
deepLinking: false,
|
||||||
|
requestInterceptor: (a => a),
|
||||||
|
responseInterceptor: (a => a),
|
||||||
|
showMutatedRequest: true,
|
||||||
|
|
||||||
// Initial set of plugins ( TODO rename this, or refactor - we don't need presets _and_ plugins. Its just there for performance.
|
// Initial set of plugins ( TODO rename this, or refactor - we don't need presets _and_ plugins. Its just there for performance.
|
||||||
// Instead, we can compile the first plugin ( it can be a collection of plugins ), then batch the rest.
|
// Instead, we can compile the first plugin ( it can be a collection of plugins ), then batch the rest.
|
||||||
@@ -64,6 +67,9 @@ module.exports = function SwaggerUI(opts) {
|
|||||||
|
|
||||||
let queryConfig = parseSearch()
|
let queryConfig = parseSearch()
|
||||||
|
|
||||||
|
const domNode = opts.domNode
|
||||||
|
delete opts.domNode
|
||||||
|
|
||||||
const constructorConfig = deepExtend({}, defaults, opts, queryConfig)
|
const constructorConfig = deepExtend({}, defaults, opts, queryConfig)
|
||||||
|
|
||||||
const storeConfigs = deepExtend({}, constructorConfig.store, {
|
const storeConfigs = deepExtend({}, constructorConfig.store, {
|
||||||
@@ -107,8 +113,8 @@ module.exports = function SwaggerUI(opts) {
|
|||||||
let mergedConfig = deepExtend({}, localConfig, constructorConfig, fetchedConfig || {}, queryConfig)
|
let mergedConfig = deepExtend({}, localConfig, constructorConfig, fetchedConfig || {}, queryConfig)
|
||||||
|
|
||||||
// deep extend mangles domNode, we need to set it manually
|
// deep extend mangles domNode, we need to set it manually
|
||||||
if(opts.domNode) {
|
if(domNode) {
|
||||||
mergedConfig.domNode = opts.domNode
|
mergedConfig.domNode = domNode
|
||||||
}
|
}
|
||||||
|
|
||||||
store.setConfigs(mergedConfig)
|
store.setConfigs(mergedConfig)
|
||||||
|
|||||||
35
src/core/plugins/oas3/actions.js
Normal file
35
src/core/plugins/oas3/actions.js
Normal file
@@ -0,0 +1,35 @@
|
|||||||
|
// Actions conform to FSA (flux-standard-actions)
|
||||||
|
// {type: string,payload: Any|Error, meta: obj, error: bool}
|
||||||
|
|
||||||
|
export const UPDATE_SELECTED_SERVER = "oas3_set_servers"
|
||||||
|
export const UPDATE_REQUEST_BODY_VALUE = "oas3_set_request_body_value"
|
||||||
|
export const UPDATE_REQUEST_CONTENT_TYPE = "oas3_set_request_content_type"
|
||||||
|
export const UPDATE_SERVER_VARIABLE_VALUE = "oas3_set_server_variable_value"
|
||||||
|
|
||||||
|
export function setSelectedServer (selectedServerUrl) {
|
||||||
|
return {
|
||||||
|
type: UPDATE_SELECTED_SERVER,
|
||||||
|
payload: selectedServerUrl
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
export function setRequestBodyValue ({ value, pathMethod }) {
|
||||||
|
return {
|
||||||
|
type: UPDATE_REQUEST_BODY_VALUE,
|
||||||
|
payload: { value, pathMethod }
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
export function setRequestContentType ({ value, pathMethod }) {
|
||||||
|
return {
|
||||||
|
type: UPDATE_REQUEST_CONTENT_TYPE,
|
||||||
|
payload: { value, pathMethod }
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
export function setServerVariableValue ({ server, key, val }) {
|
||||||
|
return {
|
||||||
|
type: UPDATE_SERVER_VARIABLE_VALUE,
|
||||||
|
payload: { server, key, val }
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -1,9 +1,13 @@
|
|||||||
import Callbacks from "./callbacks"
|
import Callbacks from "./callbacks"
|
||||||
import RequestBody from "./request-body"
|
import RequestBody from "./request-body"
|
||||||
import OperationLink from "./operation-link.jsx"
|
import OperationLink from "./operation-link.jsx"
|
||||||
|
import Servers from "./servers"
|
||||||
|
import RequestBodyEditor from "./request-body-editor"
|
||||||
|
|
||||||
export default {
|
export default {
|
||||||
Callbacks,
|
Callbacks,
|
||||||
RequestBody,
|
RequestBody,
|
||||||
|
Servers,
|
||||||
|
RequestBodyEditor,
|
||||||
operationLink: OperationLink
|
operationLink: OperationLink
|
||||||
}
|
}
|
||||||
|
|||||||
114
src/core/plugins/oas3/components/request-body-editor.jsx
Normal file
114
src/core/plugins/oas3/components/request-body-editor.jsx
Normal file
@@ -0,0 +1,114 @@
|
|||||||
|
import React, { PureComponent } from "react"
|
||||||
|
import PropTypes from "prop-types"
|
||||||
|
import { fromJS } from "immutable"
|
||||||
|
import { getSampleSchema } from "core/utils"
|
||||||
|
|
||||||
|
const NOOP = Function.prototype
|
||||||
|
|
||||||
|
export default class RequestBodyEditor extends PureComponent {
|
||||||
|
|
||||||
|
static propTypes = {
|
||||||
|
requestBody: PropTypes.object.isRequired,
|
||||||
|
mediaType: PropTypes.string.isRequired,
|
||||||
|
onChange: PropTypes.func,
|
||||||
|
getComponent: PropTypes.func.isRequired,
|
||||||
|
isExecute: PropTypes.bool,
|
||||||
|
specSelectors: PropTypes.object.isRequired,
|
||||||
|
};
|
||||||
|
|
||||||
|
static defaultProps = {
|
||||||
|
mediaType: "application/json",
|
||||||
|
requestBody: fromJS({}),
|
||||||
|
onChange: NOOP,
|
||||||
|
};
|
||||||
|
|
||||||
|
constructor(props, context) {
|
||||||
|
super(props, context)
|
||||||
|
|
||||||
|
this.state = {
|
||||||
|
isEditBox: false,
|
||||||
|
value: ""
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
componentDidMount() {
|
||||||
|
this.setValueToSample.call(this)
|
||||||
|
}
|
||||||
|
|
||||||
|
componentWillReceiveProps(nextProps) {
|
||||||
|
if(this.props.mediaType !== nextProps.mediaType) {
|
||||||
|
// media type was changed
|
||||||
|
this.setValueToSample(nextProps.mediaType)
|
||||||
|
}
|
||||||
|
|
||||||
|
if(!this.props.isExecute && nextProps.isExecute) {
|
||||||
|
// we just entered execute mode,
|
||||||
|
// so enable editing for convenience
|
||||||
|
this.setState({ isEditBox: true })
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
setValueToSample = (explicitMediaType) => {
|
||||||
|
this.onChange(this.sample(explicitMediaType))
|
||||||
|
}
|
||||||
|
|
||||||
|
sample = (explicitMediaType) => {
|
||||||
|
let { requestBody, mediaType } = this.props
|
||||||
|
let schema = requestBody.getIn(["content", explicitMediaType || mediaType, "schema"]).toJS()
|
||||||
|
|
||||||
|
return getSampleSchema(schema, explicitMediaType || mediaType, {
|
||||||
|
includeWriteOnly: true
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
onChange = (value) => {
|
||||||
|
this.setState({value})
|
||||||
|
this.props.onChange(value)
|
||||||
|
}
|
||||||
|
|
||||||
|
handleOnChange = e => {
|
||||||
|
const { mediaType } = this.props
|
||||||
|
const isJson = /json/i.test(mediaType)
|
||||||
|
const inputValue = isJson ? e.target.value.trim() : e.target.value
|
||||||
|
|
||||||
|
this.onChange(inputValue)
|
||||||
|
}
|
||||||
|
|
||||||
|
toggleIsEditBox = () => this.setState( state => ({isEditBox: !state.isEditBox}))
|
||||||
|
|
||||||
|
render() {
|
||||||
|
let {
|
||||||
|
isExecute,
|
||||||
|
getComponent,
|
||||||
|
} = this.props
|
||||||
|
|
||||||
|
const Button = getComponent("Button")
|
||||||
|
const TextArea = getComponent("TextArea")
|
||||||
|
const HighlightCode = getComponent("highlightCode")
|
||||||
|
|
||||||
|
let { value, isEditBox } = this.state
|
||||||
|
|
||||||
|
return (
|
||||||
|
<div className="body-param">
|
||||||
|
{
|
||||||
|
isEditBox && isExecute
|
||||||
|
? <TextArea className={"body-param__text"} value={value} onChange={ this.handleOnChange }/>
|
||||||
|
: (value && <HighlightCode className="body-param__example"
|
||||||
|
value={ value }/>)
|
||||||
|
}
|
||||||
|
<div className="body-param-options">
|
||||||
|
{
|
||||||
|
!isExecute ? null
|
||||||
|
: <div className="body-param-edit">
|
||||||
|
<Button className={isEditBox ? "btn cancel body-param__example-edit" : "btn edit body-param__example-edit"}
|
||||||
|
onClick={this.toggleIsEditBox}>{ isEditBox ? "Cancel" : "Edit"}
|
||||||
|
</Button>
|
||||||
|
</div>
|
||||||
|
}
|
||||||
|
</div>
|
||||||
|
|
||||||
|
</div>
|
||||||
|
)
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -2,13 +2,18 @@ import React from "react"
|
|||||||
import PropTypes from "prop-types"
|
import PropTypes from "prop-types"
|
||||||
import ImPropTypes from "react-immutable-proptypes"
|
import ImPropTypes from "react-immutable-proptypes"
|
||||||
import { OrderedMap } from "immutable"
|
import { OrderedMap } from "immutable"
|
||||||
import { getSampleSchema } from "core/utils"
|
|
||||||
|
|
||||||
|
const RequestBody = ({
|
||||||
const RequestBody = ({ requestBody, getComponent, specSelectors, contentType }) => {
|
requestBody,
|
||||||
|
getComponent,
|
||||||
|
specSelectors,
|
||||||
|
contentType,
|
||||||
|
isExecute,
|
||||||
|
onChange
|
||||||
|
}) => {
|
||||||
const Markdown = getComponent("Markdown")
|
const Markdown = getComponent("Markdown")
|
||||||
const ModelExample = getComponent("modelExample")
|
const ModelExample = getComponent("modelExample")
|
||||||
const HighlightCode = getComponent("highlightCode")
|
const RequestBodyEditor = getComponent("RequestBodyEditor")
|
||||||
|
|
||||||
const requestBodyDescription = (requestBody && requestBody.get("description")) || null
|
const requestBodyDescription = (requestBody && requestBody.get("description")) || null
|
||||||
const requestBodyContent = (requestBody && requestBody.get("content")) || new OrderedMap()
|
const requestBodyContent = (requestBody && requestBody.get("content")) || new OrderedMap()
|
||||||
@@ -16,10 +21,6 @@ const RequestBody = ({ requestBody, getComponent, specSelectors, contentType })
|
|||||||
|
|
||||||
const mediaTypeValue = requestBodyContent.get(contentType)
|
const mediaTypeValue = requestBodyContent.get(contentType)
|
||||||
|
|
||||||
const sampleSchema = getSampleSchema(mediaTypeValue.get("schema").toJS(), contentType, {
|
|
||||||
includeWriteOnly: true
|
|
||||||
})
|
|
||||||
|
|
||||||
return <div>
|
return <div>
|
||||||
{ requestBodyDescription &&
|
{ requestBodyDescription &&
|
||||||
<Markdown source={requestBodyDescription} />
|
<Markdown source={requestBodyDescription} />
|
||||||
@@ -28,8 +29,16 @@ const RequestBody = ({ requestBody, getComponent, specSelectors, contentType })
|
|||||||
getComponent={ getComponent }
|
getComponent={ getComponent }
|
||||||
specSelectors={ specSelectors }
|
specSelectors={ specSelectors }
|
||||||
expandDepth={1}
|
expandDepth={1}
|
||||||
|
isExecute={isExecute}
|
||||||
schema={mediaTypeValue.get("schema")}
|
schema={mediaTypeValue.get("schema")}
|
||||||
example={<HighlightCode value={sampleSchema} />}
|
example={<RequestBodyEditor
|
||||||
|
requestBody={requestBody}
|
||||||
|
onChange={onChange}
|
||||||
|
mediaType={contentType}
|
||||||
|
getComponent={getComponent}
|
||||||
|
isExecute={isExecute}
|
||||||
|
specSelectors={specSelectors}
|
||||||
|
/>}
|
||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
}
|
}
|
||||||
@@ -38,7 +47,9 @@ RequestBody.propTypes = {
|
|||||||
requestBody: ImPropTypes.orderedMap.isRequired,
|
requestBody: ImPropTypes.orderedMap.isRequired,
|
||||||
getComponent: PropTypes.func.isRequired,
|
getComponent: PropTypes.func.isRequired,
|
||||||
specSelectors: PropTypes.object.isRequired,
|
specSelectors: PropTypes.object.isRequired,
|
||||||
contentType: PropTypes.string.isRequired
|
contentType: PropTypes.string.isRequired,
|
||||||
|
isExecute: PropTypes.bool.isRequired,
|
||||||
|
onChange: PropTypes.func.isRequired
|
||||||
}
|
}
|
||||||
|
|
||||||
export default RequestBody
|
export default RequestBody
|
||||||
|
|||||||
155
src/core/plugins/oas3/components/servers.jsx
Normal file
155
src/core/plugins/oas3/components/servers.jsx
Normal file
@@ -0,0 +1,155 @@
|
|||||||
|
import React from "react"
|
||||||
|
import { OrderedMap } from "immutable"
|
||||||
|
import PropTypes from "prop-types"
|
||||||
|
import ImPropTypes from "react-immutable-proptypes"
|
||||||
|
|
||||||
|
export default class Servers extends React.Component {
|
||||||
|
|
||||||
|
static propTypes = {
|
||||||
|
servers: ImPropTypes.list.isRequired,
|
||||||
|
currentServer: PropTypes.string.isRequired,
|
||||||
|
setSelectedServer: PropTypes.func.isRequired,
|
||||||
|
setServerVariableValue: PropTypes.func.isRequired,
|
||||||
|
getServerVariable: PropTypes.func.isRequired,
|
||||||
|
getEffectiveServerValue: PropTypes.func.isRequired
|
||||||
|
}
|
||||||
|
|
||||||
|
componentDidMount() {
|
||||||
|
let { servers } = this.props
|
||||||
|
|
||||||
|
//fire 'change' event to set default 'value' of select
|
||||||
|
this.setServer(servers.first().get("url"))
|
||||||
|
}
|
||||||
|
|
||||||
|
componentWillReceiveProps(nextProps) {
|
||||||
|
let {
|
||||||
|
servers,
|
||||||
|
setServerVariableValue,
|
||||||
|
getServerVariable
|
||||||
|
} = this.props
|
||||||
|
|
||||||
|
if(this.props.currentServer !== nextProps.currentServer) {
|
||||||
|
// Server has changed, we may need to set default values
|
||||||
|
let currentServerDefinition = servers
|
||||||
|
.find(v => v.get("url") === nextProps.currentServer) || OrderedMap()
|
||||||
|
|
||||||
|
let currentServerVariableDefs = currentServerDefinition.get("variables") || OrderedMap()
|
||||||
|
|
||||||
|
currentServerVariableDefs.map((val, key) => {
|
||||||
|
let currentValue = getServerVariable(nextProps.currentServer, key)
|
||||||
|
// only set the default value if the user hasn't set one yet
|
||||||
|
if(!currentValue) {
|
||||||
|
setServerVariableValue({
|
||||||
|
server: nextProps.currentServer,
|
||||||
|
key,
|
||||||
|
val: val.get("default") || ""
|
||||||
|
})
|
||||||
|
}
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
onServerChange =( e ) => {
|
||||||
|
this.setServer( e.target.value )
|
||||||
|
|
||||||
|
// set default variable values
|
||||||
|
}
|
||||||
|
|
||||||
|
onServerVariableValueChange = ( e ) => {
|
||||||
|
let {
|
||||||
|
setServerVariableValue,
|
||||||
|
currentServer
|
||||||
|
} = this.props
|
||||||
|
|
||||||
|
let variableName = e.target.getAttribute("data-variable")
|
||||||
|
let newVariableValue = e.target.value
|
||||||
|
|
||||||
|
if(typeof setServerVariableValue === "function") {
|
||||||
|
setServerVariableValue({
|
||||||
|
server: currentServer,
|
||||||
|
key: variableName,
|
||||||
|
val: newVariableValue
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
setServer = ( value ) => {
|
||||||
|
let { setSelectedServer } = this.props
|
||||||
|
|
||||||
|
setSelectedServer(value)
|
||||||
|
}
|
||||||
|
|
||||||
|
render() {
|
||||||
|
let { servers,
|
||||||
|
currentServer,
|
||||||
|
getServerVariable,
|
||||||
|
getEffectiveServerValue
|
||||||
|
} = this.props
|
||||||
|
|
||||||
|
let currentServerDefinition = servers.find(v => v.get("url") === currentServer) || OrderedMap()
|
||||||
|
|
||||||
|
let currentServerVariableDefs = currentServerDefinition.get("variables") || OrderedMap()
|
||||||
|
|
||||||
|
let shouldShowVariableUI = currentServerVariableDefs.size !== 0
|
||||||
|
|
||||||
|
return (
|
||||||
|
<div>
|
||||||
|
<label htmlFor="servers">
|
||||||
|
<span className="servers-title">Servers</span>
|
||||||
|
<select onChange={ this.onServerChange }>
|
||||||
|
{ servers.valueSeq().map(
|
||||||
|
( server ) =>
|
||||||
|
<option
|
||||||
|
value={ server.get("url") }
|
||||||
|
key={ server.get("url") }>
|
||||||
|
{ server.get("url") }
|
||||||
|
</option>
|
||||||
|
).toArray()}
|
||||||
|
</select>
|
||||||
|
</label>
|
||||||
|
{ shouldShowVariableUI ?
|
||||||
|
<div>
|
||||||
|
<h4>Server variables</h4>
|
||||||
|
<div className={"computed-url"}>
|
||||||
|
Computed URL:
|
||||||
|
<code>
|
||||||
|
{getEffectiveServerValue(currentServer)}
|
||||||
|
</code>
|
||||||
|
</div>
|
||||||
|
<table>
|
||||||
|
<tbody>
|
||||||
|
{
|
||||||
|
currentServerVariableDefs.map((val, name) => {
|
||||||
|
return <tr key={name}>
|
||||||
|
<td>{name}</td>
|
||||||
|
<td>
|
||||||
|
{ val.get("enum") ?
|
||||||
|
<select data-variable={name} onChange={this.onServerVariableValueChange}>
|
||||||
|
{val.get("enum").map(enumValue => {
|
||||||
|
return <option
|
||||||
|
selected={enumValue === getServerVariable(currentServer, name)}
|
||||||
|
key={enumValue}
|
||||||
|
value={enumValue}>
|
||||||
|
{enumValue}
|
||||||
|
</option>
|
||||||
|
})}
|
||||||
|
</select> :
|
||||||
|
<input
|
||||||
|
type={"text"}
|
||||||
|
value={getServerVariable(currentServer, name) || ""}
|
||||||
|
onChange={this.onServerVariableValueChange}
|
||||||
|
data-variable={name}
|
||||||
|
></input>
|
||||||
|
}
|
||||||
|
</td>
|
||||||
|
</tr>
|
||||||
|
})
|
||||||
|
}
|
||||||
|
</tbody>
|
||||||
|
</table>
|
||||||
|
</div>: null
|
||||||
|
}
|
||||||
|
</div>
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -1,8 +1,12 @@
|
|||||||
// import reducers from "./reducers"
|
// import reducers from "./reducers"
|
||||||
// import * as actions from "./actions"
|
// import * as actions from "./actions"
|
||||||
import * as wrapSelectors from "./wrap-selectors"
|
import * as specWrapSelectors from "./spec-extensions/wrap-selectors"
|
||||||
|
import * as specSelectors from "./spec-extensions/selectors"
|
||||||
import components from "./components"
|
import components from "./components"
|
||||||
import wrapComponents from "./wrap-components"
|
import wrapComponents from "./wrap-components"
|
||||||
|
import * as oas3Actions from "./actions"
|
||||||
|
import * as oas3Selectors from "./selectors"
|
||||||
|
import oas3Reducers from "./reducers"
|
||||||
|
|
||||||
export default function() {
|
export default function() {
|
||||||
return {
|
return {
|
||||||
@@ -10,7 +14,13 @@ export default function() {
|
|||||||
wrapComponents,
|
wrapComponents,
|
||||||
statePlugins: {
|
statePlugins: {
|
||||||
spec: {
|
spec: {
|
||||||
wrapSelectors
|
wrapSelectors: specWrapSelectors,
|
||||||
|
selectors: specSelectors
|
||||||
|
},
|
||||||
|
oas3: {
|
||||||
|
actions: oas3Actions,
|
||||||
|
reducers: oas3Reducers,
|
||||||
|
selectors: oas3Selectors,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
23
src/core/plugins/oas3/reducers.js
Normal file
23
src/core/plugins/oas3/reducers.js
Normal file
@@ -0,0 +1,23 @@
|
|||||||
|
import {
|
||||||
|
UPDATE_SELECTED_SERVER,
|
||||||
|
UPDATE_REQUEST_BODY_VALUE,
|
||||||
|
UPDATE_REQUEST_CONTENT_TYPE,
|
||||||
|
UPDATE_SERVER_VARIABLE_VALUE
|
||||||
|
} from "./actions"
|
||||||
|
|
||||||
|
export default {
|
||||||
|
[UPDATE_SELECTED_SERVER]: (state, { payload: selectedServerUrl } ) =>{
|
||||||
|
return state.setIn( [ "selectedServer" ], selectedServerUrl)
|
||||||
|
},
|
||||||
|
[UPDATE_REQUEST_BODY_VALUE]: (state, { payload: { value, pathMethod } } ) =>{
|
||||||
|
let [path, method] = pathMethod
|
||||||
|
return state.setIn( [ "requestData", path, method, "bodyValue" ], value)
|
||||||
|
},
|
||||||
|
[UPDATE_REQUEST_CONTENT_TYPE]: (state, { payload: { value, pathMethod } } ) =>{
|
||||||
|
let [path, method] = pathMethod
|
||||||
|
return state.setIn( [ "requestData", path, method, "requestContentType" ], value)
|
||||||
|
},
|
||||||
|
[UPDATE_SERVER_VARIABLE_VALUE]: (state, { payload: { server, key, val } } ) =>{
|
||||||
|
return state.setIn( [ "serverVariableValues", server, key ], val)
|
||||||
|
},
|
||||||
|
}
|
||||||
53
src/core/plugins/oas3/selectors.js
Normal file
53
src/core/plugins/oas3/selectors.js
Normal file
@@ -0,0 +1,53 @@
|
|||||||
|
import { OrderedMap } from "immutable"
|
||||||
|
import { isOAS3 as isOAS3Helper } from "./helpers"
|
||||||
|
|
||||||
|
|
||||||
|
// Helpers
|
||||||
|
|
||||||
|
function onlyOAS3(selector) {
|
||||||
|
return (...args) => (system) => {
|
||||||
|
const spec = system.getSystem().specSelectors.specJson()
|
||||||
|
if(isOAS3Helper(spec)) {
|
||||||
|
return selector(...args)
|
||||||
|
} else {
|
||||||
|
return null
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
export const selectedServer = onlyOAS3(state => {
|
||||||
|
return state.getIn(["selectedServer"]) || ""
|
||||||
|
}
|
||||||
|
)
|
||||||
|
|
||||||
|
export const requestBodyValue = onlyOAS3((state, path, method) => {
|
||||||
|
return state.getIn(["requestData", path, method, "bodyValue"]) || null
|
||||||
|
}
|
||||||
|
)
|
||||||
|
|
||||||
|
export const requestContentType = onlyOAS3((state, path, method) => {
|
||||||
|
return state.getIn(["requestData", path, method, "requestContentType"]) || null
|
||||||
|
}
|
||||||
|
)
|
||||||
|
|
||||||
|
export const serverVariableValue = onlyOAS3((state, server, key) => {
|
||||||
|
return state.getIn(["serverVariableValues", server, key]) || null
|
||||||
|
}
|
||||||
|
)
|
||||||
|
|
||||||
|
export const serverVariables = onlyOAS3((state, server) => {
|
||||||
|
return state.getIn(["serverVariableValues", server]) || OrderedMap()
|
||||||
|
}
|
||||||
|
)
|
||||||
|
|
||||||
|
export const serverEffectiveValue = onlyOAS3((state, server) => {
|
||||||
|
let varValues = state.getIn(["serverVariableValues", server]) || OrderedMap()
|
||||||
|
let str = server
|
||||||
|
|
||||||
|
varValues.map((val, key) => {
|
||||||
|
str = str.replace(new RegExp(`{${key}}`, "g"), val)
|
||||||
|
})
|
||||||
|
|
||||||
|
return str
|
||||||
|
}
|
||||||
|
)
|
||||||
50
src/core/plugins/oas3/spec-extensions/selectors.js
Normal file
50
src/core/plugins/oas3/spec-extensions/selectors.js
Normal file
@@ -0,0 +1,50 @@
|
|||||||
|
import { createSelector } from "reselect"
|
||||||
|
import { Map } from "immutable"
|
||||||
|
import { isOAS3 as isOAS3Helper, isSwagger2 as isSwagger2Helper } from "../helpers"
|
||||||
|
|
||||||
|
|
||||||
|
// Helpers
|
||||||
|
|
||||||
|
function onlyOAS3(selector) {
|
||||||
|
return () => (system, ...args) => {
|
||||||
|
const spec = system.getSystem().specSelectors.specJson()
|
||||||
|
if(isOAS3Helper(spec)) {
|
||||||
|
return selector(...args)
|
||||||
|
} else {
|
||||||
|
return null
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
const state = state => {
|
||||||
|
return state || Map()
|
||||||
|
}
|
||||||
|
|
||||||
|
const specJson = createSelector(
|
||||||
|
state,
|
||||||
|
spec => spec.get("json", Map())
|
||||||
|
)
|
||||||
|
|
||||||
|
const specResolved = createSelector(
|
||||||
|
state,
|
||||||
|
spec => spec.get("resolved", Map())
|
||||||
|
)
|
||||||
|
|
||||||
|
const spec = state => {
|
||||||
|
let res = specResolved(state)
|
||||||
|
if(res.count() < 1)
|
||||||
|
res = specJson(state)
|
||||||
|
return res
|
||||||
|
}
|
||||||
|
|
||||||
|
// New selectors
|
||||||
|
|
||||||
|
export const servers = onlyOAS3(createSelector(
|
||||||
|
spec,
|
||||||
|
spec => spec.getIn(["servers"]) || Map()
|
||||||
|
))
|
||||||
|
|
||||||
|
export const isSwagger2 = (ori, system) => () => {
|
||||||
|
const spec = system.getSystem().specSelectors.specJson()
|
||||||
|
return isSwagger2Helper(spec)
|
||||||
|
}
|
||||||
@@ -1,6 +1,6 @@
|
|||||||
import { createSelector } from "reselect"
|
import { createSelector } from "reselect"
|
||||||
import { Map } from "immutable"
|
import { Map } from "immutable"
|
||||||
import { isOAS3 as isOAS3Helper, isSwagger2 as isSwagger2Helper } from "./helpers"
|
import { isOAS3 as isOAS3Helper, isSwagger2 as isSwagger2Helper } from "../helpers"
|
||||||
|
|
||||||
|
|
||||||
// Helpers
|
// Helpers
|
||||||
@@ -56,6 +56,11 @@ export const schemes = OAS3NullSelector
|
|||||||
|
|
||||||
// New selectors
|
// New selectors
|
||||||
|
|
||||||
|
export const servers = onlyOAS3(createSelector(
|
||||||
|
spec,
|
||||||
|
spec => spec.getIn(["servers"]) || Map()
|
||||||
|
))
|
||||||
|
|
||||||
export const isOAS3 = (ori, system) => () => {
|
export const isOAS3 = (ori, system) => () => {
|
||||||
const spec = system.getSystem().specSelectors.specJson()
|
const spec = system.getSystem().specSelectors.specJson()
|
||||||
return isOAS3Helper(spec)
|
return isOAS3Helper(spec)
|
||||||
@@ -3,7 +3,6 @@ import parameters from "./parameters"
|
|||||||
import VersionStamp from "./version-stamp"
|
import VersionStamp from "./version-stamp"
|
||||||
import OnlineValidatorBadge from "./online-validator-badge"
|
import OnlineValidatorBadge from "./online-validator-badge"
|
||||||
import Model from "./model"
|
import Model from "./model"
|
||||||
import TryItOutButton from "./try-it-out-button"
|
|
||||||
|
|
||||||
export default {
|
export default {
|
||||||
Markdown,
|
Markdown,
|
||||||
@@ -11,5 +10,4 @@ export default {
|
|||||||
VersionStamp,
|
VersionStamp,
|
||||||
model: Model,
|
model: Model,
|
||||||
onlineValidatorBadge: OnlineValidatorBadge,
|
onlineValidatorBadge: OnlineValidatorBadge,
|
||||||
TryItOutButton
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -13,8 +13,7 @@ class Parameters extends Component {
|
|||||||
super(props)
|
super(props)
|
||||||
this.state = {
|
this.state = {
|
||||||
callbackVisible: false,
|
callbackVisible: false,
|
||||||
parametersVisible: true,
|
parametersVisible: true
|
||||||
requestBodyContentType: ""
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -24,6 +23,8 @@ class Parameters extends Component {
|
|||||||
operation: PropTypes.object.isRequired,
|
operation: PropTypes.object.isRequired,
|
||||||
getComponent: PropTypes.func.isRequired,
|
getComponent: PropTypes.func.isRequired,
|
||||||
specSelectors: PropTypes.object.isRequired,
|
specSelectors: PropTypes.object.isRequired,
|
||||||
|
oas3Actions: PropTypes.object.isRequired,
|
||||||
|
oas3Selectors: PropTypes.object.isRequired,
|
||||||
fn: PropTypes.object.isRequired,
|
fn: PropTypes.object.isRequired,
|
||||||
tryItOutEnabled: PropTypes.bool,
|
tryItOutEnabled: PropTypes.bool,
|
||||||
allowTryItOut: PropTypes.bool,
|
allowTryItOut: PropTypes.bool,
|
||||||
@@ -86,6 +87,8 @@ class Parameters extends Component {
|
|||||||
fn,
|
fn,
|
||||||
getComponent,
|
getComponent,
|
||||||
specSelectors,
|
specSelectors,
|
||||||
|
oas3Actions,
|
||||||
|
oas3Selectors,
|
||||||
pathMethod,
|
pathMethod,
|
||||||
operation
|
operation
|
||||||
} = this.props
|
} = this.props
|
||||||
@@ -159,16 +162,22 @@ class Parameters extends Component {
|
|||||||
<h4 className={`opblock-title parameter__name ${requestBody.get("required") && "required"}`}>Request body</h4>
|
<h4 className={`opblock-title parameter__name ${requestBody.get("required") && "required"}`}>Request body</h4>
|
||||||
<label>
|
<label>
|
||||||
<ContentType
|
<ContentType
|
||||||
value={this.state.requestBodyContentType}
|
value={oas3Selectors.requestContentType(...pathMethod)}
|
||||||
contentTypes={ requestBody.get("content").keySeq() }
|
contentTypes={ requestBody.get("content").keySeq() }
|
||||||
onChange={(val) => this.setState({ requestBodyContentType: val })}
|
onChange={(value) => {
|
||||||
|
oas3Actions.setRequestContentType({ value, pathMethod })
|
||||||
|
}}
|
||||||
className="body-param-content-type" />
|
className="body-param-content-type" />
|
||||||
</label>
|
</label>
|
||||||
</div>
|
</div>
|
||||||
<div className="opblock-description-wrapper">
|
<div className="opblock-description-wrapper">
|
||||||
<RequestBody
|
<RequestBody
|
||||||
requestBody={requestBody}
|
requestBody={requestBody}
|
||||||
contentType={this.state.requestBodyContentType}/>
|
isExecute={isExecute}
|
||||||
|
onChange={(value) => {
|
||||||
|
oas3Actions.setRequestBodyValue({ value, pathMethod })
|
||||||
|
}}
|
||||||
|
contentType={oas3Selectors.requestContentType(...pathMethod)}/>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,5 +0,0 @@
|
|||||||
import { OAS3ComponentWrapFactory } from "../helpers"
|
|
||||||
|
|
||||||
export default OAS3ComponentWrapFactory(() => {
|
|
||||||
return null
|
|
||||||
})
|
|
||||||
@@ -1,6 +1,7 @@
|
|||||||
import YAML from "js-yaml"
|
import YAML from "js-yaml"
|
||||||
import parseUrl from "url-parse"
|
import parseUrl from "url-parse"
|
||||||
import serializeError from "serialize-error"
|
import serializeError from "serialize-error"
|
||||||
|
import { isJSONObject } from "core/utils"
|
||||||
|
|
||||||
// Actions conform to FSA (flux-standard-actions)
|
// Actions conform to FSA (flux-standard-actions)
|
||||||
// {type: string,payload: Any|Error, meta: obj, error: bool}
|
// {type: string,payload: Any|Error, meta: obj, error: bool}
|
||||||
@@ -12,6 +13,7 @@ export const UPDATE_PARAM = "spec_update_param"
|
|||||||
export const VALIDATE_PARAMS = "spec_validate_param"
|
export const VALIDATE_PARAMS = "spec_validate_param"
|
||||||
export const SET_RESPONSE = "spec_set_response"
|
export const SET_RESPONSE = "spec_set_response"
|
||||||
export const SET_REQUEST = "spec_set_request"
|
export const SET_REQUEST = "spec_set_request"
|
||||||
|
export const SET_MUTATED_REQUEST = "spec_set_mutated_request"
|
||||||
export const LOG_REQUEST = "spec_log_request"
|
export const LOG_REQUEST = "spec_log_request"
|
||||||
export const CLEAR_RESPONSE = "spec_clear_response"
|
export const CLEAR_RESPONSE = "spec_clear_response"
|
||||||
export const CLEAR_REQUEST = "spec_clear_request"
|
export const CLEAR_REQUEST = "spec_clear_request"
|
||||||
@@ -177,6 +179,13 @@ export const setRequest = ( path, method, req ) => {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export const setMutatedRequest = ( path, method, req ) => {
|
||||||
|
return {
|
||||||
|
payload: { path, method, req },
|
||||||
|
type: SET_MUTATED_REQUEST
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// This is for debugging, remove this comment if you depend on this action
|
// This is for debugging, remove this comment if you depend on this action
|
||||||
export const logRequest = (req) => {
|
export const logRequest = (req) => {
|
||||||
return {
|
return {
|
||||||
@@ -187,8 +196,10 @@ export const logRequest = (req) => {
|
|||||||
|
|
||||||
// Actually fire the request via fn.execute
|
// Actually fire the request via fn.execute
|
||||||
// (For debugging) and ease of testing
|
// (For debugging) and ease of testing
|
||||||
export const executeRequest = (req) => ({fn, specActions, specSelectors}) => {
|
export const executeRequest = (req) =>
|
||||||
|
({fn, specActions, specSelectors, getConfigs, oas3Selectors}) => {
|
||||||
let { pathName, method, operation } = req
|
let { pathName, method, operation } = req
|
||||||
|
let { requestInterceptor, responseInterceptor } = getConfigs()
|
||||||
|
|
||||||
let op = operation.toJS()
|
let op = operation.toJS()
|
||||||
|
|
||||||
@@ -202,11 +213,35 @@ export const executeRequest = (req) => ({fn, specActions, specSelectors}) => {
|
|||||||
req.operationId = fn.opId(op, pathName, method)
|
req.operationId = fn.opId(op, pathName, method)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if(specSelectors.isOAS3()) {
|
||||||
|
// OAS3 request feature support
|
||||||
|
req.server = oas3Selectors.selectedServer()
|
||||||
|
req.serverVariables = oas3Selectors.serverVariables(req.server).toJS()
|
||||||
|
req.requestContentType = oas3Selectors.requestContentType(pathName, method)
|
||||||
|
const requestBody = oas3Selectors.requestBodyValue(pathName, method)
|
||||||
|
|
||||||
|
if(isJSONObject(requestBody)) {
|
||||||
|
req.requestBody = JSON.parse(requestBody)
|
||||||
|
} else {
|
||||||
|
req.requestBody = requestBody
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
let parsedRequest = Object.assign({}, req)
|
let parsedRequest = Object.assign({}, req)
|
||||||
parsedRequest = fn.buildRequest(parsedRequest)
|
parsedRequest = fn.buildRequest(parsedRequest)
|
||||||
|
|
||||||
specActions.setRequest(req.pathName, req.method, parsedRequest)
|
specActions.setRequest(req.pathName, req.method, parsedRequest)
|
||||||
|
|
||||||
|
let requestInterceptorWrapper = function(r) {
|
||||||
|
let mutatedRequest = requestInterceptor.apply(this, [r])
|
||||||
|
let parsedMutatedRequest = Object.assign({}, mutatedRequest)
|
||||||
|
specActions.setMutatedRequest(req.pathName, req.method, parsedMutatedRequest)
|
||||||
|
return mutatedRequest
|
||||||
|
}
|
||||||
|
|
||||||
|
req.requestInterceptor = requestInterceptorWrapper
|
||||||
|
req.responseInterceptor = responseInterceptor
|
||||||
|
|
||||||
// track duration of request
|
// track duration of request
|
||||||
const startTime = Date.now()
|
const startTime = Date.now()
|
||||||
|
|
||||||
@@ -215,8 +250,12 @@ export const executeRequest = (req) => ({fn, specActions, specSelectors}) => {
|
|||||||
res.duration = Date.now() - startTime
|
res.duration = Date.now() - startTime
|
||||||
specActions.setResponse(req.pathName, req.method, res)
|
specActions.setResponse(req.pathName, req.method, res)
|
||||||
} )
|
} )
|
||||||
.catch( err => specActions.setResponse(req.pathName, req.method, { error: true, err: serializeError(err) } ) )
|
.catch(
|
||||||
}
|
err => specActions.setResponse(req.pathName, req.method, {
|
||||||
|
error: true, err: serializeError(err)
|
||||||
|
})
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
// I'm using extras as a way to inject properties into the final, `execute` method - It's not great. Anyone have a better idea? @ponelat
|
// I'm using extras as a way to inject properties into the final, `execute` method - It's not great. Anyone have a better idea? @ponelat
|
||||||
|
|||||||
@@ -10,6 +10,7 @@ import {
|
|||||||
VALIDATE_PARAMS,
|
VALIDATE_PARAMS,
|
||||||
SET_RESPONSE,
|
SET_RESPONSE,
|
||||||
SET_REQUEST,
|
SET_REQUEST,
|
||||||
|
SET_MUTATED_REQUEST,
|
||||||
UPDATE_RESOLVED,
|
UPDATE_RESOLVED,
|
||||||
UPDATE_OPERATION_VALUE,
|
UPDATE_OPERATION_VALUE,
|
||||||
CLEAR_RESPONSE,
|
CLEAR_RESPONSE,
|
||||||
@@ -101,6 +102,10 @@ export default {
|
|||||||
return state.setIn( [ "requests", path, method ], fromJSOrdered(req))
|
return state.setIn( [ "requests", path, method ], fromJSOrdered(req))
|
||||||
},
|
},
|
||||||
|
|
||||||
|
[SET_MUTATED_REQUEST]: (state, { payload: { req, path, method } } ) =>{
|
||||||
|
return state.setIn( [ "mutatedRequests", path, method ], fromJSOrdered(req))
|
||||||
|
},
|
||||||
|
|
||||||
[UPDATE_OPERATION_VALUE]: (state, { payload: { path, value, key } }) => {
|
[UPDATE_OPERATION_VALUE]: (state, { payload: { path, value, key } }) => {
|
||||||
let operationPath = ["resolved", "paths", ...path]
|
let operationPath = ["resolved", "paths", ...path]
|
||||||
if(!state.getIn(operationPath)) {
|
if(!state.getIn(operationPath)) {
|
||||||
|
|||||||
@@ -237,6 +237,11 @@ export const requests = createSelector(
|
|||||||
state => state.get( "requests", Map() )
|
state => state.get( "requests", Map() )
|
||||||
)
|
)
|
||||||
|
|
||||||
|
export const mutatedRequests = createSelector(
|
||||||
|
state,
|
||||||
|
state => state.get( "mutatedRequests", Map() )
|
||||||
|
)
|
||||||
|
|
||||||
export const responseFor = (state, path, method) => {
|
export const responseFor = (state, path, method) => {
|
||||||
return responses(state).getIn([path, method], null)
|
return responses(state).getIn([path, method], null)
|
||||||
}
|
}
|
||||||
@@ -245,6 +250,10 @@ export const requestFor = (state, path, method) => {
|
|||||||
return requests(state).getIn([path, method], null)
|
return requests(state).getIn([path, method], null)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export const mutatedRequestFor = (state, path, method) => {
|
||||||
|
return mutatedRequests(state).getIn([path, method], null)
|
||||||
|
}
|
||||||
|
|
||||||
export const allowTryItOutFor = () => {
|
export const allowTryItOutFor = () => {
|
||||||
// This is just a hook for now.
|
// This is just a hook for now.
|
||||||
return true
|
return true
|
||||||
|
|||||||
@@ -13,6 +13,25 @@ const DEFAULT_REPONSE_KEY = "default"
|
|||||||
|
|
||||||
export const isImmutable = (maybe) => Im.Iterable.isIterable(maybe)
|
export const isImmutable = (maybe) => Im.Iterable.isIterable(maybe)
|
||||||
|
|
||||||
|
export function isJSONObject (str) {
|
||||||
|
try {
|
||||||
|
var o = JSON.parse(str)
|
||||||
|
|
||||||
|
// Handle non-exception-throwing cases:
|
||||||
|
// Neither JSON.parse(false) or JSON.parse(1234) throw errors, hence the type-checking,
|
||||||
|
// but... JSON.parse(null) returns null, and typeof null === "object",
|
||||||
|
// so we must check for that, too. Thankfully, null is falsey, so this suffices:
|
||||||
|
if (o && typeof o === "object") {
|
||||||
|
return o
|
||||||
|
}
|
||||||
|
}
|
||||||
|
catch (e) {
|
||||||
|
// do nothing
|
||||||
|
}
|
||||||
|
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
|
||||||
export function objectify (thing) {
|
export function objectify (thing) {
|
||||||
if(!isObject(thing))
|
if(!isObject(thing))
|
||||||
return {}
|
return {}
|
||||||
|
|||||||
@@ -1,2 +1,5 @@
|
|||||||
// Promise global, Used ( at least ) by 'whatwg-fetch'. And required by IE 11
|
// Promise global, Used ( at least ) by 'whatwg-fetch'. And required by IE 11
|
||||||
require("core-js/fn/promise")
|
|
||||||
|
if(!window.Promise) {
|
||||||
|
require("core-js/fn/promise")
|
||||||
|
}
|
||||||
|
|||||||
@@ -636,6 +636,77 @@
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.server-container
|
||||||
|
{
|
||||||
|
margin: 0 0 20px 0;
|
||||||
|
padding: 30px 0;
|
||||||
|
|
||||||
|
background: #fff;
|
||||||
|
box-shadow: 0 1px 2px 0 rgba(0,0,0,.15);
|
||||||
|
|
||||||
|
.computed-url {
|
||||||
|
margin: 2em 0;
|
||||||
|
|
||||||
|
code {
|
||||||
|
color: grey;
|
||||||
|
display: inline-block;
|
||||||
|
padding: 4px;
|
||||||
|
font-size: 16px;
|
||||||
|
margin: 0 1em;
|
||||||
|
font-style: italic;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.servers
|
||||||
|
{
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
|
||||||
|
.servers-title {
|
||||||
|
margin-right: 1em;
|
||||||
|
}
|
||||||
|
|
||||||
|
> label
|
||||||
|
{
|
||||||
|
font-size: 12px;
|
||||||
|
|
||||||
|
display: flex;
|
||||||
|
flex-direction: column;
|
||||||
|
|
||||||
|
margin: -20px 15px 0 0;
|
||||||
|
|
||||||
|
@include text_headline();
|
||||||
|
|
||||||
|
select
|
||||||
|
{
|
||||||
|
min-width: 130px;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
table {
|
||||||
|
tr {
|
||||||
|
width: 30em;
|
||||||
|
}
|
||||||
|
td {
|
||||||
|
display: inline-block;
|
||||||
|
max-width: 15em;
|
||||||
|
vertical-align: middle;
|
||||||
|
padding-top: 10px;
|
||||||
|
padding-bottom: 10px;
|
||||||
|
|
||||||
|
&:first-of-type {
|
||||||
|
padding-right: 2em;
|
||||||
|
}
|
||||||
|
|
||||||
|
input {
|
||||||
|
width: 100%;
|
||||||
|
height: 100%;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
.loading-container
|
.loading-container
|
||||||
{
|
{
|
||||||
@@ -726,12 +797,12 @@ section
|
|||||||
a.nostyle {
|
a.nostyle {
|
||||||
text-decoration: inherit;
|
text-decoration: inherit;
|
||||||
color: inherit;
|
color: inherit;
|
||||||
cursor: auto;
|
cursor: pointer;
|
||||||
display: inline;
|
display: inline;
|
||||||
|
|
||||||
&:visited {
|
&:visited {
|
||||||
text-decoration: inherit;
|
text-decoration: inherit;
|
||||||
color: inherit;
|
color: inherit;
|
||||||
cursor: auto;
|
cursor: pointer;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
85
test/components/live-response.js
Normal file
85
test/components/live-response.js
Normal file
@@ -0,0 +1,85 @@
|
|||||||
|
/* eslint-env mocha */
|
||||||
|
import React from "react"
|
||||||
|
import { fromJSOrdered } from "core/utils"
|
||||||
|
import expect, { createSpy } from "expect"
|
||||||
|
import { shallow } from "enzyme"
|
||||||
|
import Curl from "components/curl"
|
||||||
|
import LiveResponse from "components/live-response"
|
||||||
|
import ResponseBody from "components/response-body"
|
||||||
|
|
||||||
|
describe("<LiveResponse/>", function(){
|
||||||
|
let request = fromJSOrdered({
|
||||||
|
credentials: "same-origin",
|
||||||
|
headers: {
|
||||||
|
accept: "application/xml"
|
||||||
|
},
|
||||||
|
url: "http://petstore.swagger.io/v2/pet/1"
|
||||||
|
})
|
||||||
|
|
||||||
|
let mutatedRequest = fromJSOrdered({
|
||||||
|
credentials: "same-origin",
|
||||||
|
headers: {
|
||||||
|
accept: "application/xml",
|
||||||
|
mutated: "header"
|
||||||
|
},
|
||||||
|
url: "http://petstore.swagger.io/v2/pet/1"
|
||||||
|
})
|
||||||
|
|
||||||
|
let requests = {
|
||||||
|
request: request,
|
||||||
|
mutatedRequest: mutatedRequest
|
||||||
|
}
|
||||||
|
|
||||||
|
const tests = [
|
||||||
|
{ showMutatedRequest: true, expected: { request: "mutatedRequest", requestForCalls: 0, mutatedRequestForCalls: 1 } },
|
||||||
|
{ showMutatedRequest: false, expected: { request: "request", requestForCalls: 1, mutatedRequestForCalls: 0 } }
|
||||||
|
]
|
||||||
|
|
||||||
|
tests.forEach(function(test) {
|
||||||
|
it("passes " + test.expected.request + " to Curl when showMutatedRequest = " + test.showMutatedRequest, function() {
|
||||||
|
|
||||||
|
// Given
|
||||||
|
|
||||||
|
let response = fromJSOrdered({
|
||||||
|
status: 200,
|
||||||
|
url: "http://petstore.swagger.io/v2/pet/1",
|
||||||
|
headers: {},
|
||||||
|
text: "<response/>",
|
||||||
|
})
|
||||||
|
|
||||||
|
let mutatedRequestForSpy = createSpy().andReturn(mutatedRequest)
|
||||||
|
let requestForSpy = createSpy().andReturn(request)
|
||||||
|
|
||||||
|
let components = {
|
||||||
|
curl: Curl,
|
||||||
|
responseBody: ResponseBody
|
||||||
|
}
|
||||||
|
|
||||||
|
let props = {
|
||||||
|
response: response,
|
||||||
|
specSelectors: {
|
||||||
|
mutatedRequestFor: mutatedRequestForSpy,
|
||||||
|
requestFor: requestForSpy,
|
||||||
|
},
|
||||||
|
pathMethod: [ "/one", "get" ],
|
||||||
|
getComponent: (c) => {
|
||||||
|
return components[c]
|
||||||
|
},
|
||||||
|
displayRequestDuration: true,
|
||||||
|
getConfigs: () => ({ showMutatedRequest: test.showMutatedRequest })
|
||||||
|
}
|
||||||
|
|
||||||
|
// When
|
||||||
|
let wrapper = shallow(<LiveResponse {...props}/>)
|
||||||
|
|
||||||
|
// Then
|
||||||
|
expect(mutatedRequestForSpy.calls.length).toEqual(test.expected.mutatedRequestForCalls)
|
||||||
|
expect(requestForSpy.calls.length).toEqual(test.expected.requestForCalls)
|
||||||
|
|
||||||
|
const curl = wrapper.find(Curl)
|
||||||
|
expect(curl.length).toEqual(1)
|
||||||
|
expect(curl.props().request).toBe(requests[test.expected.request])
|
||||||
|
|
||||||
|
})
|
||||||
|
})
|
||||||
|
})
|
||||||
@@ -93,6 +93,55 @@ describe("spec plugin - actions", function(){
|
|||||||
})
|
})
|
||||||
})
|
})
|
||||||
|
|
||||||
|
it("should pass requestInterceptor/responseInterceptor to fn.execute", function(){
|
||||||
|
// Given
|
||||||
|
let configs = {
|
||||||
|
requestInterceptor: createSpy(),
|
||||||
|
responseInterceptor: createSpy()
|
||||||
|
}
|
||||||
|
const system = {
|
||||||
|
fn: {
|
||||||
|
buildRequest: createSpy(),
|
||||||
|
execute: createSpy().andReturn(Promise.resolve())
|
||||||
|
},
|
||||||
|
specActions: {
|
||||||
|
executeRequest: createSpy(),
|
||||||
|
setMutatedRequest: createSpy(),
|
||||||
|
setRequest: createSpy()
|
||||||
|
},
|
||||||
|
specSelectors: {
|
||||||
|
spec: () => fromJS({}),
|
||||||
|
parameterValues: () => fromJS({}),
|
||||||
|
contentTypeValues: () => fromJS({}),
|
||||||
|
url: () => fromJS({}),
|
||||||
|
isOAS3: () => false
|
||||||
|
},
|
||||||
|
getConfigs: () => configs
|
||||||
|
}
|
||||||
|
// When
|
||||||
|
let executeFn = executeRequest({
|
||||||
|
pathName: "/one",
|
||||||
|
method: "GET",
|
||||||
|
operation: fromJS({operationId: "getOne"})
|
||||||
|
})
|
||||||
|
let res = executeFn(system)
|
||||||
|
|
||||||
|
// Then
|
||||||
|
expect(system.fn.execute.calls.length).toEqual(1)
|
||||||
|
expect(system.fn.execute.calls[0].arguments[0]).toIncludeKey("requestInterceptor")
|
||||||
|
expect(system.fn.execute.calls[0].arguments[0]).toInclude({
|
||||||
|
responseInterceptor: configs.responseInterceptor
|
||||||
|
})
|
||||||
|
expect(system.specActions.setMutatedRequest.calls.length).toEqual(0)
|
||||||
|
expect(system.specActions.setRequest.calls.length).toEqual(1)
|
||||||
|
|
||||||
|
|
||||||
|
let wrappedRequestInterceptor = system.fn.execute.calls[0].arguments[0].requestInterceptor
|
||||||
|
wrappedRequestInterceptor(system.fn.execute.calls[0].arguments[0])
|
||||||
|
expect(configs.requestInterceptor.calls.length).toEqual(1)
|
||||||
|
expect(system.specActions.setMutatedRequest.calls.length).toEqual(1)
|
||||||
|
expect(system.specActions.setRequest.calls.length).toEqual(1)
|
||||||
|
})
|
||||||
})
|
})
|
||||||
|
|
||||||
xit("should call specActions.setResponse, when fn.execute resolves", function(){
|
xit("should call specActions.setResponse, when fn.execute resolves", function(){
|
||||||
|
|||||||
Reference in New Issue
Block a user