Merge branch 'master' of github.com:swagger-api/swagger-ui into bug/3511-query-formData-parameters
# Conflicts: # src/core/components/parameter-row.jsx # src/core/plugins/spec/actions.js
This commit is contained in:
70
.github/issue_template.md
vendored
70
.github/issue_template.md
vendored
@@ -1,3 +1,67 @@
|
||||
When reporting an issue, please provide the following details:
|
||||
- swagger-ui version
|
||||
- a swagger file reproducing the issue
|
||||
<!---
|
||||
Thanks for filing an issue 😄 ! Before you submit, please read the following:
|
||||
|
||||
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/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 -->
|
||||
|
||||
2
.gitignore
vendored
2
.gitignore
vendored
@@ -6,3 +6,5 @@ npm-debug.log*
|
||||
.eslintcache
|
||||
package-lock.json
|
||||
*.iml
|
||||
selenium-debug.log
|
||||
test/e2e/db.json
|
||||
|
||||
54
CONTRIBUTING.md
Normal file
54
CONTRIBUTING.md
Normal file
@@ -0,0 +1,54 @@
|
||||
## Contributing to Swagger-UI
|
||||
|
||||
We love contributions from our community of users! This document explains our guidelines and workflows. Please take care to follow them, as it helps us keep things moving smoothly.
|
||||
|
||||
#### Environment setup
|
||||
|
||||
0. Install Node.js (4 or newer) and npm (3 or newer).
|
||||
1. Make a fork of Swagger-UI on GitHub, then clone your fork to your machine.
|
||||
2. Run `npm install` in your Swagger-UI directory.
|
||||
3. Run `npm run dev`. `localhost:3200` should open automatically.
|
||||
4. You're ready to go!
|
||||
|
||||
#### Branching model
|
||||
|
||||
Feature branches should be prefixed with `ft/`.
|
||||
|
||||
Bugfix branches should be prefixed with `bug/`.
|
||||
|
||||
Version branches should be prefixed with `v/`.
|
||||
|
||||
After the forward slash, include a short description of what you're fixing. For example: `bug/fix-everything-that-was-broken`. For versions, add the version that will be released via the branch, for example: `v/1.2.3`.
|
||||
|
||||
If there's an issue filed that you're addressing in your branch, include the issue number directly after the forward slash. For example: `bug/1234-fix-all-the-other-things`.
|
||||
|
||||
#### Filing issues
|
||||
|
||||
- **Do** include the Swagger-UI build you're using - you can find this by opening your console and checking `window.versions.swaggerUi`
|
||||
- **Do** include a spec that demonstrates the issue you're experiencing.
|
||||
- **Do** include screenshots, if needed. GIFs are even better!
|
||||
- **Do** place code inside of a pre-formatted container by surrounding the code with triple backticks.
|
||||
- **Don't** open tickets discussing issues with the Swagger/OpenAPI specification itself, or for issues with projects that use Swagger-UI.
|
||||
- **Don't** open an issue without searching the issue tracker for duplicates first.
|
||||
|
||||
#### Committing
|
||||
|
||||
- Break your commits into logical atomic units. Well-segmented commits make it _much_ easier for others to step through your changes.
|
||||
- Limit your subject (first) line to 50 characters (GitHub truncates more than 70).
|
||||
- Provide a body if you'd like to explain your commit in detail.
|
||||
- Capitalize the beginning of your subject line, and do not end the subject line with a period.
|
||||
- Your subject line should complete this sentence: `If applied, this commit will [your subject line].`
|
||||
- Don't use [magic GitHub words](https://help.github.com/articles/closing-issues-using-keywords/) in your commits to close issues - do that in the pull request for your code instead.
|
||||
|
||||
_Adapted from [How to Write a Git Commit Message](https://chris.beams.io/posts/git-commit/#seven-rules)._
|
||||
|
||||
#### Making pull requests
|
||||
|
||||
- **Do** summarize your changes in the PR body. If in doubt, write a bullet-point list titled `This PR does the following:`.
|
||||
- **Do** include references to issues that your PR solves, and use [magic GitHub words](https://help.github.com/articles/closing-issues-using-keywords/) to close those issues automatically when your PR is merged.
|
||||
- **Do** include tests that cover new or changed functionality.
|
||||
- **Do** be careful to follow our ESLint style rules. We recommend installing an ESLint plugin if you use a graphical code editor.
|
||||
- **Do** make sure that tests and the linter are passing by running `npm test` locally, otherwise we can't merge your pull request.
|
||||
- **Don't** include any changes to files in the `dist/` directory - we update those files only during releases.
|
||||
- **Don't** mention maintainers in your original PR body - we probably would've seen it anyway, so it just increases the noise in our inboxes. Do feel free to ping maintainers if a week has passed and you've heard nothing from us.
|
||||
- **Don't** open PRs for custom functionality that only serves a small subset of our users - custom functionality should be implemented outside of our codebase, via a plugin.
|
||||
22
README.md
22
README.md
@@ -10,10 +10,10 @@
|
||||
|
||||
As a brand new version, written from the ground up, there are some known issues and unimplemented features. Check out the [Known Issues](#known-issues) section for more details.
|
||||
|
||||
This repo publishes to two different NPM packages:
|
||||
This repository publishes to two different NPM modules:
|
||||
|
||||
* [swagger-ui](https://www.npmjs.com/package/swagger-ui) is intended for use as a node module.
|
||||
* [swagger-ui-dist](https://www.npmjs.com/package/swagger-ui-dist) comes pre-bundled with all dependencies and can be incorporated directly in a webapp.
|
||||
* [swagger-ui](https://www.npmjs.com/package/swagger-ui) is a traditional npm module intended for use in JavaScript web application projects that are capable of resolving dependencies (via Webpack, Browserify, etc).
|
||||
* [swagger-ui-dist](https://www.npmjs.com/package/swagger-ui-dist) is a dependency-free module that includes everything you need to serve Swagger-UI in a server-side project, or a web project that can't resolve npm module dependencies.
|
||||
|
||||
For the older version of swagger-ui, refer to the [*2.x branch*](https://github.com/swagger-api/swagger-ui/tree/2.x).
|
||||
|
||||
@@ -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.1.2 | 2017-07-31 | 2.0, 3.0 | [tag v3.1.2](https://github.com/swagger-api/swagger-ui/tree/v3.1.2)
|
||||
3.2.1 | 2017-09-15 | 2.0, 3.0 | [tag v3.2.1](https://github.com/swagger-api/swagger-ui/tree/v3.2.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)
|
||||
@@ -46,7 +46,7 @@ Will start nginx with swagger-ui on port 80.
|
||||
Or you can provide your own swagger.json on your host
|
||||
|
||||
```
|
||||
docker run -p 80:8080 -e "SWAGGER_JSON=/foo/swagger.json" -v /bar:/foo swaggerapi/swagger-ui
|
||||
docker run -p 80:8080 -e SWAGGER_JSON=/foo/swagger.json -v /bar:/foo swaggerapi/swagger-ui
|
||||
```
|
||||
|
||||
##### Prerequisites
|
||||
@@ -59,6 +59,15 @@ If you'd like to make modifications to the codebase, run the dev server with: `n
|
||||
|
||||
If you'd like to rebuild the `/dist` folder with your codebase changes, run `npm run build`.
|
||||
|
||||
|
||||
##### Integration Tests
|
||||
|
||||
You will need JDK of version 7 or higher as instructed here
|
||||
http://nightwatchjs.org/gettingstarted#selenium-server-setup
|
||||
|
||||
Integration tests can be run locally with `npm run e2e` - be sure you aren't running a dev server when testing!
|
||||
|
||||
|
||||
##### Browser support
|
||||
Swagger UI works in the latest versions of Chrome, Safari, Firefox, Edge and IE11.
|
||||
|
||||
@@ -151,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.
|
||||
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)
|
||||
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
|
||||
|
||||
|
||||
@@ -21,7 +21,6 @@
|
||||
{
|
||||
box-sizing: inherit;
|
||||
}
|
||||
|
||||
body {
|
||||
margin:0;
|
||||
background: #fafafa;
|
||||
|
||||
@@ -11,7 +11,11 @@
|
||||
var redirectUrl = oauth2.redirectUrl;
|
||||
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.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 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.forEach(function (v,i,_arr) { _arr[i] = '"' + v.replace('=', '":"') + '"';})
|
||||
|
||||
27
dist/swagger-ui-bundle.js
vendored
27
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;;;;;;AAy+EA;;;;;;;;;;;;;;;;;;;;;;;;;;AAw1TA;;;;;;;;;;;;;;AAs8JA;;;;;;;;;AAy6oBA;;;;;AAqqQA;AAm4DA;;;;;;AAo4YA;;;;;;AA8jaA;AAumvBA","sourceRoot":""}
|
||||
{"version":3,"file":"swagger-ui-bundle.js","sources":["webpack:///swagger-ui-bundle.js"],"mappings":"AAAA;;;;;AAwjMA;;;;;;AA65DA;;;;;;;;;;;;;;;;;;;;;;;;;;AAs9TA;;;;;;;;;;;;;;AAs8JA;;;;;;;;;AAm/pBA;;;;;AAu5QA;;;;;AAynBA;AAi0CA;;;;;;AAq/YA;;;;;;AAojaA;AA8lvBA","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;;;;;AA00CA;;;;;;AAmlFA","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;;;;;;AAyvcA","sourceRoot":""}
|
||||
{"version":3,"file":"swagger-ui.js","sources":["webpack:///swagger-ui.js"],"mappings":"AAAA;;;;;;AAmxeA","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,9 +1,10 @@
|
||||
var path = require("path")
|
||||
|
||||
var webpack = require("webpack")
|
||||
var ExtractTextPlugin = require("extract-text-webpack-plugin")
|
||||
var deepExtend = require("deep-extend")
|
||||
const {gitDescribeSync} = require("git-describe")
|
||||
var webpack = require('webpack')
|
||||
var ExtractTextPlugin = require('extract-text-webpack-plugin')
|
||||
const CopyWebpackPlugin = require('copy-webpack-plugin')
|
||||
var deepExtend = require('deep-extend')
|
||||
const {gitDescribeSync} = require('git-describe')
|
||||
const os = require("os")
|
||||
|
||||
var pkg = require("./package.json")
|
||||
@@ -60,7 +61,8 @@ module.exports = function(rules, options) {
|
||||
}))
|
||||
}
|
||||
|
||||
if( specialOptions.minimize ) {
|
||||
if( specialOptions.minimize ) { // production mode
|
||||
|
||||
plugins.push(
|
||||
new webpack.optimize.UglifyJsPlugin({
|
||||
sourceMap: true,
|
||||
@@ -74,6 +76,8 @@ module.exports = function(rules, options) {
|
||||
|
||||
plugins.push( new webpack.NoEmitOnErrorsPlugin())
|
||||
|
||||
} else { // development mode
|
||||
plugins.push(new CopyWebpackPlugin([ { from: 'test/e2e/specs', to: 'test-specs' } ]))
|
||||
}
|
||||
|
||||
plugins.push(
|
||||
|
||||
20
package.json
20
package.json
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "swagger-ui",
|
||||
"version": "3.1.2",
|
||||
"version": "3.2.1",
|
||||
"main": "dist/swagger-ui.js",
|
||||
"repository": "git@github.com:swagger-api/swagger-ui.git",
|
||||
"contributors": [
|
||||
@@ -32,11 +32,17 @@
|
||||
"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"
|
||||
"just-test-in-node": "mocha --recursive --compilers js:babel-core/register test/core test/components test/bugs test/swagger-ui-dist-package",
|
||||
"test-e2e": "sleep 3 && nightwatch test/e2e/scenarios/ --config test/e2e/nightwatch.json",
|
||||
"e2e-initial-render": "nightwatch test/e2e/scenarios/ --config test/e2e/nightwatch.json --group initial-render",
|
||||
"mock-api": "json-server --watch test/e2e/db.json --port 3204",
|
||||
"e2e": "npm-run-all --parallel -r hot-server mock-api test-e2e"
|
||||
},
|
||||
"dependencies": {
|
||||
"base64-js": "^1.2.0",
|
||||
"brace": "0.7.0",
|
||||
"classnames": "^2.2.5",
|
||||
"css.escape": "1.5.1",
|
||||
"deep-extend": "0.4.1",
|
||||
"expect": "1.20.2",
|
||||
"getbase": "^2.8.2",
|
||||
@@ -49,7 +55,7 @@
|
||||
"promise-worker": "^1.1.1",
|
||||
"prop-types": "^15.5.10",
|
||||
"react": "^15.4.0",
|
||||
"react-addons-perf": "0.14.8",
|
||||
"react-addons-perf": "^15.4.0",
|
||||
"react-addons-shallow-compare": "0.14.8",
|
||||
"react-addons-test-utils": "^15.4.0",
|
||||
"react-collapse": "2.3.1",
|
||||
@@ -71,7 +77,7 @@
|
||||
"scroll-to-element": "^2.0.0",
|
||||
"serialize-error": "2.0.0",
|
||||
"shallowequal": "0.2.2",
|
||||
"swagger-client": "3.0.19",
|
||||
"swagger-client": "3.1.1",
|
||||
"url-parse": "^1.1.8",
|
||||
"whatwg-fetch": "0.11.1",
|
||||
"worker-loader": "^0.7.1",
|
||||
@@ -90,6 +96,8 @@
|
||||
"babel-preset-react": "^6.23.0",
|
||||
"babel-preset-stage-0": "^6.22.0",
|
||||
"babel-runtime": "^6.23.0",
|
||||
"chromedriver": "^2.30.1",
|
||||
"copy-webpack-plugin": "^4.0.1",
|
||||
"css-loader": "0.28.4",
|
||||
"deep-extend": "^0.5.0",
|
||||
"deepmerge": "^1.3.2",
|
||||
@@ -100,9 +108,9 @@
|
||||
"extract-text-webpack-plugin": "^2.1.2",
|
||||
"file-loader": "0.11.2",
|
||||
"git-describe": "^4.0.1",
|
||||
"html-webpack-plugin": "^2.28.0",
|
||||
"imports-loader": "0.7.1",
|
||||
"json-loader": "0.5.4",
|
||||
"json-server": "^0.11.0",
|
||||
"karma": "^1.7.0",
|
||||
"karma-chrome-launcher": "^2.2.0",
|
||||
"karma-mocha": "^1.3.0",
|
||||
@@ -111,6 +119,7 @@
|
||||
"less": "2.7.2",
|
||||
"license-checker": "^11.0.0",
|
||||
"mocha": "^3.4.2",
|
||||
"nightwatch": "^0.9.16",
|
||||
"node-sass": "^4.5.0",
|
||||
"npm-run-all": "4.0.2",
|
||||
"null-loader": "0.1.1",
|
||||
@@ -121,6 +130,7 @@
|
||||
"react-test-renderer": "^15.5.4",
|
||||
"rimraf": "^2.6.0",
|
||||
"sass-loader": "^6.0.2",
|
||||
"selenium-server-standalone-jar": "3.4.0",
|
||||
"standard": "^10.0.2",
|
||||
"standard-loader": "^6.0.1",
|
||||
"style-loader": "0.18.2",
|
||||
|
||||
@@ -15,7 +15,7 @@ export default class ArrayModel extends Component {
|
||||
}
|
||||
|
||||
render(){
|
||||
let { getComponent, required, schema, depth, expandDepth, name } = this.props
|
||||
let { getComponent, schema, depth, expandDepth, name } = this.props
|
||||
let items = schema.get("items")
|
||||
let title = schema.get("title") || name
|
||||
let properties = schema.filter( ( v, key) => ["type", "items", "$$ref"].indexOf(key) === -1 )
|
||||
@@ -28,10 +28,15 @@ export default class ArrayModel extends Component {
|
||||
<span className="model-title__text">{ title }</span>
|
||||
</span>
|
||||
|
||||
/*
|
||||
Note: we set `name={null}` in <Model> below because we don't want
|
||||
the name of the current Model passed (and displayed) as the name of the array element Model
|
||||
*/
|
||||
|
||||
return <span className="model">
|
||||
<ModelCollapse title={titleEl} collapsed={ depth > expandDepth } collapsedContent="[...]">
|
||||
[
|
||||
<span><Model { ...this.props } schema={ items } required={ false }/></span>
|
||||
<span><Model { ...this.props } name={null} schema={ items } required={ false } depth={ depth + 1 } /></span>
|
||||
]
|
||||
{
|
||||
properties.size ? <span>
|
||||
@@ -41,7 +46,6 @@ export default class ArrayModel extends Component {
|
||||
: null
|
||||
}
|
||||
</ModelCollapse>
|
||||
{ required && <span style={{ color: "red" }}>*</span>}
|
||||
</span>
|
||||
}
|
||||
}
|
||||
|
||||
@@ -23,7 +23,7 @@ export default class AuthorizationPopup extends React.Component {
|
||||
<h3>Available authorizations</h3>
|
||||
<button type="button" className="close-modal" onClick={ this.close }>
|
||||
<svg width="20" height="20">
|
||||
<use xlinkHref="#close" />
|
||||
<use href="#close" xlinkHref="#close" />
|
||||
</svg>
|
||||
</button>
|
||||
</div>
|
||||
|
||||
@@ -25,7 +25,7 @@ export default class AuthorizeBtn extends React.Component {
|
||||
<button className={isAuthorized ? "btn authorize locked" : "btn authorize unlocked"} onClick={ this.onClick }>
|
||||
<span>Authorize</span>
|
||||
<svg width="20" height="20">
|
||||
<use xlinkHref={ isAuthorized ? "#locked" : "#unlocked" } />
|
||||
<use href={ isAuthorized ? "#locked" : "#unlocked" } xlinkHref={ isAuthorized ? "#locked" : "#unlocked" } />
|
||||
</svg>
|
||||
</button>
|
||||
{ showPopup && <AuthorizationPopup /> }
|
||||
|
||||
@@ -24,7 +24,7 @@ export default class AuthorizeOperationBtn extends React.Component {
|
||||
return (
|
||||
<button className={isAuthorized ? "authorization__btn locked" : "authorization__btn unlocked"} onClick={ this.onClick }>
|
||||
<svg width="20" height="20">
|
||||
<use xlinkHref={ isAuthorized ? "#locked" : "#unlocked" } />
|
||||
<use href={ isAuthorized ? "#locked" : "#unlocked" } xlinkHref={ isAuthorized ? "#locked" : "#unlocked" } />
|
||||
</svg>
|
||||
</button>
|
||||
|
||||
|
||||
@@ -8,6 +8,8 @@ export default class BaseLayout extends React.Component {
|
||||
errActions: PropTypes.object.isRequired,
|
||||
specActions: PropTypes.object.isRequired,
|
||||
specSelectors: PropTypes.object.isRequired,
|
||||
oas3Selectors: PropTypes.object.isRequired,
|
||||
oas3Actions: PropTypes.object.isRequired,
|
||||
layoutSelectors: PropTypes.object.isRequired,
|
||||
layoutActions: PropTypes.object.isRequired,
|
||||
getComponent: PropTypes.func.isRequired
|
||||
@@ -19,7 +21,14 @@ export default class BaseLayout extends React.Component {
|
||||
}
|
||||
|
||||
render() {
|
||||
let { specSelectors, specActions, getComponent, layoutSelectors } = this.props
|
||||
let {
|
||||
specSelectors,
|
||||
specActions,
|
||||
getComponent,
|
||||
layoutSelectors,
|
||||
oas3Selectors,
|
||||
oas3Actions
|
||||
} = this.props
|
||||
|
||||
let info = specSelectors.info()
|
||||
let url = specSelectors.url()
|
||||
@@ -28,6 +37,7 @@ export default class BaseLayout extends React.Component {
|
||||
let securityDefinitions = specSelectors.securityDefinitions()
|
||||
let externalDocs = specSelectors.externalDocs()
|
||||
let schemes = specSelectors.schemes()
|
||||
let servers = specSelectors.servers()
|
||||
|
||||
let Info = getComponent("info")
|
||||
let Operations = getComponent("operations", true)
|
||||
@@ -35,6 +45,7 @@ export default class BaseLayout extends React.Component {
|
||||
let AuthorizeBtn = getComponent("authorizeBtn", true)
|
||||
let Row = getComponent("Row")
|
||||
let Col = getComponent("Col")
|
||||
let Servers = getComponent("Servers")
|
||||
let Errors = getComponent("errors", true)
|
||||
|
||||
let isLoading = specSelectors.loadingStatus() === "loading"
|
||||
@@ -69,7 +80,10 @@ export default class BaseLayout extends React.Component {
|
||||
<div className="scheme-container">
|
||||
<Col className="schemes wrapper" mobile={12}>
|
||||
{ schemes && schemes.size ? (
|
||||
<Schemes schemes={ schemes } specActions={ specActions } />
|
||||
<Schemes
|
||||
currentScheme={specSelectors.operationScheme()}
|
||||
schemes={ schemes }
|
||||
specActions={ specActions } />
|
||||
) : null }
|
||||
|
||||
{ securityDefinitions ? (
|
||||
@@ -79,6 +93,22 @@ export default class BaseLayout extends React.Component {
|
||||
</div>
|
||||
) : 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 :
|
||||
<div className="filter-container">
|
||||
|
||||
@@ -29,13 +29,18 @@ Duration.propTypes = {
|
||||
export default class LiveResponse extends React.Component {
|
||||
static propTypes = {
|
||||
response: PropTypes.object.isRequired,
|
||||
specSelectors: PropTypes.object.isRequired,
|
||||
pathMethod: PropTypes.object.isRequired,
|
||||
getComponent: PropTypes.func.isRequired,
|
||||
displayRequestDuration: PropTypes.bool.isRequired
|
||||
displayRequestDuration: PropTypes.bool.isRequired,
|
||||
getConfigs: PropTypes.func.isRequired
|
||||
}
|
||||
|
||||
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 url = response.get("url")
|
||||
const headers = response.get("headers").toJS()
|
||||
@@ -55,7 +60,7 @@ export default class LiveResponse extends React.Component {
|
||||
|
||||
return (
|
||||
<div>
|
||||
{ request && <Curl request={ request }/> }
|
||||
{ curlRequest && <Curl request={ curlRequest }/> }
|
||||
<h4>Server response</h4>
|
||||
<table className="responses-table">
|
||||
<thead>
|
||||
|
||||
@@ -30,39 +30,38 @@ export default class Model extends Component {
|
||||
|
||||
render () {
|
||||
let { getComponent, specSelectors, schema, required, name, isRef } = this.props
|
||||
let ObjectModel = getComponent("ObjectModel")
|
||||
let ArrayModel = getComponent("ArrayModel")
|
||||
let PrimitiveModel = getComponent("PrimitiveModel")
|
||||
const ObjectModel = getComponent("ObjectModel")
|
||||
const ArrayModel = getComponent("ArrayModel")
|
||||
const PrimitiveModel = getComponent("PrimitiveModel")
|
||||
let type = "object"
|
||||
let $$ref = schema && schema.get("$$ref")
|
||||
let modelName = $$ref && this.getModelName( $$ref )
|
||||
let modelSchema, type
|
||||
|
||||
// If we weren't passed a `name` but have a ref, grab the name from the ref
|
||||
if ( !name && $$ref ) {
|
||||
name = this.getModelName( $$ref )
|
||||
}
|
||||
// If we weren't passed a `schema` but have a ref, grab the schema from the ref
|
||||
if ( !schema && $$ref ) {
|
||||
schema = this.getRefSchema( name )
|
||||
}
|
||||
|
||||
const deprecated = specSelectors.isOAS3() && schema.get("deprecated")
|
||||
|
||||
if ( schema && (schema.get("type") || schema.get("properties")) ) {
|
||||
modelSchema = schema
|
||||
} else if ( $$ref ) {
|
||||
modelSchema = this.getRefSchema( modelName )
|
||||
}
|
||||
|
||||
type = modelSchema && modelSchema.get("type")
|
||||
if ( !type && modelSchema && modelSchema.get("properties") ) {
|
||||
type = "object"
|
||||
}
|
||||
isRef = isRef !== undefined ? isRef : !!$$ref
|
||||
type = schema && schema.get("type") || type
|
||||
|
||||
switch(type) {
|
||||
case "object":
|
||||
return <ObjectModel
|
||||
className="object" { ...this.props }
|
||||
schema={ modelSchema }
|
||||
name={ name || modelName }
|
||||
schema={ schema }
|
||||
name={ name }
|
||||
deprecated={deprecated}
|
||||
isRef={ isRef!== undefined ? isRef : !!$$ref } />
|
||||
isRef={ isRef } />
|
||||
case "array":
|
||||
return <ArrayModel
|
||||
className="array" { ...this.props }
|
||||
schema={ modelSchema }
|
||||
name={ name || modelName }
|
||||
schema={ schema }
|
||||
name={ name }
|
||||
deprecated={deprecated}
|
||||
required={ required } />
|
||||
case "string":
|
||||
@@ -73,9 +72,10 @@ export default class Model extends Component {
|
||||
return <PrimitiveModel
|
||||
{ ...this.props }
|
||||
getComponent={ getComponent }
|
||||
schema={ modelSchema }
|
||||
name={ name || modelName }
|
||||
schema={ schema }
|
||||
name={ name }
|
||||
deprecated={deprecated}
|
||||
required={ required }/> }
|
||||
required={ required }/>
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -24,7 +24,7 @@ export default class Models extends Component {
|
||||
return <section className={ showModels ? "models is-open" : "models"}>
|
||||
<h4 onClick={() => layoutActions.show("models", !showModels)}>
|
||||
<span>Models</span>
|
||||
<svg className="arrow" width="20" height="20">
|
||||
<svg width="20" height="20">
|
||||
<use xlinkHref={showModels ? "#large-arrow-down" : "#large-arrow"} />
|
||||
</svg>
|
||||
</h4>
|
||||
@@ -34,7 +34,6 @@ export default class Models extends Component {
|
||||
return <div className="model-container" key={ `models-section-${name}` }>
|
||||
<ModelWrapper name={ name }
|
||||
schema={ model }
|
||||
isRef={ true }
|
||||
getComponent={ getComponent }
|
||||
specSelectors={ specSelectors }/>
|
||||
</div>
|
||||
|
||||
@@ -17,9 +17,10 @@ export default class ObjectModel extends Component {
|
||||
}
|
||||
|
||||
render(){
|
||||
let { schema, name, isRef, getComponent, depth, ...props } = this.props
|
||||
let { expandDepth, specSelectors } = this.props
|
||||
let { schema, name, isRef, getComponent, depth, expandDepth, ...otherProps } = this.props
|
||||
let { specSelectors } = otherProps
|
||||
let { isOAS3 } = specSelectors
|
||||
|
||||
let description = schema.get("description")
|
||||
let properties = schema.get("properties")
|
||||
let additionalProperties = schema.get("additionalProperties")
|
||||
@@ -59,7 +60,7 @@ export default class ObjectModel extends Component {
|
||||
}
|
||||
<span className="inner-object">
|
||||
{
|
||||
<table className="model" style={{ marginLeft: "2em" }}><tbody>
|
||||
<table className="model"><tbody>
|
||||
{
|
||||
!description ? null : <tr style={{ color: "#999", fontStyle: "italic" }}>
|
||||
<td>description:</td>
|
||||
@@ -82,7 +83,7 @@ export default class ObjectModel extends Component {
|
||||
{ key }{ isRequired && <span style={{ color: "red" }}>*</span> }
|
||||
</td>
|
||||
<td style={{ verticalAlign: "top" }}>
|
||||
<Model key={ `object-${name}-${key}_${value}` } { ...props }
|
||||
<Model key={ `object-${name}-${key}_${value}` } { ...otherProps }
|
||||
required={ isRequired }
|
||||
getComponent={ getComponent }
|
||||
schema={ value }
|
||||
@@ -96,7 +97,7 @@ export default class ObjectModel extends Component {
|
||||
: <tr>
|
||||
<td>{ "< * >:" }</td>
|
||||
<td>
|
||||
<Model { ...props } required={ false }
|
||||
<Model { ...otherProps } required={ false }
|
||||
getComponent={ getComponent }
|
||||
schema={ additionalProperties }
|
||||
depth={ depth + 1 } />
|
||||
@@ -109,7 +110,7 @@ export default class ObjectModel extends Component {
|
||||
<td>{ "anyOf ->" }</td>
|
||||
<td>
|
||||
{anyOf.map((schema, k) => {
|
||||
return <div key={k}><Model { ...props } required={ false }
|
||||
return <div key={k}><Model { ...otherProps } required={ false }
|
||||
getComponent={ getComponent }
|
||||
schema={ schema }
|
||||
depth={ depth + 1 } /></div>
|
||||
@@ -123,7 +124,7 @@ export default class ObjectModel extends Component {
|
||||
<td>{ "oneOf ->" }</td>
|
||||
<td>
|
||||
{oneOf.map((schema, k) => {
|
||||
return <div key={k}><Model { ...props } required={ false }
|
||||
return <div key={k}><Model { ...otherProps } required={ false }
|
||||
getComponent={ getComponent }
|
||||
schema={ schema }
|
||||
depth={ depth + 1 } /></div>
|
||||
@@ -137,7 +138,7 @@ export default class ObjectModel extends Component {
|
||||
<td>{ "not ->" }</td>
|
||||
<td>
|
||||
{not.map((schema, k) => {
|
||||
return <div key={k}><Model { ...props } required={ false }
|
||||
return <div key={k}><Model { ...otherProps } required={ false }
|
||||
getComponent={ getComponent }
|
||||
schema={ schema }
|
||||
depth={ depth + 1 } /></div>
|
||||
|
||||
@@ -28,6 +28,7 @@ export default class Operation extends PureComponent {
|
||||
authSelectors: PropTypes.object,
|
||||
specActions: PropTypes.object.isRequired,
|
||||
specSelectors: PropTypes.object.isRequired,
|
||||
oas3Actions: PropTypes.object.isRequired,
|
||||
layoutActions: PropTypes.object.isRequired,
|
||||
layoutSelectors: PropTypes.object.isRequired,
|
||||
fn: PropTypes.object.isRequired,
|
||||
@@ -117,7 +118,8 @@ export default class Operation extends PureComponent {
|
||||
specSelectors,
|
||||
authActions,
|
||||
authSelectors,
|
||||
getConfigs
|
||||
getConfigs,
|
||||
oas3Actions
|
||||
} = this.props
|
||||
|
||||
let summary = operation.get("summary")
|
||||
@@ -163,8 +165,8 @@ export default class Operation extends PureComponent {
|
||||
<span className={ deprecated ? "opblock-summary-path__deprecated" : "opblock-summary-path" } >
|
||||
<a
|
||||
className="nostyle"
|
||||
onClick={(e) => e.preventDefault()}
|
||||
href={ isDeepLinkingEnabled ? `#/${isShownKey[1]}/${isShownKey[2]}` : ""} >
|
||||
onClick={isDeepLinkingEnabled ? (e) => e.preventDefault() : null}
|
||||
href={isDeepLinkingEnabled ? `#/${isShownKey[1]}/${isShownKey[2]}` : null}>
|
||||
<span>{path}</span>
|
||||
</a>
|
||||
<JumpToPath path={jumpToKey} />
|
||||
@@ -186,7 +188,7 @@ export default class Operation extends PureComponent {
|
||||
}
|
||||
</div>
|
||||
|
||||
<Collapse isOpened={shown} animated>
|
||||
<Collapse isOpened={shown}>
|
||||
<div className="opblock-body">
|
||||
{ deprecated && <h4 className="opblock-title_normal"> Warning: Deprecated</h4>}
|
||||
{ description &&
|
||||
@@ -229,7 +231,7 @@ export default class Operation extends PureComponent {
|
||||
path={ path }
|
||||
method={ method }
|
||||
specActions={ specActions }
|
||||
operationScheme={ operationScheme } />
|
||||
currentScheme={ operationScheme } />
|
||||
</div> : null
|
||||
}
|
||||
|
||||
@@ -263,7 +265,9 @@ export default class Operation extends PureComponent {
|
||||
request={ request }
|
||||
tryItOutResponse={ response }
|
||||
getComponent={ getComponent }
|
||||
getConfigs={ getConfigs }
|
||||
specSelectors={ specSelectors }
|
||||
oas3Actions={oas3Actions}
|
||||
specActions={ specActions }
|
||||
produces={ produces }
|
||||
producesValue={ operation.get("produces_value") }
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
import React from "react"
|
||||
import PropTypes from "prop-types"
|
||||
import { helpers } from "swagger-client"
|
||||
|
||||
import { createDeepLinkPath } from "core/utils"
|
||||
const { opId } = helpers
|
||||
|
||||
export default class Operations extends React.Component {
|
||||
@@ -9,6 +9,7 @@ export default class Operations extends React.Component {
|
||||
static propTypes = {
|
||||
specSelectors: PropTypes.object.isRequired,
|
||||
specActions: PropTypes.object.isRequired,
|
||||
oas3Actions: PropTypes.object.isRequired,
|
||||
getComponent: PropTypes.func.isRequired,
|
||||
layoutSelectors: PropTypes.object.isRequired,
|
||||
layoutActions: PropTypes.object.isRequired,
|
||||
@@ -21,6 +22,7 @@ export default class Operations extends React.Component {
|
||||
let {
|
||||
specSelectors,
|
||||
specActions,
|
||||
oas3Actions,
|
||||
getComponent,
|
||||
layoutSelectors,
|
||||
layoutActions,
|
||||
@@ -69,7 +71,7 @@ export default class Operations extends React.Component {
|
||||
let tagExternalDocsDescription = tagObj.getIn(["tagDetails", "externalDocs", "description"])
|
||||
let tagExternalDocsUrl = tagObj.getIn(["tagDetails", "externalDocs", "url"])
|
||||
|
||||
let isShownKey = ["operations-tag", tag]
|
||||
let isShownKey = ["operations-tag", createDeepLinkPath(tag)]
|
||||
let showTag = layoutSelectors.isShown(isShownKey, docExpansion === "full" || docExpansion === "list")
|
||||
|
||||
return (
|
||||
@@ -81,8 +83,8 @@ export default class Operations extends React.Component {
|
||||
id={isShownKey.join("-")}>
|
||||
<a
|
||||
className="nostyle"
|
||||
onClick={(e) => e.preventDefault()}
|
||||
href={ isDeepLinkingEnabled ? `#/${tag}` : ""}>
|
||||
onClick={isDeepLinkingEnabled ? (e) => e.preventDefault() : null}
|
||||
href= {isDeepLinkingEnabled ? `#/${tag}` : null}>
|
||||
<span>{tag}</span>
|
||||
</a>
|
||||
{ !tagDescription ? null :
|
||||
@@ -109,7 +111,7 @@ export default class Operations extends React.Component {
|
||||
|
||||
<button className="expand-operation" title="Expand operation" onClick={() => layoutActions.show(isShownKey, !showTag)}>
|
||||
<svg className="arrow" width="20" height="20">
|
||||
<use xlinkHref={showTag ? "#large-arrow-down" : "#large-arrow"} />
|
||||
<use href={showTag ? "#large-arrow-down" : "#large-arrow"} xlinkHref={showTag ? "#large-arrow-down" : "#large-arrow"} />
|
||||
</svg>
|
||||
</button>
|
||||
</h4>
|
||||
@@ -124,7 +126,7 @@ export default class Operations extends React.Component {
|
||||
|
||||
const operationId =
|
||||
op.getIn(["operation", "operationId"]) || op.getIn(["operation", "__originalOperationId"]) || opId(op.get("operation"), path, method) || op.get("id")
|
||||
const isShownKey = ["operations", tag, operationId]
|
||||
const isShownKey = ["operations", createDeepLinkPath(tag), createDeepLinkPath(operationId)]
|
||||
|
||||
const allowTryItOut = specSelectors.allowTryItOutFor(op.get("path"), op.get("method"))
|
||||
const response = specSelectors.responseFor(op.get("path"), op.get("method"))
|
||||
@@ -147,6 +149,8 @@ export default class Operations extends React.Component {
|
||||
specActions={ specActions }
|
||||
specSelectors={ specSelectors }
|
||||
|
||||
oas3Actions={oas3Actions}
|
||||
|
||||
layoutActions={ layoutActions }
|
||||
layoutSelectors={ layoutSelectors }
|
||||
|
||||
|
||||
@@ -69,7 +69,9 @@ export default class ParamBody extends PureComponent {
|
||||
let { param, fn:{inferSchema} } = this.props
|
||||
let schema = inferSchema(param.toJS())
|
||||
|
||||
return getSampleSchema(schema, xml)
|
||||
return getSampleSchema(schema, xml, {
|
||||
includeWriteOnly: true
|
||||
})
|
||||
}
|
||||
|
||||
onChange = (value, { isEditBox, isXml }) => {
|
||||
|
||||
@@ -62,6 +62,8 @@ export default class ParameterRow extends Component {
|
||||
render() {
|
||||
let {param, onChange, getComponent, isExecute, fn, onChangeConsumes, specSelectors, pathMethod} = this.props
|
||||
|
||||
let { isOAS3 } = specSelectors
|
||||
|
||||
// const onChangeWrapper = (value) => onChange(param, value)
|
||||
const JsonSchemaForm = getComponent("JsonSchemaForm")
|
||||
const ParamBody = getComponent("ParamBody")
|
||||
@@ -83,11 +85,11 @@ export default class ParameterRow extends Component {
|
||||
const Markdown = getComponent("Markdown")
|
||||
|
||||
let schema = param.get("schema")
|
||||
|
||||
let type = isOAS3 && isOAS3() ? param.getIn(["schema", "type"]) : param.get("type")
|
||||
let isFormData = inType === "formData"
|
||||
let isFormDataSupported = "FormData" in win
|
||||
let required = param.get("required")
|
||||
let itemType = param.getIn(["items", "type"])
|
||||
let itemType = param.getIn(isOAS3 && isOAS3() ? ["schema", "items", "type"] : ["items", "type"])
|
||||
let parameter = specSelectors.getParameter(pathMethod, param.get("name"), param.get("in"))
|
||||
let value = parameter ? parameter.get("value") : ""
|
||||
|
||||
@@ -98,7 +100,10 @@ export default class ParameterRow extends Component {
|
||||
{ param.get("name") }
|
||||
{ !required ? null : <span style={{color: "red"}}> *</span> }
|
||||
</div>
|
||||
<div className="parameter__type">{ param.get("type") } { itemType && `[${itemType}]` }</div>
|
||||
<div className="parameter__type">{ type } { itemType && `[${itemType}]` }</div>
|
||||
<div className="parameter__deprecated">
|
||||
{ isOAS3 && isOAS3() && param.get("deprecated") ? "deprecated": null }
|
||||
</div>
|
||||
<div className="parameter__in">({ param.get("in") })</div>
|
||||
</td>
|
||||
|
||||
|
||||
@@ -7,11 +7,12 @@ export default class Primitive extends Component {
|
||||
static propTypes = {
|
||||
schema: PropTypes.object.isRequired,
|
||||
getComponent: PropTypes.func.isRequired,
|
||||
required: PropTypes.bool
|
||||
name: PropTypes.string,
|
||||
depth: PropTypes.number
|
||||
}
|
||||
|
||||
render(){
|
||||
let { schema, getComponent, required } = this.props
|
||||
let { schema, getComponent, name, depth } = this.props
|
||||
|
||||
if(!schema || !schema.get) {
|
||||
// don't render if schema isn't correctly formed
|
||||
@@ -24,12 +25,13 @@ export default class Primitive extends Component {
|
||||
let enumArray = schema.get("enum")
|
||||
let description = schema.get("description")
|
||||
let properties = schema.filter( ( v, key) => ["enum", "type", "format", "description", "$$ref"].indexOf(key) === -1 )
|
||||
let style = required ? { fontWeight: "bold" } : {}
|
||||
const Markdown = getComponent("Markdown")
|
||||
const EnumModel = getComponent("EnumModel")
|
||||
|
||||
return <span className="prop">
|
||||
<span className="prop-type" style={ style }>{ type }</span> { required && <span style={{ color: "red" }}>*</span>}
|
||||
return <span className="model">
|
||||
<span className="prop">
|
||||
{ name && <span className={`${depth === 1 && "model-title"} prop-name`}>{ name }</span> }
|
||||
<span className="prop-type">{ type }</span>
|
||||
{ format && <span className="prop-format">(${format})</span>}
|
||||
{
|
||||
properties.size ? properties.entrySeq().map( ( [ key, v ] ) => <span key={`${key}-${v}`} style={ propStyle }>
|
||||
@@ -51,5 +53,6 @@ export default class Primitive extends Component {
|
||||
enumArray && <EnumModel value={ enumArray } getComponent={ getComponent } />
|
||||
}
|
||||
</span>
|
||||
</span>
|
||||
}
|
||||
}
|
||||
@@ -1,7 +1,8 @@
|
||||
import React from "react"
|
||||
import PropTypes from "prop-types"
|
||||
import cx from "classnames"
|
||||
import { fromJS, Seq } from "immutable"
|
||||
import { getSampleSchema } from "core/utils"
|
||||
import { getSampleSchema, fromJSOrdered } from "core/utils"
|
||||
|
||||
const getExampleComponent = ( sampleResponse, examples, HighlightCode ) => {
|
||||
if ( examples && examples.size ) {
|
||||
@@ -46,23 +47,35 @@ export default class Response extends React.Component {
|
||||
getComponent: PropTypes.func.isRequired,
|
||||
specSelectors: PropTypes.object.isRequired,
|
||||
fn: PropTypes.object.isRequired,
|
||||
contentType: PropTypes.string
|
||||
contentType: PropTypes.string,
|
||||
controlsAcceptHeader: PropTypes.bool,
|
||||
onContentTypeChange: PropTypes.func
|
||||
}
|
||||
|
||||
static defaultProps = {
|
||||
response: fromJS({}),
|
||||
onContentTypeChange: () => {}
|
||||
};
|
||||
|
||||
_onContentTypeChange = (value) => {
|
||||
const { onContentTypeChange, controlsAcceptHeader } = this.props
|
||||
this.setState({ responseContentType: value })
|
||||
onContentTypeChange({
|
||||
value: value,
|
||||
controlsAcceptHeader
|
||||
})
|
||||
}
|
||||
|
||||
render() {
|
||||
let {
|
||||
code,
|
||||
response,
|
||||
className,
|
||||
|
||||
fn,
|
||||
getComponent,
|
||||
specSelectors,
|
||||
contentType
|
||||
contentType,
|
||||
controlsAcceptHeader
|
||||
} = this.props
|
||||
|
||||
let { inferSchema } = fn
|
||||
@@ -83,11 +96,16 @@ export default class Response extends React.Component {
|
||||
|
||||
if(isOAS3()) {
|
||||
let oas3SchemaForContentType = response.getIn(["content", this.state.responseContentType, "schema"])
|
||||
sampleResponse = oas3SchemaForContentType ? getSampleSchema(oas3SchemaForContentType.toJS(), this.state.responseContentType, { includeReadOnly: true }) : null
|
||||
sampleResponse = oas3SchemaForContentType ? getSampleSchema(oas3SchemaForContentType.toJS(), this.state.responseContentType, {
|
||||
includeReadOnly: true
|
||||
}) : null
|
||||
schema = oas3SchemaForContentType ? inferSchema(oas3SchemaForContentType.toJS()) : null
|
||||
} else {
|
||||
schema = inferSchema(response.toJS())
|
||||
sampleResponse = schema ? getSampleSchema(schema, contentType, { includeReadOnly: true }) : null
|
||||
sampleResponse = schema ? getSampleSchema(schema, contentType, {
|
||||
includeReadOnly: true,
|
||||
includeWriteOnly: true // writeOnly has no filtering effect in swagger 2.0
|
||||
}) : null
|
||||
}
|
||||
let example = getExampleComponent( sampleResponse, examples, HighlightCode )
|
||||
|
||||
@@ -102,17 +120,24 @@ export default class Response extends React.Component {
|
||||
<Markdown source={ response.get( "description" ) } />
|
||||
</div>
|
||||
|
||||
{ isOAS3 ? <ContentType
|
||||
{ isOAS3 ?
|
||||
<div className={cx("response-content-type", {
|
||||
"controls-accept-header": controlsAcceptHeader
|
||||
})}>
|
||||
<ContentType
|
||||
value={this.state.responseContentType}
|
||||
contentTypes={ response.get("content") ? response.get("content").keySeq() : Seq() }
|
||||
onChange={(val) => this.setState({ responseContentType: val })}
|
||||
className="response-content-type" /> : null }
|
||||
onChange={this._onContentTypeChange}
|
||||
/>
|
||||
{ controlsAcceptHeader ? <small>Controls <code>Accept</code> header.</small> : null }
|
||||
</div>
|
||||
: null }
|
||||
|
||||
{ example ? (
|
||||
<ModelExample
|
||||
getComponent={ getComponent }
|
||||
specSelectors={ specSelectors }
|
||||
schema={ fromJS(schema) }
|
||||
schema={ fromJSOrdered(schema) }
|
||||
example={ example }/>
|
||||
) : null}
|
||||
|
||||
@@ -122,10 +147,10 @@ export default class Response extends React.Component {
|
||||
|
||||
|
||||
</td>
|
||||
{specSelectors.isOAS3() ? <td>
|
||||
{specSelectors.isOAS3() ? <td className="col response-col_links">
|
||||
{ links ?
|
||||
links.toSeq().map((link, key) => {
|
||||
return <OperationLink key={key} name={key} link={ link }/>
|
||||
return <OperationLink key={key} name={key} link={ link } getComponent={getComponent}/>
|
||||
})
|
||||
: <i>No links</i>}
|
||||
</td> : null}
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
import React from "react"
|
||||
import PropTypes from "prop-types"
|
||||
import { fromJS } from "immutable"
|
||||
import { defaultStatusCode } from "core/utils"
|
||||
import { defaultStatusCode, getAcceptControllingResponse } from "core/utils"
|
||||
|
||||
export default class Responses extends React.Component {
|
||||
|
||||
@@ -14,9 +14,11 @@ export default class Responses extends React.Component {
|
||||
getComponent: PropTypes.func.isRequired,
|
||||
specSelectors: PropTypes.object.isRequired,
|
||||
specActions: PropTypes.object.isRequired,
|
||||
oas3Actions: PropTypes.object.isRequired,
|
||||
pathMethod: PropTypes.array.isRequired,
|
||||
displayRequestDuration: PropTypes.bool.isRequired,
|
||||
fn: PropTypes.object.isRequired
|
||||
fn: PropTypes.object.isRequired,
|
||||
getConfigs: PropTypes.func.isRequired
|
||||
}
|
||||
|
||||
static defaultProps = {
|
||||
@@ -28,8 +30,28 @@ export default class Responses extends React.Component {
|
||||
|
||||
onChangeProducesWrapper = ( val ) => this.props.specActions.changeProducesValue(this.props.pathMethod, val)
|
||||
|
||||
onResponseContentTypeChange = ({ controlsAcceptHeader, value }) => {
|
||||
const { oas3Actions, pathMethod } = this.props
|
||||
if(controlsAcceptHeader) {
|
||||
oas3Actions.setResponseContentType({
|
||||
value,
|
||||
pathMethod
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
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 )
|
||||
|
||||
const ContentType = getComponent( "contentType" )
|
||||
@@ -38,6 +60,11 @@ export default class Responses extends React.Component {
|
||||
|
||||
let produces = this.props.produces && this.props.produces.size ? this.props.produces : Responses.defaultProps.produces
|
||||
|
||||
const isSpecOAS3 = specSelectors.isOAS3()
|
||||
|
||||
const acceptControllingResponse = isSpecOAS3 ?
|
||||
getAcceptControllingResponse(responses) : null
|
||||
|
||||
return (
|
||||
<div className="responses-wrapper">
|
||||
<div className="opblock-section-header">
|
||||
@@ -57,6 +84,9 @@ export default class Responses extends React.Component {
|
||||
<LiveResponse request={ request }
|
||||
response={ tryItOutResponse }
|
||||
getComponent={ getComponent }
|
||||
getConfigs={ getConfigs }
|
||||
specSelectors={ specSelectors }
|
||||
pathMethod={ this.props.pathMethod }
|
||||
displayRequestDuration={ displayRequestDuration } />
|
||||
<h4>Responses</h4>
|
||||
</div>
|
||||
@@ -68,13 +98,12 @@ export default class Responses extends React.Component {
|
||||
<tr className="responses-header">
|
||||
<td className="col col_header response-col_status">Code</td>
|
||||
<td className="col col_header response-col_description">Description</td>
|
||||
{ specSelectors.isOAS3() ? <td className="col col_header response-col_description">Links</td> : null }
|
||||
{ specSelectors.isOAS3() ? <td className="col col_header response-col_links">Links</td> : null }
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
{
|
||||
responses.entrySeq().map( ([code, response]) => {
|
||||
|
||||
let className = tryItOutResponse && tryItOutResponse.get("status") == code ? "response_current" : ""
|
||||
return (
|
||||
<Response key={ code }
|
||||
@@ -84,6 +113,8 @@ export default class Responses extends React.Component {
|
||||
code={ code }
|
||||
response={ response }
|
||||
specSelectors={ specSelectors }
|
||||
controlsAcceptHeader={response === acceptControllingResponse}
|
||||
onContentTypeChange={this.onResponseContentTypeChange}
|
||||
contentType={ producesValue }
|
||||
getComponent={ getComponent }/>
|
||||
)
|
||||
|
||||
@@ -6,9 +6,9 @@ export default class Schemes extends React.Component {
|
||||
static propTypes = {
|
||||
specActions: PropTypes.object.isRequired,
|
||||
schemes: PropTypes.object.isRequired,
|
||||
currentScheme: PropTypes.string.isRequired,
|
||||
path: PropTypes.string,
|
||||
method: PropTypes.string,
|
||||
operationScheme: PropTypes.string
|
||||
}
|
||||
|
||||
componentWillMount() {
|
||||
@@ -19,8 +19,8 @@ export default class Schemes extends React.Component {
|
||||
}
|
||||
|
||||
componentWillReceiveProps(nextProps) {
|
||||
if ( !this.props.operationScheme || !nextProps.schemes.has(this.props.operationScheme) ) {
|
||||
// if we don't have a selected operationScheme or if our selected scheme is no longer an option,
|
||||
if ( !this.props.currentScheme || !nextProps.schemes.includes(this.props.currentScheme) ) {
|
||||
// if we don't have a selected currentScheme or if our selected scheme is no longer an option,
|
||||
// then fire 'change' event and select the first scheme in the list of options
|
||||
this.setScheme(nextProps.schemes.first())
|
||||
}
|
||||
|
||||
@@ -20,7 +20,7 @@ export default function curl( request ){
|
||||
if ( request.get("body") ){
|
||||
|
||||
if(type === "multipart/form-data" && request.get("method") === "POST") {
|
||||
for( let [ k,v ] of request.get("body").values()) {
|
||||
for( let [ k,v ] of request.get("body").entrySeq()) {
|
||||
curlified.push( "-F" )
|
||||
if (v instanceof win.File) {
|
||||
curlified.push( `"${k}=@${v.name};type=${v.type}"` )
|
||||
|
||||
@@ -6,6 +6,11 @@ import ApisPreset from "core/presets/apis"
|
||||
import * as AllPlugins from "core/plugins/all"
|
||||
import { parseSearch } from "core/utils"
|
||||
|
||||
if (process.env.NODE_ENV !== "production") {
|
||||
const Perf = require("react-addons-perf")
|
||||
window.Perf = Perf
|
||||
}
|
||||
|
||||
// eslint-disable-next-line no-undef
|
||||
const { GIT_DIRTY, GIT_COMMIT, PACKAGE_VERSION, HOSTNAME, BUILD_TIME } = buildInfo
|
||||
|
||||
@@ -37,6 +42,9 @@ module.exports = function SwaggerUI(opts) {
|
||||
displayOperationId: false,
|
||||
displayRequestDuration: 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.
|
||||
// Instead, we can compile the first plugin ( it can be a collection of plugins ), then batch the rest.
|
||||
@@ -59,6 +67,9 @@ module.exports = function SwaggerUI(opts) {
|
||||
|
||||
let queryConfig = parseSearch()
|
||||
|
||||
const domNode = opts.domNode
|
||||
delete opts.domNode
|
||||
|
||||
const constructorConfig = deepExtend({}, defaults, opts, queryConfig)
|
||||
|
||||
const storeConfigs = deepExtend({}, constructorConfig.store, {
|
||||
@@ -102,8 +113,8 @@ module.exports = function SwaggerUI(opts) {
|
||||
let mergedConfig = deepExtend({}, localConfig, constructorConfig, fetchedConfig || {}, queryConfig)
|
||||
|
||||
// deep extend mangles domNode, we need to set it manually
|
||||
if(opts.domNode) {
|
||||
mergedConfig.domNode = opts.domNode
|
||||
if(domNode) {
|
||||
mergedConfig.domNode = domNode
|
||||
}
|
||||
|
||||
store.setConfigs(mergedConfig)
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
import { setHash } from "./helpers"
|
||||
import { createDeepLinkPath } from "core/utils"
|
||||
|
||||
export const show = (ori, { getConfigs }) => (...args) => {
|
||||
ori(...args)
|
||||
@@ -19,12 +20,12 @@ export const show = (ori, { getConfigs }) => (...args) => {
|
||||
|
||||
if(type === "operations") {
|
||||
let [, tag, operationId] = thing
|
||||
setHash(`/${tag}/${operationId}`)
|
||||
setHash(`/${createDeepLinkPath(tag)}/${createDeepLinkPath(operationId)}`)
|
||||
}
|
||||
|
||||
if(type === "operations-tag") {
|
||||
let [, tag] = thing
|
||||
setHash(`/${tag}`)
|
||||
setHash(`/${createDeepLinkPath(tag)}`)
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
import scrollTo from "scroll-to-element"
|
||||
import { escapeDeepLinkPath } from "core/utils"
|
||||
|
||||
const SCROLL_OFFSET = -5
|
||||
let hasHashBeenParsed = false
|
||||
@@ -34,14 +35,14 @@ export const updateResolved = (ori, { layoutActions, getConfigs }) => (...args)
|
||||
layoutActions.show(["operations-tag", tag], true)
|
||||
layoutActions.show(["operations", tag, operationId], true)
|
||||
|
||||
scrollTo(`#operations-${tag}-${operationId}`, {
|
||||
scrollTo(`#operations-${escapeDeepLinkPath(tag)}-${escapeDeepLinkPath(operationId)}`, {
|
||||
offset: SCROLL_OFFSET
|
||||
})
|
||||
} else if(tag) {
|
||||
// Pre-expand and scroll to the tag
|
||||
layoutActions.show(["operations-tag", tag], true)
|
||||
|
||||
scrollTo(`#operations-tag-${tag}`, {
|
||||
scrollTo(`#operations-tag-${escapeDeepLinkPath(tag)}`, {
|
||||
offset: SCROLL_OFFSET
|
||||
})
|
||||
}
|
||||
|
||||
43
src/core/plugins/oas3/actions.js
Normal file
43
src/core/plugins/oas3/actions.js
Normal file
@@ -0,0 +1,43 @@
|
||||
// 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_RESPONSE_CONTENT_TYPE = "oas3_set_response_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 setResponseContentType ({ value, pathMethod }) {
|
||||
return {
|
||||
type: UPDATE_RESPONSE_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 RequestBody from "./request-body"
|
||||
import OperationLink from "./operation-link.jsx"
|
||||
import Servers from "./servers"
|
||||
import RequestBodyEditor from "./request-body-editor"
|
||||
|
||||
export default {
|
||||
Callbacks,
|
||||
RequestBody,
|
||||
Servers,
|
||||
RequestBodyEditor,
|
||||
operationLink: OperationLink
|
||||
}
|
||||
|
||||
@@ -4,19 +4,24 @@ import ImPropTypes from "react-immutable-proptypes"
|
||||
|
||||
class OperationLink extends Component {
|
||||
render() {
|
||||
const { link, name } = this.props
|
||||
const { link, name, getComponent } = this.props
|
||||
|
||||
const Markdown = getComponent("Markdown")
|
||||
|
||||
let targetOp = link.get("operationId") || link.get("operationRef")
|
||||
let parameters = link.get("parameters") && link.get("parameters").toJS()
|
||||
let description = link.get("description")
|
||||
|
||||
return <span>
|
||||
<div style={{ padding: "5px 2px" }}>{name}{description ? `: ${description}` : ""}</div>
|
||||
return <div style={{ marginBottom: "1.5em" }}>
|
||||
<div style={{ marginBottom: ".5em" }}>
|
||||
<b><code>{name}</code></b>
|
||||
{ description ? <Markdown source={description}></Markdown> : null }
|
||||
</div>
|
||||
<pre>
|
||||
Operation `{targetOp}`<br /><br />
|
||||
Parameters {padString(0, JSON.stringify(parameters, null, 2)) || "{}"}<br />
|
||||
</pre>
|
||||
</span>
|
||||
</div>
|
||||
}
|
||||
|
||||
}
|
||||
@@ -30,6 +35,7 @@ function padString(n, string) {
|
||||
}
|
||||
|
||||
OperationLink.propTypes = {
|
||||
getComponent: PropTypes.func.isRequired,
|
||||
link: ImPropTypes.orderedMap.isRequired,
|
||||
name: PropTypes.String
|
||||
}
|
||||
|
||||
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 ImPropTypes from "react-immutable-proptypes"
|
||||
import { OrderedMap } from "immutable"
|
||||
import { getSampleSchema } from "core/utils"
|
||||
|
||||
|
||||
const RequestBody = ({ requestBody, getComponent, specSelectors, contentType }) => {
|
||||
const RequestBody = ({
|
||||
requestBody,
|
||||
getComponent,
|
||||
specSelectors,
|
||||
contentType,
|
||||
isExecute,
|
||||
onChange
|
||||
}) => {
|
||||
const Markdown = getComponent("Markdown")
|
||||
const ModelExample = getComponent("modelExample")
|
||||
const HighlightCode = getComponent("highlightCode")
|
||||
const RequestBodyEditor = getComponent("RequestBodyEditor")
|
||||
|
||||
const requestBodyDescription = (requestBody && requestBody.get("description")) || null
|
||||
const requestBodyContent = (requestBody && requestBody.get("content")) || new OrderedMap()
|
||||
@@ -16,8 +21,6 @@ const RequestBody = ({ requestBody, getComponent, specSelectors, contentType })
|
||||
|
||||
const mediaTypeValue = requestBodyContent.get(contentType)
|
||||
|
||||
const sampleSchema = getSampleSchema(mediaTypeValue.get("schema").toJS(), contentType)
|
||||
|
||||
return <div>
|
||||
{ requestBodyDescription &&
|
||||
<Markdown source={requestBodyDescription} />
|
||||
@@ -26,8 +29,16 @@ const RequestBody = ({ requestBody, getComponent, specSelectors, contentType })
|
||||
getComponent={ getComponent }
|
||||
specSelectors={ specSelectors }
|
||||
expandDepth={1}
|
||||
isExecute={isExecute}
|
||||
schema={mediaTypeValue.get("schema")}
|
||||
example={<HighlightCode value={sampleSchema} />}
|
||||
example={<RequestBodyEditor
|
||||
requestBody={requestBody}
|
||||
onChange={onChange}
|
||||
mediaType={contentType}
|
||||
getComponent={getComponent}
|
||||
isExecute={isExecute}
|
||||
specSelectors={specSelectors}
|
||||
/>}
|
||||
/>
|
||||
</div>
|
||||
}
|
||||
@@ -36,7 +47,9 @@ RequestBody.propTypes = {
|
||||
requestBody: ImPropTypes.orderedMap.isRequired,
|
||||
getComponent: PropTypes.func.isRequired,
|
||||
specSelectors: PropTypes.object.isRequired,
|
||||
contentType: PropTypes.string.isRequired
|
||||
contentType: PropTypes.string.isRequired,
|
||||
isExecute: PropTypes.bool.isRequired,
|
||||
onChange: PropTypes.func.isRequired
|
||||
}
|
||||
|
||||
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 * 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 wrapComponents from "./wrap-components"
|
||||
import * as oas3Actions from "./actions"
|
||||
import * as oas3Selectors from "./selectors"
|
||||
import oas3Reducers from "./reducers"
|
||||
|
||||
export default function() {
|
||||
return {
|
||||
@@ -10,7 +14,13 @@ export default function() {
|
||||
wrapComponents,
|
||||
statePlugins: {
|
||||
spec: {
|
||||
wrapSelectors
|
||||
wrapSelectors: specWrapSelectors,
|
||||
selectors: specSelectors
|
||||
},
|
||||
oas3: {
|
||||
actions: oas3Actions,
|
||||
reducers: oas3Reducers,
|
||||
selectors: oas3Selectors,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
28
src/core/plugins/oas3/reducers.js
Normal file
28
src/core/plugins/oas3/reducers.js
Normal file
@@ -0,0 +1,28 @@
|
||||
import {
|
||||
UPDATE_SELECTED_SERVER,
|
||||
UPDATE_REQUEST_BODY_VALUE,
|
||||
UPDATE_REQUEST_CONTENT_TYPE,
|
||||
UPDATE_SERVER_VARIABLE_VALUE,
|
||||
UPDATE_RESPONSE_CONTENT_TYPE
|
||||
} 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_RESPONSE_CONTENT_TYPE]: (state, { payload: { value, pathMethod } } ) =>{
|
||||
let [path, method] = pathMethod
|
||||
return state.setIn( [ "requestData", path, method, "responseContentType" ], value)
|
||||
},
|
||||
[UPDATE_SERVER_VARIABLE_VALUE]: (state, { payload: { server, key, val } } ) =>{
|
||||
return state.setIn( [ "serverVariableValues", server, key ], val)
|
||||
},
|
||||
}
|
||||
58
src/core/plugins/oas3/selectors.js
Normal file
58
src/core/plugins/oas3/selectors.js
Normal file
@@ -0,0 +1,58 @@
|
||||
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 responseContentType = onlyOAS3((state, path, method) => {
|
||||
return state.getIn(["requestData", path, method, "responseContentType"]) || 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 { Map } from "immutable"
|
||||
import { isOAS3 as isOAS3Helper, isSwagger2 as isSwagger2Helper } from "./helpers"
|
||||
import { isOAS3 as isOAS3Helper, isSwagger2 as isSwagger2Helper } from "../helpers"
|
||||
|
||||
|
||||
// Helpers
|
||||
@@ -56,6 +56,11 @@ export const schemes = OAS3NullSelector
|
||||
|
||||
// New selectors
|
||||
|
||||
export const servers = onlyOAS3(createSelector(
|
||||
spec,
|
||||
spec => spec.getIn(["servers"]) || Map()
|
||||
))
|
||||
|
||||
export const isOAS3 = (ori, system) => () => {
|
||||
const spec = system.getSystem().specSelectors.specJson()
|
||||
return isOAS3Helper(spec)
|
||||
@@ -3,7 +3,6 @@ import parameters from "./parameters"
|
||||
import VersionStamp from "./version-stamp"
|
||||
import OnlineValidatorBadge from "./online-validator-badge"
|
||||
import Model from "./model"
|
||||
import TryItOutButton from "./try-it-out-button"
|
||||
|
||||
export default {
|
||||
Markdown,
|
||||
@@ -11,5 +10,4 @@ export default {
|
||||
VersionStamp,
|
||||
model: Model,
|
||||
onlineValidatorBadge: OnlineValidatorBadge,
|
||||
TryItOutButton
|
||||
}
|
||||
|
||||
@@ -3,7 +3,6 @@ import PropTypes from "prop-types"
|
||||
import { OAS3ComponentWrapFactory } from "../helpers"
|
||||
import { Model } from "core/components/model"
|
||||
|
||||
|
||||
class ModelComponent extends Component {
|
||||
static propTypes = {
|
||||
schema: PropTypes.object.isRequired,
|
||||
|
||||
@@ -13,8 +13,7 @@ class Parameters extends Component {
|
||||
super(props)
|
||||
this.state = {
|
||||
callbackVisible: false,
|
||||
parametersVisible: true,
|
||||
requestBodyContentType: ""
|
||||
parametersVisible: true
|
||||
}
|
||||
}
|
||||
|
||||
@@ -24,6 +23,8 @@ class Parameters extends Component {
|
||||
operation: PropTypes.object.isRequired,
|
||||
getComponent: PropTypes.func.isRequired,
|
||||
specSelectors: PropTypes.object.isRequired,
|
||||
oas3Actions: PropTypes.object.isRequired,
|
||||
oas3Selectors: PropTypes.object.isRequired,
|
||||
fn: PropTypes.object.isRequired,
|
||||
tryItOutEnabled: PropTypes.bool,
|
||||
allowTryItOut: PropTypes.bool,
|
||||
@@ -86,6 +87,8 @@ class Parameters extends Component {
|
||||
fn,
|
||||
getComponent,
|
||||
specSelectors,
|
||||
oas3Actions,
|
||||
oas3Selectors,
|
||||
pathMethod,
|
||||
operation
|
||||
} = this.props
|
||||
@@ -159,16 +162,22 @@ class Parameters extends Component {
|
||||
<h4 className={`opblock-title parameter__name ${requestBody.get("required") && "required"}`}>Request body</h4>
|
||||
<label>
|
||||
<ContentType
|
||||
value={this.state.requestBodyContentType}
|
||||
value={oas3Selectors.requestContentType(...pathMethod)}
|
||||
contentTypes={ requestBody.get("content").keySeq() }
|
||||
onChange={(val) => this.setState({ requestBodyContentType: val })}
|
||||
onChange={(value) => {
|
||||
oas3Actions.setRequestContentType({ value, pathMethod })
|
||||
}}
|
||||
className="body-param-content-type" />
|
||||
</label>
|
||||
</div>
|
||||
<div className="opblock-description-wrapper">
|
||||
<RequestBody
|
||||
requestBody={requestBody}
|
||||
contentType={this.state.requestBodyContentType}/>
|
||||
isExecute={isExecute}
|
||||
onChange={(value) => {
|
||||
oas3Actions.setRequestBodyValue({ value, pathMethod })
|
||||
}}
|
||||
contentType={oas3Selectors.requestContentType(...pathMethod)}/>
|
||||
</div>
|
||||
</div>
|
||||
}
|
||||
|
||||
@@ -1,5 +0,0 @@
|
||||
import { OAS3ComponentWrapFactory } from "../helpers"
|
||||
|
||||
export default OAS3ComponentWrapFactory(() => {
|
||||
return null
|
||||
})
|
||||
@@ -27,7 +27,7 @@ const primitive = (schema) => {
|
||||
|
||||
export const sampleFromSchema = (schema, config={}) => {
|
||||
let { type, example, properties, additionalProperties, items } = objectify(schema)
|
||||
let { includeReadOnly } = config
|
||||
let { includeReadOnly, includeWriteOnly } = config
|
||||
|
||||
if(example !== undefined)
|
||||
return example
|
||||
@@ -46,16 +46,20 @@ export const sampleFromSchema = (schema, config={}) => {
|
||||
let props = objectify(properties)
|
||||
let obj = {}
|
||||
for (var name in props) {
|
||||
if ( !props[name].readOnly || includeReadOnly ) {
|
||||
obj[name] = sampleFromSchema(props[name], { includeReadOnly: includeReadOnly })
|
||||
if ( props[name].readOnly && !includeReadOnly ) {
|
||||
continue
|
||||
}
|
||||
if ( props[name].writeOnly && !includeWriteOnly ) {
|
||||
continue
|
||||
}
|
||||
obj[name] = sampleFromSchema(props[name], config)
|
||||
}
|
||||
|
||||
if ( additionalProperties === true ) {
|
||||
obj.additionalProp1 = {}
|
||||
} else if ( additionalProperties ) {
|
||||
let additionalProps = objectify(additionalProperties)
|
||||
let additionalPropVal = sampleFromSchema(additionalProps, { includeReadOnly: includeReadOnly })
|
||||
let additionalPropVal = sampleFromSchema(additionalProps, config)
|
||||
|
||||
for (let i = 1; i < 4; i++) {
|
||||
obj["additionalProp" + i] = additionalPropVal
|
||||
@@ -65,7 +69,7 @@ export const sampleFromSchema = (schema, config={}) => {
|
||||
}
|
||||
|
||||
if(type === "array") {
|
||||
return [ sampleFromSchema(items, { includeReadOnly: includeReadOnly }) ]
|
||||
return [ sampleFromSchema(items, config) ]
|
||||
}
|
||||
|
||||
if(schema["enum"]) {
|
||||
@@ -96,7 +100,7 @@ export const inferSchema = (thing) => {
|
||||
export const sampleXmlFromSchema = (schema, config={}) => {
|
||||
let objectifySchema = objectify(schema)
|
||||
let { type, properties, additionalProperties, items, example } = objectifySchema
|
||||
let { includeReadOnly } = config
|
||||
let { includeReadOnly, includeWriteOnly } = config
|
||||
let defaultValue = objectifySchema.default
|
||||
let res = {}
|
||||
let _attr = {}
|
||||
@@ -177,7 +181,13 @@ export const sampleXmlFromSchema = (schema, config={}) => {
|
||||
example = example || {}
|
||||
|
||||
for (let propName in props) {
|
||||
if ( !props[propName].readOnly || includeReadOnly ) {
|
||||
if ( props[propName].readOnly && !includeReadOnly ) {
|
||||
continue
|
||||
}
|
||||
if ( props[propName].writeOnly && !includeWriteOnly ) {
|
||||
continue
|
||||
}
|
||||
|
||||
props[propName].xml = props[propName].xml || {}
|
||||
|
||||
if (props[propName].xml.attribute) {
|
||||
@@ -199,7 +209,6 @@ export const sampleXmlFromSchema = (schema, config={}) => {
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (additionalProperties === true) {
|
||||
res[displayName].push({additionalProp: "Anything can be here"})
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
import YAML from "js-yaml"
|
||||
import parseUrl from "url-parse"
|
||||
import serializeError from "serialize-error"
|
||||
import { isJSONObject } from "core/utils"
|
||||
|
||||
// Actions conform to FSA (flux-standard-actions)
|
||||
// {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 SET_RESPONSE = "spec_set_response"
|
||||
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 CLEAR_RESPONSE = "spec_clear_response"
|
||||
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
|
||||
export const logRequest = (req) => {
|
||||
return {
|
||||
@@ -187,8 +196,10 @@ export const logRequest = (req) => {
|
||||
|
||||
// Actually fire the request via fn.execute
|
||||
// (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 { requestInterceptor, responseInterceptor } = getConfigs()
|
||||
|
||||
let op = operation.toJS()
|
||||
|
||||
@@ -201,11 +212,36 @@ export const executeRequest = (req) => ({fn, specActions, specSelectors}) => {
|
||||
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)
|
||||
req.responseContentType = oas3Selectors.responseContentType(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)
|
||||
parsedRequest = fn.buildRequest(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
|
||||
const startTime = Date.now()
|
||||
|
||||
@@ -214,8 +250,12 @@ export const executeRequest = (req) => ({fn, specActions, specSelectors}) => {
|
||||
res.duration = Date.now() - startTime
|
||||
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
|
||||
|
||||
@@ -10,6 +10,7 @@ import {
|
||||
VALIDATE_PARAMS,
|
||||
SET_RESPONSE,
|
||||
SET_REQUEST,
|
||||
SET_MUTATED_REQUEST,
|
||||
UPDATE_RESOLVED,
|
||||
UPDATE_OPERATION_VALUE,
|
||||
CLEAR_RESPONSE,
|
||||
@@ -102,6 +103,10 @@ export default {
|
||||
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 } }) => {
|
||||
let operationPath = ["resolved", "paths", ...path]
|
||||
if(!state.getIn(operationPath)) {
|
||||
|
||||
@@ -237,6 +237,11 @@ export const requests = createSelector(
|
||||
state => state.get( "requests", Map() )
|
||||
)
|
||||
|
||||
export const mutatedRequests = createSelector(
|
||||
state,
|
||||
state => state.get( "mutatedRequests", Map() )
|
||||
)
|
||||
|
||||
export const responseFor = (state, path, method) => {
|
||||
return responses(state).getIn([path, method], null)
|
||||
}
|
||||
@@ -245,6 +250,10 @@ export const requestFor = (state, path, method) => {
|
||||
return requests(state).getIn([path, method], null)
|
||||
}
|
||||
|
||||
export const mutatedRequestFor = (state, path, method) => {
|
||||
return mutatedRequests(state).getIn([path, method], null)
|
||||
}
|
||||
|
||||
export const allowTryItOutFor = () => {
|
||||
// This is just a hook for now.
|
||||
return true
|
||||
|
||||
@@ -8,11 +8,31 @@ import some from "lodash/some"
|
||||
import eq from "lodash/eq"
|
||||
import { memoizedSampleFromSchema, memoizedCreateXMLExample } from "core/plugins/samples/fn"
|
||||
import win from "./window"
|
||||
import cssEscape from "css.escape"
|
||||
|
||||
const DEFAULT_REPONSE_KEY = "default"
|
||||
|
||||
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) {
|
||||
if(!isObject(thing))
|
||||
return {}
|
||||
@@ -631,3 +651,29 @@ export const shallowEqualKeys = (a,b, keys) => {
|
||||
return eq(a[key], b[key])
|
||||
})
|
||||
}
|
||||
|
||||
export function getAcceptControllingResponse(responses) {
|
||||
if(!Im.OrderedMap.isOrderedMap(responses)) {
|
||||
// wrong type!
|
||||
return null
|
||||
}
|
||||
|
||||
if(!responses.size) {
|
||||
// responses is empty
|
||||
return null
|
||||
}
|
||||
|
||||
const suitable2xxResponse = responses.find((res, k) => {
|
||||
return k.startsWith("2") && Object.keys(res.get("content") || {}).length > 0
|
||||
})
|
||||
|
||||
// try to find a suitable `default` responses
|
||||
const defaultResponse = responses.get("default") || Im.OrderedMap()
|
||||
const defaultResponseMediaTypes = (defaultResponse.get("content") || Im.OrderedMap()).keySeq().toJS()
|
||||
const suitableDefaultResponse = defaultResponseMediaTypes.length ? defaultResponse : null
|
||||
|
||||
return suitable2xxResponse || suitableDefaultResponse
|
||||
}
|
||||
|
||||
export const createDeepLinkPath = (str) => typeof str == "string" || str instanceof String ? str.trim().replace(/\s/g, "_") : ""
|
||||
export const escapeDeepLinkPath = (str) => cssEscape( createDeepLinkPath(str) )
|
||||
|
||||
@@ -1,2 +1,5 @@
|
||||
// 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")
|
||||
}
|
||||
|
||||
@@ -1,21 +1,3 @@
|
||||
html
|
||||
{
|
||||
box-sizing: border-box;
|
||||
}
|
||||
*,
|
||||
*:before,
|
||||
*:after
|
||||
{
|
||||
box-sizing: inherit;
|
||||
}
|
||||
|
||||
body
|
||||
{
|
||||
margin: 0;
|
||||
|
||||
background: #fafafa;
|
||||
}
|
||||
|
||||
.wrapper
|
||||
{
|
||||
width: 100%;
|
||||
@@ -540,6 +522,22 @@ body
|
||||
}
|
||||
}
|
||||
|
||||
.response-col_links
|
||||
{
|
||||
padding-left: 2em;
|
||||
max-width: 40em;
|
||||
font-size: 14px;
|
||||
|
||||
@include text_body();
|
||||
|
||||
.response-undocumented
|
||||
{
|
||||
font-size: 11px;
|
||||
|
||||
@include text_code(#999);
|
||||
}
|
||||
}
|
||||
|
||||
.response-col_description__inner
|
||||
{
|
||||
span
|
||||
@@ -638,6 +636,77 @@ body
|
||||
}
|
||||
}
|
||||
|
||||
.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
|
||||
{
|
||||
@@ -699,7 +768,6 @@ body
|
||||
.renderedMarkdown {
|
||||
p {
|
||||
@include text_body();
|
||||
font-size: 14px;
|
||||
margin-top: 0px;
|
||||
margin-bottom: 0px;
|
||||
}
|
||||
@@ -707,6 +775,17 @@ body
|
||||
|
||||
.response-content-type {
|
||||
padding-top: 1em;
|
||||
|
||||
&.controls-accept-header {
|
||||
select {
|
||||
border-color: green;
|
||||
}
|
||||
|
||||
small {
|
||||
color: green;
|
||||
font-size: .7em;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@keyframes blinker
|
||||
@@ -729,12 +808,12 @@ section
|
||||
a.nostyle {
|
||||
text-decoration: inherit;
|
||||
color: inherit;
|
||||
cursor: auto;
|
||||
cursor: pointer;
|
||||
display: inline;
|
||||
|
||||
&:visited {
|
||||
text-decoration: inherit;
|
||||
color: inherit;
|
||||
cursor: auto;
|
||||
cursor: pointer;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -227,8 +227,6 @@ span
|
||||
{
|
||||
> span.model
|
||||
{
|
||||
padding: 0 0 0 10px;
|
||||
|
||||
.brace-close
|
||||
{
|
||||
padding: 0 0 0 10px;
|
||||
@@ -236,6 +234,12 @@ span
|
||||
}
|
||||
}
|
||||
|
||||
.prop-name
|
||||
{
|
||||
display: inline-block;
|
||||
width: 100px;
|
||||
}
|
||||
|
||||
.prop-type
|
||||
{
|
||||
color: #55a;
|
||||
|
||||
@@ -19,8 +19,8 @@ table
|
||||
|
||||
&:first-of-type
|
||||
{
|
||||
width: 100px;
|
||||
padding: 0;
|
||||
width: 124px;
|
||||
padding: 0 0 0 2em;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -52,7 +52,8 @@ table
|
||||
|
||||
&:first-of-type
|
||||
{
|
||||
width: 20%;
|
||||
max-width: 20%;
|
||||
min-width: 6em;
|
||||
padding: 10px 0;
|
||||
}
|
||||
}
|
||||
@@ -138,6 +139,14 @@ table
|
||||
@include text_code(#888);
|
||||
}
|
||||
|
||||
.parameter__deprecated
|
||||
{
|
||||
font-size: 12px;
|
||||
font-style: italic;
|
||||
|
||||
@include text_code(#f00);
|
||||
}
|
||||
|
||||
|
||||
.table-container
|
||||
{
|
||||
|
||||
@@ -43,6 +43,7 @@
|
||||
margin: 0;
|
||||
|
||||
border: 2px solid #547f00;
|
||||
border-radius: 4px 0 0 4px;
|
||||
outline: none;
|
||||
}
|
||||
|
||||
|
||||
@@ -14,5 +14,6 @@
|
||||
@import 'information';
|
||||
@import 'authorize';
|
||||
@import 'errors';
|
||||
@include text_body();
|
||||
@import 'split-pane-mode';
|
||||
}
|
||||
|
||||
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])
|
||||
|
||||
})
|
||||
})
|
||||
})
|
||||
58
test/components/response.js
Normal file
58
test/components/response.js
Normal file
@@ -0,0 +1,58 @@
|
||||
import React from "react"
|
||||
import expect from "expect"
|
||||
import { shallow } from "enzyme"
|
||||
import { fromJS } from "immutable"
|
||||
import Response from "components/response"
|
||||
import ModelExample from "components/model-example"
|
||||
import { inferSchema } from "corePlugins/samples/fn"
|
||||
|
||||
describe("<Response />", function() {
|
||||
const dummyComponent = () => null
|
||||
const components = {
|
||||
headers: dummyComponent,
|
||||
highlightCode: dummyComponent,
|
||||
modelExample: ModelExample,
|
||||
Markdown: dummyComponent,
|
||||
operationLink: dummyComponent,
|
||||
contentType: dummyComponent
|
||||
}
|
||||
const props = {
|
||||
getComponent: c => components[c],
|
||||
specSelectors: {
|
||||
isOAS3() {
|
||||
return false
|
||||
}
|
||||
},
|
||||
fn: {
|
||||
inferSchema
|
||||
},
|
||||
contentType: "application/json",
|
||||
className: "for-test",
|
||||
response: fromJS({
|
||||
type: "object",
|
||||
properties: {
|
||||
// Note reverse order: c, b, a
|
||||
"c": {
|
||||
type: "integer"
|
||||
},
|
||||
"b": {
|
||||
type: "boolean"
|
||||
},
|
||||
"a": {
|
||||
type: "string"
|
||||
}
|
||||
}
|
||||
}),
|
||||
code: "200"
|
||||
}
|
||||
|
||||
it("renders the model-example schema properties in order", function() {
|
||||
const wrapper = shallow(<Response {...props}/>)
|
||||
const renderedModelExample = wrapper.find(ModelExample)
|
||||
expect(renderedModelExample.length).toEqual(1)
|
||||
|
||||
// Assert the schema's properties have maintained their order
|
||||
const modelExampleSchemaProperties = renderedModelExample.props().schema.toJS().properties
|
||||
expect( Object.keys(modelExampleSchemaProperties) ).toEqual(["c", "b", "a"])
|
||||
})
|
||||
})
|
||||
@@ -7,18 +7,20 @@ import { fromJS } from "immutable"
|
||||
import Schemes from "components/schemes"
|
||||
|
||||
describe("<Schemes/>", function(){
|
||||
it("calls props.specActions.setScheme() when no operationScheme is selected", function(){
|
||||
it("calls props.specActions.setScheme() when no currentScheme is selected", function(){
|
||||
|
||||
let setSchemeSpy = createSpy()
|
||||
|
||||
// Given
|
||||
let props = {
|
||||
specActions: {
|
||||
setScheme: createSpy()
|
||||
setScheme: setSchemeSpy
|
||||
},
|
||||
schemes: fromJS([
|
||||
"http",
|
||||
"https"
|
||||
]),
|
||||
operationScheme: undefined,
|
||||
currentScheme: undefined,
|
||||
path: "/test",
|
||||
method: "get"
|
||||
}
|
||||
@@ -26,16 +28,45 @@ describe("<Schemes/>", function(){
|
||||
// When
|
||||
let wrapper = shallow(<Schemes {...props}/>)
|
||||
|
||||
// Then operationScheme should default to first scheme in options list
|
||||
// Then currentScheme should default to first scheme in options list
|
||||
expect(props.specActions.setScheme).toHaveBeenCalledWith("http", "/test" , "get")
|
||||
|
||||
// When the operationScheme is no longer in the list of options
|
||||
// When the currentScheme is no longer in the list of options
|
||||
props.schemes = fromJS([
|
||||
"https"
|
||||
])
|
||||
wrapper.setProps(props)
|
||||
|
||||
// Then operationScheme should default to first scheme in options list
|
||||
// Then currentScheme should default to first scheme in options list, again
|
||||
expect(props.specActions.setScheme).toHaveBeenCalledWith("https", "/test", "get")
|
||||
})
|
||||
|
||||
it("doesn't call props.specActions.setScheme() when schemes hasn't changed", function(){
|
||||
|
||||
let setSchemeSpy = createSpy()
|
||||
|
||||
// Given
|
||||
let props = {
|
||||
specActions: {
|
||||
setScheme: setSchemeSpy
|
||||
},
|
||||
schemes: fromJS([
|
||||
"http",
|
||||
"https"
|
||||
]),
|
||||
currentScheme: "https"
|
||||
}
|
||||
|
||||
// When
|
||||
let wrapper = shallow(<Schemes {...props}/>)
|
||||
|
||||
// Should be called initially, to set the global state
|
||||
expect(setSchemeSpy.calls.length).toEqual(1)
|
||||
|
||||
// After an update
|
||||
wrapper.instance().componentWillReceiveProps(props)
|
||||
|
||||
// Should not be called again, since `currentScheme` is in schemes
|
||||
expect(setSchemeSpy.calls.length).toEqual(1)
|
||||
})
|
||||
})
|
||||
|
||||
@@ -132,10 +132,10 @@ describe("curlify", function() {
|
||||
url: "http://example.com",
|
||||
method: "POST",
|
||||
headers: { "content-type": "multipart/form-data" },
|
||||
body: [
|
||||
["id", "123"],
|
||||
["name", "Sahar"]
|
||||
]
|
||||
body: {
|
||||
id: "123",
|
||||
name: "Sahar"
|
||||
}
|
||||
}
|
||||
|
||||
let curlified = curl(Im.fromJS(req))
|
||||
@@ -152,10 +152,10 @@ describe("curlify", function() {
|
||||
url: "http://example.com",
|
||||
method: "POST",
|
||||
headers: { "content-type": "multipart/form-data" },
|
||||
body: [
|
||||
["id", "123"],
|
||||
["file", file]
|
||||
]
|
||||
body: {
|
||||
id: "123",
|
||||
file
|
||||
}
|
||||
}
|
||||
|
||||
let curlified = curl(Im.fromJS(req))
|
||||
|
||||
@@ -1,6 +1,105 @@
|
||||
import { createXMLExample } from "corePlugins/samples/fn"
|
||||
import { createXMLExample, sampleFromSchema } from "corePlugins/samples/fn"
|
||||
import expect from "expect"
|
||||
|
||||
describe("sampleFromSchema", function() {
|
||||
it("returns object with no readonly fields for parameter", function () {
|
||||
var definition = {
|
||||
type: "object",
|
||||
properties: {
|
||||
id: {
|
||||
type: "integer"
|
||||
},
|
||||
readOnlyDog: {
|
||||
readOnly: true,
|
||||
type: "string"
|
||||
}
|
||||
},
|
||||
xml: {
|
||||
name: "animals"
|
||||
}
|
||||
}
|
||||
|
||||
var expected = {
|
||||
id: 0
|
||||
}
|
||||
|
||||
expect(sampleFromSchema(definition, { includeReadOnly: false })).toEqual(expected)
|
||||
})
|
||||
|
||||
it("returns object with readonly fields for parameter, with includeReadOnly", function () {
|
||||
var definition = {
|
||||
type: "object",
|
||||
properties: {
|
||||
id: {
|
||||
type: "integer"
|
||||
},
|
||||
readOnlyDog: {
|
||||
readOnly: true,
|
||||
type: "string"
|
||||
}
|
||||
},
|
||||
xml: {
|
||||
name: "animals"
|
||||
}
|
||||
}
|
||||
|
||||
var expected = {
|
||||
id: 0,
|
||||
readOnlyDog: "string"
|
||||
}
|
||||
|
||||
expect(sampleFromSchema(definition, { includeReadOnly: true })).toEqual(expected)
|
||||
})
|
||||
|
||||
it("returns object without writeonly fields for parameter", function () {
|
||||
var definition = {
|
||||
type: "object",
|
||||
properties: {
|
||||
id: {
|
||||
type: "integer"
|
||||
},
|
||||
writeOnlyDog: {
|
||||
writeOnly: true,
|
||||
type: "string"
|
||||
}
|
||||
},
|
||||
xml: {
|
||||
name: "animals"
|
||||
}
|
||||
}
|
||||
|
||||
var expected = {
|
||||
id: 0
|
||||
}
|
||||
|
||||
expect(sampleFromSchema(definition)).toEqual(expected)
|
||||
})
|
||||
|
||||
it("returns object with writeonly fields for parameter, with includeWriteOnly", function () {
|
||||
var definition = {
|
||||
type: "object",
|
||||
properties: {
|
||||
id: {
|
||||
type: "integer"
|
||||
},
|
||||
writeOnlyDog: {
|
||||
writeOnly: true,
|
||||
type: "string"
|
||||
}
|
||||
},
|
||||
xml: {
|
||||
name: "animals"
|
||||
}
|
||||
}
|
||||
|
||||
var expected = {
|
||||
id: 0,
|
||||
writeOnlyDog: "string"
|
||||
}
|
||||
|
||||
expect(sampleFromSchema(definition, { includeWriteOnly: true })).toEqual(expected)
|
||||
})
|
||||
})
|
||||
|
||||
describe("createXMLExample", function () {
|
||||
var sut = createXMLExample
|
||||
@@ -554,6 +653,69 @@ describe("createXMLExample", function () {
|
||||
expect(sut(definition, { includeReadOnly: false })).toEqual(expected)
|
||||
})
|
||||
|
||||
it("returns object with readonly fields for parameter, with includeReadOnly", function () {
|
||||
var expected = "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<animals>\n\t<id>0</id>\n\t<dog>string</dog>\n</animals>"
|
||||
var definition = {
|
||||
type: "object",
|
||||
properties: {
|
||||
id: {
|
||||
type: "integer"
|
||||
},
|
||||
dog: {
|
||||
readOnly: true,
|
||||
type: "string"
|
||||
}
|
||||
},
|
||||
xml: {
|
||||
name: "animals"
|
||||
}
|
||||
}
|
||||
|
||||
expect(sut(definition, { includeReadOnly: true })).toEqual(expected)
|
||||
})
|
||||
|
||||
it("returns object without writeonly fields for parameter", function () {
|
||||
var expected = "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<animals>\n\t<id>0</id>\n</animals>"
|
||||
var definition = {
|
||||
type: "object",
|
||||
properties: {
|
||||
id: {
|
||||
type: "integer"
|
||||
},
|
||||
dog: {
|
||||
writeOnly: true,
|
||||
type: "string"
|
||||
}
|
||||
},
|
||||
xml: {
|
||||
name: "animals"
|
||||
}
|
||||
}
|
||||
|
||||
expect(sut(definition)).toEqual(expected)
|
||||
})
|
||||
|
||||
it("returns object with writeonly fields for parameter, with includeWriteOnly", function () {
|
||||
var expected = "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<animals>\n\t<id>0</id>\n\t<dog>string</dog>\n</animals>"
|
||||
var definition = {
|
||||
type: "object",
|
||||
properties: {
|
||||
id: {
|
||||
type: "integer"
|
||||
},
|
||||
dog: {
|
||||
writeOnly: true,
|
||||
type: "string"
|
||||
}
|
||||
},
|
||||
xml: {
|
||||
name: "animals"
|
||||
}
|
||||
}
|
||||
|
||||
expect(sut(definition, { includeWriteOnly: true })).toEqual(expected)
|
||||
})
|
||||
|
||||
it("returns object with passed property as attribute", function () {
|
||||
var expected = "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<animals id=\"0\">\n\t<dog>string</dog>\n</animals>"
|
||||
var definition = {
|
||||
|
||||
@@ -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(){
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
/* eslint-env mocha */
|
||||
import expect from "expect"
|
||||
import { fromJS } from "immutable"
|
||||
import { mapToList, validateNumber, validateInteger, validateParam, validateFile, fromJSOrdered } from "core/utils"
|
||||
import { fromJS, OrderedMap } from "immutable"
|
||||
import { mapToList, validateNumber, validateInteger, validateParam, validateFile, fromJSOrdered, getAcceptControllingResponse, createDeepLinkPath, escapeDeepLinkPath } from "core/utils"
|
||||
import win from "core/window"
|
||||
|
||||
describe("utils", function() {
|
||||
@@ -582,4 +582,151 @@ describe("utils", function() {
|
||||
expect( result ).toEqual( [1, 1, 2, 3, 5, 8] )
|
||||
})
|
||||
})
|
||||
|
||||
describe.only("getAcceptControllingResponse", () => {
|
||||
it("should return the first 2xx response with a media type", () => {
|
||||
const responses = fromJSOrdered({
|
||||
"200": {
|
||||
content: {
|
||||
"application/json": {
|
||||
schema: {
|
||||
type: "object"
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"201": {
|
||||
content: {
|
||||
"application/json": {
|
||||
schema: {
|
||||
type: "object"
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
})
|
||||
|
||||
expect(getAcceptControllingResponse(responses)).toEqual(responses.get("200"))
|
||||
})
|
||||
it("should skip 2xx responses without defined media types", () => {
|
||||
const responses = fromJSOrdered({
|
||||
"200": {
|
||||
content: {
|
||||
"application/json": {
|
||||
schema: {
|
||||
type: "object"
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"201": {
|
||||
content: {
|
||||
"application/json": {
|
||||
schema: {
|
||||
type: "object"
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
})
|
||||
|
||||
expect(getAcceptControllingResponse(responses)).toEqual(responses.get("201"))
|
||||
})
|
||||
it("should default to the `default` response if it has defined media types", () => {
|
||||
const responses = fromJSOrdered({
|
||||
"200": {
|
||||
description: "quite empty"
|
||||
},
|
||||
"201": {
|
||||
description: "quite empty"
|
||||
},
|
||||
default: {
|
||||
content: {
|
||||
"application/json": {
|
||||
schema: {
|
||||
type: "object"
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
})
|
||||
|
||||
expect(getAcceptControllingResponse(responses)).toEqual(responses.get("default"))
|
||||
})
|
||||
it("should return null if there are no suitable controlling responses", () => {
|
||||
const responses = fromJSOrdered({
|
||||
"200": {
|
||||
description: "quite empty"
|
||||
},
|
||||
"201": {
|
||||
description: "quite empty"
|
||||
},
|
||||
"default": {
|
||||
description: "also empty.."
|
||||
}
|
||||
})
|
||||
|
||||
expect(getAcceptControllingResponse(responses)).toBe(null)
|
||||
})
|
||||
it("should return null if an empty OrderedMap is passed", () => {
|
||||
const responses = fromJSOrdered()
|
||||
|
||||
expect(getAcceptControllingResponse(responses)).toBe(null)
|
||||
})
|
||||
it("should return null if anything except an OrderedMap is passed", () => {
|
||||
const responses = {}
|
||||
|
||||
expect(getAcceptControllingResponse(responses)).toBe(null)
|
||||
})
|
||||
})
|
||||
|
||||
describe("createDeepLinkPath", function() {
|
||||
it("creates a deep link path replacing spaces with underscores", function() {
|
||||
const result = createDeepLinkPath("tag id with spaces")
|
||||
expect(result).toEqual("tag_id_with_spaces")
|
||||
})
|
||||
|
||||
it("trims input when creating a deep link path", function() {
|
||||
let result = createDeepLinkPath(" spaces before and after ")
|
||||
expect(result).toEqual("spaces_before_and_after")
|
||||
|
||||
result = createDeepLinkPath(" ")
|
||||
expect(result).toEqual("")
|
||||
})
|
||||
|
||||
it("creates a deep link path with special characters", function() {
|
||||
const result = createDeepLinkPath("!@#$%^&*(){}[]")
|
||||
expect(result).toEqual("!@#$%^&*(){}[]")
|
||||
})
|
||||
|
||||
it("returns an empty string for invalid input", function() {
|
||||
expect( createDeepLinkPath(null) ).toEqual("")
|
||||
expect( createDeepLinkPath(undefined) ).toEqual("")
|
||||
expect( createDeepLinkPath(1) ).toEqual("")
|
||||
expect( createDeepLinkPath([]) ).toEqual("")
|
||||
expect( createDeepLinkPath({}) ).toEqual("")
|
||||
})
|
||||
})
|
||||
|
||||
describe("escapeDeepLinkPath", function() {
|
||||
it("creates and escapes a deep link path", function() {
|
||||
const result = escapeDeepLinkPath("tag id with spaces?")
|
||||
expect(result).toEqual("tag_id_with_spaces\\?")
|
||||
})
|
||||
|
||||
it("escapes a deep link path that starts with a number", function() {
|
||||
const result = escapeDeepLinkPath("123")
|
||||
expect(result).toEqual("\\31 23")
|
||||
})
|
||||
|
||||
it("escapes a deep link path with a class selector", function() {
|
||||
const result = escapeDeepLinkPath("hello.world")
|
||||
expect(result).toEqual("hello\\.world")
|
||||
})
|
||||
|
||||
it("escapes a deep link path with an id selector", function() {
|
||||
const result = escapeDeepLinkPath("hello#world")
|
||||
expect(result).toEqual("hello\\#world")
|
||||
})
|
||||
})
|
||||
})
|
||||
|
||||
130
test/e2e/db.json
Normal file
130
test/e2e/db.json
Normal file
@@ -0,0 +1,130 @@
|
||||
{
|
||||
"pet": [
|
||||
{
|
||||
"id": 1,
|
||||
"category": {
|
||||
"id": 0,
|
||||
"name": "string"
|
||||
},
|
||||
"name": "doggie",
|
||||
"photoUrls": [
|
||||
"string"
|
||||
],
|
||||
"tags": [
|
||||
{
|
||||
"id": 0,
|
||||
"name": "string"
|
||||
}
|
||||
],
|
||||
"status": "available"
|
||||
},
|
||||
{
|
||||
"id": 2,
|
||||
"category": {
|
||||
"id": 0,
|
||||
"name": "string"
|
||||
},
|
||||
"name": "doggie",
|
||||
"photoUrls": [
|
||||
"string"
|
||||
],
|
||||
"tags": [
|
||||
{
|
||||
"id": 0,
|
||||
"name": "string"
|
||||
}
|
||||
],
|
||||
"status": "available"
|
||||
},
|
||||
{
|
||||
"id": 3,
|
||||
"category": {
|
||||
"id": 0,
|
||||
"name": "string"
|
||||
},
|
||||
"name": "doggie",
|
||||
"photoUrls": [
|
||||
"string"
|
||||
],
|
||||
"tags": [
|
||||
{
|
||||
"id": 0,
|
||||
"name": "string"
|
||||
}
|
||||
],
|
||||
"status": "available"
|
||||
},
|
||||
{
|
||||
"id": 4,
|
||||
"category": {
|
||||
"id": 0,
|
||||
"name": "string"
|
||||
},
|
||||
"name": "doggie",
|
||||
"photoUrls": [
|
||||
"string"
|
||||
],
|
||||
"tags": [
|
||||
{
|
||||
"id": 0,
|
||||
"name": "string"
|
||||
}
|
||||
],
|
||||
"status": "available"
|
||||
},
|
||||
{
|
||||
"id": 5,
|
||||
"category": {
|
||||
"id": 0,
|
||||
"name": "string"
|
||||
},
|
||||
"name": "doggie",
|
||||
"photoUrls": [
|
||||
"string"
|
||||
],
|
||||
"tags": [
|
||||
{
|
||||
"id": 0,
|
||||
"name": "string"
|
||||
}
|
||||
],
|
||||
"status": "available"
|
||||
},
|
||||
{
|
||||
"id": 6,
|
||||
"category": {
|
||||
"id": 0,
|
||||
"name": "string"
|
||||
},
|
||||
"name": "doggie",
|
||||
"photoUrls": [
|
||||
"string"
|
||||
],
|
||||
"tags": [
|
||||
{
|
||||
"id": 0,
|
||||
"name": "string"
|
||||
}
|
||||
],
|
||||
"status": "available"
|
||||
},
|
||||
{
|
||||
"id": 7,
|
||||
"category": {
|
||||
"id": 0,
|
||||
"name": "string"
|
||||
},
|
||||
"name": "doggie",
|
||||
"photoUrls": [
|
||||
"string"
|
||||
],
|
||||
"tags": [
|
||||
{
|
||||
"id": 0,
|
||||
"name": "string"
|
||||
}
|
||||
],
|
||||
"status": "available"
|
||||
}
|
||||
]
|
||||
}
|
||||
63
test/e2e/nightwatch.json
Normal file
63
test/e2e/nightwatch.json
Normal file
@@ -0,0 +1,63 @@
|
||||
{
|
||||
"src_folders" : ["test/e2e/scenarios"],
|
||||
"output_folder" : "reports",
|
||||
"live_output": true,
|
||||
"custom_commands_path" : "",
|
||||
"custom_assertions_path" : "",
|
||||
"page_objects_path" : "test/e2e/pages",
|
||||
"globals_path" : "",
|
||||
"test_workers" : {
|
||||
"enabled" : true,
|
||||
"workers" : "auto"
|
||||
},
|
||||
|
||||
"test_runner" : {
|
||||
"type" : "mocha",
|
||||
"options" : {
|
||||
"ui" : "bdd",
|
||||
"reporter" : "list"
|
||||
}
|
||||
},
|
||||
|
||||
"selenium" : {
|
||||
"start_process" : true,
|
||||
"server_path" : "node_modules/selenium-server-standalone-jar/jar/selenium-server-standalone-3.4.0.jar",
|
||||
"log_path" : "",
|
||||
"host" : "127.0.0.1",
|
||||
"port" : 4444,
|
||||
"cli_args" : {
|
||||
"webdriver.chrome.driver" : "node_modules/chromedriver/bin/chromedriver",
|
||||
"webdriver.firefox.profile" : "",
|
||||
"webdriver.ie.driver" : ""
|
||||
}
|
||||
},
|
||||
|
||||
"test_settings" : {
|
||||
"default" : {
|
||||
"launch_url" : "http://localhost",
|
||||
"selenium_port" : 4444,
|
||||
"selenium_host" : "localhost",
|
||||
"silent": true,
|
||||
"screenshots" : {
|
||||
"enabled" : false,
|
||||
"path" : ""
|
||||
},
|
||||
"desiredCapabilities": {
|
||||
"browserName": "chrome",
|
||||
"marionette": true
|
||||
}
|
||||
},
|
||||
|
||||
"chrome" : {
|
||||
"desiredCapabilities": {
|
||||
"browserName": "chrome"
|
||||
}
|
||||
},
|
||||
|
||||
"edge" : {
|
||||
"desiredCapabilities": {
|
||||
"browserName": "MicrosoftEdge"
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
505
test/e2e/pages/main.js
Normal file
505
test/e2e/pages/main.js
Normal file
@@ -0,0 +1,505 @@
|
||||
module.exports = {
|
||||
sections: {
|
||||
topbar: {
|
||||
selector: ".topbar",
|
||||
elements: {
|
||||
inputBox: {
|
||||
selector: "input"
|
||||
},
|
||||
btnExplore: {
|
||||
selector: "button"
|
||||
}
|
||||
}
|
||||
},
|
||||
informationContainer: {
|
||||
selector: ".information-container.wrapper",
|
||||
elements: {
|
||||
title: {
|
||||
selector: ".title"
|
||||
},
|
||||
version: {
|
||||
selector: ".version"
|
||||
},
|
||||
baseUrl: {
|
||||
selector: ".base-url"
|
||||
},
|
||||
mainUrl: {
|
||||
selector: ".main a"
|
||||
},
|
||||
mainUrlContent: {
|
||||
selector: ".main a span"
|
||||
},
|
||||
description: {
|
||||
selector: ".description p"
|
||||
},
|
||||
swaggerUrl: {
|
||||
selector: ".description p a:nth-of-type(1)"
|
||||
},
|
||||
swaggerircUrl: {
|
||||
selector: ".description p a:nth-of-type(2)"
|
||||
},
|
||||
termsLink: {
|
||||
selector: ".info > div:nth-child(3) a"
|
||||
},
|
||||
contactDevLink: {
|
||||
selector: ".info > div:nth-child(4) a"
|
||||
},
|
||||
apacheLink: {
|
||||
selector: ".info > div:nth-child(5) a"
|
||||
},
|
||||
aboutSwaggerLink: {
|
||||
selector: ".info > a"
|
||||
}
|
||||
}
|
||||
},
|
||||
schemeContainer: {
|
||||
selector: ".scheme-container",
|
||||
elements: {
|
||||
httpOption: {
|
||||
selector: "select option"
|
||||
},
|
||||
btnAuthorize: {
|
||||
selector: "button.authorize"
|
||||
},
|
||||
authorizationModal: {
|
||||
selector: ".dialog-ux"
|
||||
},
|
||||
appName: {
|
||||
selector: ".auth-container h5"
|
||||
},
|
||||
authorizationUrl: {
|
||||
selector: ".auth-container code"
|
||||
},
|
||||
flow: {
|
||||
selector: ".flow code"
|
||||
},
|
||||
inputClientID: {
|
||||
selector: "#client_id"
|
||||
},
|
||||
checkWritePetStoreAuth: {
|
||||
selector: "#write:pets-checkbox-petstore_auth"
|
||||
},
|
||||
checkReadPetStoreAuth: {
|
||||
selector: "#read:pets-checkbox-petstore_auth"
|
||||
}
|
||||
}
|
||||
},
|
||||
apiWrapper: {
|
||||
selector: ".swagger-ui .wrapper:nth-child(3)",
|
||||
elements: {
|
||||
petAPIWrapper: {
|
||||
selector: ".swagger-ui .opblock-tag-section:nth-child(1)"
|
||||
},
|
||||
petAPIWrapperBar: {
|
||||
selector: ".swagger-ui .opblock-tag-section:nth-child(1) .opblock-tag"
|
||||
},
|
||||
/**
|
||||
* Post pet/ api
|
||||
*/
|
||||
petOperationPostContainer: {
|
||||
selector: ".swagger-ui .opblock-tag-section:nth-child(1) div#operations-pet-addPet"
|
||||
},
|
||||
petOperationPostTitle: {
|
||||
selector: ".swagger-ui .opblock-tag-section:nth-child(1) div#operations-pet-addPet .opblock-summary-post span.opblock-summary-path span"
|
||||
},
|
||||
petOperationPostCollpase: {
|
||||
selector: ".swagger-ui .opblock-tag-section:nth-child(1) div#operations-pet-addPet .opblock-summary-post"
|
||||
},
|
||||
petOperationPostCollapseContainer: {
|
||||
selector: ".swagger-ui .opblock-tag-section:nth-child(1) div#operations-pet-addPet>div:nth-child(2)"
|
||||
},
|
||||
petOperationPostTryBtn: {
|
||||
selector: ".swagger-ui .opblock-tag-section:nth-child(1) div#operations-pet-addPet button.try-out__btn"
|
||||
},
|
||||
petOperationPostTryText: {
|
||||
selector: ".swagger-ui .opblock-tag-section:nth-child(1) div#operations-pet-addPet textarea.body-param__text"
|
||||
},
|
||||
petOperationPostExecuteBtn: {
|
||||
selector: ".swagger-ui .opblock-tag-section:nth-child(1) div#operations-pet-addPet button.execute"
|
||||
},
|
||||
petOperationPostTryTextArea: {
|
||||
selector: ".swagger-ui .opblock-tag-section:nth-child(1) div#operations-pet-addPet textarea"
|
||||
},
|
||||
petOperationPostResultsBox: {
|
||||
selector: ".swagger-ui .opblock-tag-section:nth-child(1) div#operations-pet-addPet pre.microlight"
|
||||
},
|
||||
petOperationPostMockCategoryID: {
|
||||
selector: ".swagger-ui .opblock-tag-section:nth-child(1) div#operations-pet-addPet pre.microlight span:nth-child(17)"
|
||||
},
|
||||
petOperationPostMockCategoryName: {
|
||||
selector: ".swagger-ui .opblock-tag-section:nth-child(1) div#operations-pet-addPet pre.microlight span:nth-child(23)"
|
||||
},
|
||||
petOperationPostMockName: {
|
||||
selector: ".swagger-ui .opblock-tag-section:nth-child(1) div#operations-pet-addPet pre.microlight span:nth-child(31)"
|
||||
},
|
||||
petOperationPostTagID: {
|
||||
selector: ".swagger-ui .opblock-tag-section:nth-child(1) div#operations-pet-addPet pre.microlight span:nth-child(54)"
|
||||
},
|
||||
petOperationPostTagName: {
|
||||
selector: ".swagger-ui .opblock-tag-section:nth-child(1) div#operations-pet-addPet pre.microlight span:nth-child(60)"
|
||||
},
|
||||
petOperationPostStatus: {
|
||||
selector: ".swagger-ui .opblock-tag-section:nth-child(1) div#operations-pet-addPet pre.microlight span:nth-child(70)"
|
||||
},
|
||||
/**
|
||||
* Put pet/ api
|
||||
*/
|
||||
petOperationPutContainer: {
|
||||
selector: ".swagger-ui .opblock-tag-section:nth-child(1) div#operations-pet-updatePet"
|
||||
},
|
||||
petOperationPutTitle: {
|
||||
selector: ".swagger-ui .opblock-tag-section:nth-child(1) div#operations-pet-updatePet .opblock-summary-put span.opblock-summary-path span"
|
||||
},
|
||||
petOperationPutCollpase: {
|
||||
selector: ".swagger-ui .opblock-tag-section:nth-child(1) div#operations-pet-updatePet .opblock-summary-put"
|
||||
},
|
||||
petOperationPutCollapseContainer: {
|
||||
selector: ".swagger-ui .opblock-tag-section:nth-child(1) div#operations-pet-updatePet>div:nth-child(2)"
|
||||
},
|
||||
petOperationPutTryBtn: {
|
||||
selector: ".swagger-ui .opblock-tag-section:nth-child(1) div#operations-pet-updatePet button.try-out__btn"
|
||||
},
|
||||
petOperationPutTryText: {
|
||||
selector: ".swagger-ui .opblock-tag-section:nth-child(1) div#operations-pet-updatePet textarea.body-param__text"
|
||||
},
|
||||
petOperationPutExecuteBtn: {
|
||||
selector: ".swagger-ui .opblock-tag-section:nth-child(1) div#operations-pet-updatePet button.execute"
|
||||
},
|
||||
petOperationPutTryTextArea: {
|
||||
selector: ".swagger-ui .opblock-tag-section:nth-child(1) div#operations-pet-updatePet textarea"
|
||||
},
|
||||
petOperationPutResultsBox: {
|
||||
selector: ".swagger-ui .opblock-tag-section:nth-child(1) div#operations-pet-updatePet pre.microlight"
|
||||
},
|
||||
petOperationPutMockCategoryID: {
|
||||
selector: ".swagger-ui .opblock-tag-section:nth-child(1) div#operations-pet-updatePet pre.microlight span:nth-child(17)"
|
||||
},
|
||||
petOperationPutMockCategoryName: {
|
||||
selector: ".swagger-ui .opblock-tag-section:nth-child(1) div#operations-pet-updatePet pre.microlight span:nth-child(23)"
|
||||
},
|
||||
petOperationPutMockName: {
|
||||
selector: ".swagger-ui .opblock-tag-section:nth-child(1) div#operations-pet-updatePet pre.microlight span:nth-child(31)"
|
||||
},
|
||||
petOperationPutTagID: {
|
||||
selector: ".swagger-ui .opblock-tag-section:nth-child(1) div#operations-pet-updatePet pre.microlight span:nth-child(54)"
|
||||
},
|
||||
petOperationPutTagName: {
|
||||
selector: ".swagger-ui .opblock-tag-section:nth-child(1) div#operations-pet-updatePet pre.microlight span:nth-child(60)"
|
||||
},
|
||||
petOperationPutStatus: {
|
||||
selector: ".swagger-ui .opblock-tag-section:nth-child(1) div#operations-pet-updatePet pre.microlight span:nth-child(70)"
|
||||
},
|
||||
/**
|
||||
* Get pet/
|
||||
*/
|
||||
petOperationGetByTagContainer: {
|
||||
selector: ".swagger-ui .opblock-tag-section:nth-child(1) div#operations-pet-findPetsByTags"
|
||||
},
|
||||
petOperationGetByTagTitle: {
|
||||
selector: ".swagger-ui .opblock-tag-section:nth-child(1) div#operations-pet-findPetsByTags .opblock-summary-get span.opblock-summary-path__deprecated span"
|
||||
},
|
||||
petOperationGetByTagCollpase: {
|
||||
selector: ".swagger-ui .opblock-tag-section:nth-child(1) div#operations-pet-findPetsByTags .opblock-summary-get"
|
||||
},
|
||||
petOperationGetByTagCollapseContainer: {
|
||||
selector: ".swagger-ui .opblock-tag-section:nth-child(1) div#operations-pet-findPetsByTags .ReactCollapse--collapse"
|
||||
},
|
||||
petOperationGetByTagTryBtn: {
|
||||
selector: ".swagger-ui .opblock-tag-section:nth-child(1) div#operations-pet-findPetsByTags button.try-out__btn"
|
||||
},
|
||||
petOperationGetByTagTryAdded: {
|
||||
selector: ".swagger-ui .opblock-tag-section:nth-child(1) div#operations-pet-findPetsByTags button.json-schema-form-item-add"
|
||||
},
|
||||
petOperationGetByTagExecuteBtn: {
|
||||
selector: ".swagger-ui .opblock-tag-section:nth-child(1) div#operations-pet-findPetsByTags button.execute"
|
||||
},
|
||||
petOperationGetByTagTryTextArea: {
|
||||
selector: ".swagger-ui .opblock-tag-section:nth-child(1) div#operations-pet-findPetsByTags textarea"
|
||||
},
|
||||
petOperationGetByTagResultsBox: {
|
||||
selector: ".swagger-ui .opblock-tag-section:nth-child(1) div#operations-pet-findPetsByTags pre.microlight"
|
||||
},
|
||||
petOperationGetByTagMockCategoryID: {
|
||||
selector: ".swagger-ui .opblock-tag-section:nth-child(1) div#operations-pet-findPetsByTags pre.microlight span:nth-child(17)"
|
||||
},
|
||||
petOperationGetByTagMockCategoryName: {
|
||||
selector: ".swagger-ui .opblock-tag-section:nth-child(1) div#operations-pet-findPetsByTags pre.microlight span:nth-child(23)"
|
||||
},
|
||||
petOperationGetByTagMockName: {
|
||||
selector: ".swagger-ui .opblock-tag-section:nth-child(1) div#operations-pet-findPetsByTags pre.microlight span:nth-child(31)"
|
||||
},
|
||||
petOperationGetByTagTagID: {
|
||||
selector: ".swagger-ui .opblock-tag-section:nth-child(1) div#operations-pet-findPetsByTags pre.microlight span:nth-child(54)"
|
||||
},
|
||||
petOperationGetByTagTagName: {
|
||||
selector: ".swagger-ui .opblock-tag-section:nth-child(1) div#operations-pet-findPetsByTags pre.microlight span:nth-child(60)"
|
||||
},
|
||||
petOperationGetByTagStatus: {
|
||||
selector: ".swagger-ui .opblock-tag-section:nth-child(1) div#operations-pet-findPetsByTags pre.microlight span:nth-child(70)"
|
||||
},
|
||||
|
||||
/**
|
||||
* Delete pet/
|
||||
*/
|
||||
petOperationDeleteContainer: {
|
||||
selector: ".swagger-ui .opblock-tag-section:nth-child(1) div#operations-pet-deletePet"
|
||||
},
|
||||
petOperationDeleteTitle: {
|
||||
selector: ".swagger-ui .opblock-tag-section:nth-child(1) div#operations-pet-deletePet .opblock-summary-delete span.opblock-summary-path span"
|
||||
},
|
||||
petOperationDeleteCollpase: {
|
||||
selector: ".swagger-ui .opblock-tag-section:nth-child(1) div#operations-pet-deletePet .opblock-summary-delete"
|
||||
},
|
||||
petOperationDeleteCollapseContainer: {
|
||||
selector: ".swagger-ui .opblock-tag-section:nth-child(1) div#operations-pet-deletePet>div:nth-child(2)"
|
||||
},
|
||||
petOperationDeleteTryBtn: {
|
||||
selector: ".swagger-ui .opblock-tag-section:nth-child(1) div#operations-pet-deletePet button.try-out__btn"
|
||||
},
|
||||
petOperationDeleteExecuteBtn: {
|
||||
selector: ".swagger-ui .opblock-tag-section:nth-child(1) div#operations-pet-deletePet button.execute"
|
||||
},
|
||||
petOperationDeleteTryTextArea: {
|
||||
selector: ".swagger-ui .opblock-tag-section:nth-child(1) div#operations-pet-deletePet textarea"
|
||||
},
|
||||
petOperationDeleteResultsBox: {
|
||||
selector: ".swagger-ui .opblock-tag-section:nth-child(1) div#operations-pet-deletePet pre.microlight"
|
||||
},
|
||||
petOperationDeleteMockCategoryID: {
|
||||
selector: ".swagger-ui .opblock-tag-section:nth-child(1) div#operations-pet-deletePet pre.microlight span:nth-child(17)"
|
||||
},
|
||||
petOperationDeleteMockCategoryName: {
|
||||
selector: ".swagger-ui .opblock-tag-section:nth-child(1) div#operations-pet-deletePet pre.microlight span:nth-child(23)"
|
||||
},
|
||||
petOperationDeleteMockName: {
|
||||
selector: ".swagger-ui .opblock-tag-section:nth-child(1) div#operations-pet-deletePet pre.microlight span:nth-child(31)"
|
||||
},
|
||||
petOperationDeleteTagID: {
|
||||
selector: ".swagger-ui .opblock-tag-section:nth-child(1) div#operations-pet-deletePet pre.microlight span:nth-child(54)"
|
||||
},
|
||||
petOperationDeleteTagName: {
|
||||
selector: ".swagger-ui .opblock-tag-section:nth-child(1) div#operations-pet-deletePet pre.microlight span:nth-child(60)"
|
||||
},
|
||||
petOperationDeleteStatus: {
|
||||
selector: ".swagger-ui .opblock-tag-section:nth-child(1) div#operations-pet-deletePet pre.microlight span:nth-child(70)"
|
||||
},
|
||||
|
||||
/**
|
||||
* ***********Store************
|
||||
*/
|
||||
storeAPIWrapper: {
|
||||
selector: ".swagger-ui .opblock-tag-section:nth-child(2)"
|
||||
},
|
||||
storeAPIWrapperBar: {
|
||||
selector: ".swagger-ui .opblock-tag-section:nth-child(2) .opblock-tag"
|
||||
},
|
||||
/**
|
||||
* Get /store/inventory
|
||||
*/
|
||||
storeOperationGetContainer: {
|
||||
selector: ".swagger-ui .opblock-tag-section:nth-child(2) div#operations-store-getInventory"
|
||||
},
|
||||
storeOperationGetTitle: {
|
||||
selector: ".swagger-ui .opblock-tag-section:nth-child(2) div#operations-store-getInventory .opblock-summary-get span.opblock-summary-path span"
|
||||
},
|
||||
storeOperationGetCollpase: {
|
||||
selector: ".swagger-ui .opblock-tag-section:nth-child(2) div#operations-store-getInventory .opblock-summary-get"
|
||||
},
|
||||
storeOperationGetCollapseContainer: {
|
||||
selector: ".swagger-ui .opblock-tag-section:nth-child(2) div#operations-store-getInventory>div:nth-child(2)"
|
||||
},
|
||||
storeOperationGetTryBtn: {
|
||||
selector: ".swagger-ui .opblock-tag-section:nth-child(2) div#operations-store-getInventory button.try-out__btn"
|
||||
},
|
||||
storeOperationGetExecuteBtn: {
|
||||
selector: ".swagger-ui .opblock-tag-section:nth-child(2) div#operations-store-getInventory button.execute"
|
||||
},
|
||||
storeOperationResponseProps1: {
|
||||
selector: ".swagger-ui .opblock-tag-section:nth-child(2) div#operations-store-getInventory pre.example.microlight span:nth-child(6)"
|
||||
},
|
||||
storeOperationResponseProps2: {
|
||||
selector: ".swagger-ui .opblock-tag-section:nth-child(2) div#operations-store-getInventory pre.example.microlight span:nth-child(12)"
|
||||
},
|
||||
storeOperationResponseProps3: {
|
||||
selector: ".swagger-ui .opblock-tag-section:nth-child(2) div#operations-store-getInventory pre.example.microlight span:nth-child(18)"
|
||||
},
|
||||
/**
|
||||
* Post /store/order
|
||||
*/
|
||||
storeOperationPostContainer: {
|
||||
selector: ".swagger-ui .opblock-tag-section:nth-child(2) div#operations-store-placeOrder"
|
||||
},
|
||||
storeOperationPostTitle: {
|
||||
selector: ".swagger-ui .opblock-tag-section:nth-child(2) div#operations-store-placeOrder .opblock-summary-post span.opblock-summary-path span"
|
||||
},
|
||||
storeOperationPostCollpase: {
|
||||
selector: ".swagger-ui .opblock-tag-section:nth-child(2) div#operations-store-placeOrder .opblock-summary-post"
|
||||
},
|
||||
storeOperationPostCollapseContainer: {
|
||||
selector: ".swagger-ui .opblock-tag-section:nth-child(2) div#operations-store-placeOrder>div:nth-child(2)"
|
||||
},
|
||||
storeOperationPostTryBtn: {
|
||||
selector: ".swagger-ui .opblock-tag-section:nth-child(2) div#operations-store-placeOrder button.try-out__btn"
|
||||
},
|
||||
storeOperationPostExecuteBtn: {
|
||||
selector: ".swagger-ui .opblock-tag-section:nth-child(2) div#operations-store-placeOrder button.execute"
|
||||
},
|
||||
storeOperationPostResponseId: {
|
||||
selector: ".swagger-ui .opblock-tag-section:nth-child(2) div#operations-store-placeOrder pre.example.microlight span:nth-child(22)"
|
||||
},
|
||||
storeOperationPostResponsePetId: {
|
||||
selector: ".swagger-ui .opblock-tag-section:nth-child(2) div#operations-store-placeOrder pre.example.microlight span:nth-child(31)"
|
||||
},
|
||||
storeOperationPostResponseQuantity: {
|
||||
selector: ".swagger-ui .opblock-tag-section:nth-child(2) div#operations-store-placeOrder pre.example.microlight span:nth-child(40)"
|
||||
},
|
||||
storeOperationPostResponseStatus: {
|
||||
selector: ".swagger-ui .opblock-tag-section:nth-child(2) div#operations-store-placeOrder pre.example.microlight span:nth-child(66)"
|
||||
},
|
||||
storeOperationPostResponseComplete: {
|
||||
selector: ".swagger-ui .opblock-tag-section:nth-child(2) div#operations-store-placeOrder pre.example.microlight span:nth-child(75)"
|
||||
},
|
||||
/**
|
||||
* Delete /store/order/{orderId}
|
||||
*/
|
||||
storeOperationDeleteContainer: {
|
||||
selector: ".swagger-ui .opblock-tag-section:nth-child(2) div#operations-store-deleteOrder"
|
||||
},
|
||||
storeOperationDeleteTitle: {
|
||||
selector: ".swagger-ui .opblock-tag-section:nth-child(2) div#operations-store-deleteOrder .opblock-summary-delete span.opblock-summary-path span"
|
||||
},
|
||||
storeOperationDeleteCollpase: {
|
||||
selector: ".swagger-ui .opblock-tag-section:nth-child(2) div#operations-store-deleteOrder .opblock-summary-delete"
|
||||
},
|
||||
storeOperationDeleteCollapseContainer: {
|
||||
selector: ".swagger-ui .opblock-tag-section:nth-child(2) div#operations-store-deleteOrder>div:nth-child(2)"
|
||||
},
|
||||
storeOperationDeleteTryBtn: {
|
||||
selector: ".swagger-ui .opblock-tag-section:nth-child(2) div#operations-store-deleteOrder button.try-out__btn"
|
||||
},
|
||||
storeOperationDeleteExecuteBtn: {
|
||||
selector: ".swagger-ui .opblock-tag-section:nth-child(2) div#operations-store-deleteOrder button.execute"
|
||||
},
|
||||
storeOperationGetResponseHeaders: {
|
||||
selector: ".swagger-ui .opblock-tag-section:nth-child(2) div#operations-store-deleteOrder pre span"
|
||||
},
|
||||
/**
|
||||
* *********User**************
|
||||
*/
|
||||
userAPIWrapper: {
|
||||
selector: ".swagger-ui .opblock-tag-section:nth-child(3)"
|
||||
},
|
||||
userAPIWrapperBar: {
|
||||
selector: ".swagger-ui .opblock-tag-section:nth-child(3) .opblock-tag"
|
||||
},
|
||||
/**
|
||||
* Put /user/login
|
||||
*/
|
||||
userOperationPutContainer: {
|
||||
selector: ".swagger-ui .opblock-tag-section:nth-child(3) div#operations-user-updateUser"
|
||||
},
|
||||
userOperationPutTitle: {
|
||||
selector: ".swagger-ui .opblock-tag-section:nth-child(3) div#operations-user-updateUser .opblock-summary-put span.opblock-summary-path span"
|
||||
},
|
||||
userOperationPutCollpase: {
|
||||
selector: ".swagger-ui .opblock-tag-section:nth-child(3) div#operations-user-updateUser .opblock-summary-put"
|
||||
},
|
||||
userOperationPutCollapseContainer: {
|
||||
selector: ".swagger-ui .opblock-tag-section:nth-child(3) div#operations-user-updateUser>div:nth-child(2)"
|
||||
},
|
||||
userOperationPutTryBtn: {
|
||||
selector: ".swagger-ui .opblock-tag-section:nth-child(3) div#operations-user-updateUser button.try-out__btn"
|
||||
},
|
||||
userOperationPutExecuteBtn: {
|
||||
selector: ".swagger-ui .opblock-tag-section:nth-child(3) div#operations-user-updateUser button.execute"
|
||||
},
|
||||
userOperationPutParameter: {
|
||||
selector: ".swagger-ui .opblock-tag-section:nth-child(3) div#operations-user-updateUser div.parameters-col_description input"
|
||||
},
|
||||
userOperationPutResponseHeader: {
|
||||
selector: ".swagger-ui .opblock-tag-section:nth-child(3) div#operations-user-updateUser div.parameters-col_description input"
|
||||
},
|
||||
/**
|
||||
* Delete /user
|
||||
*/
|
||||
userOperationDeleteContainer: {
|
||||
selector: ".swagger-ui .opblock-tag-section:nth-child(3) div#operations-user-deleteUser"
|
||||
},
|
||||
userOperationDeleteTitle: {
|
||||
selector: ".swagger-ui .opblock-tag-section:nth-child(3) div#operations-user-deleteUser .opblock-summary-delete span.opblock-summary-path span"
|
||||
},
|
||||
userOperationDeleteCollpase: {
|
||||
selector: ".swagger-ui .opblock-tag-section:nth-child(3) div#operations-user-deleteUser .opblock-summary-delete"
|
||||
},
|
||||
userOperationDeleteCollapseContainer: {
|
||||
selector: ".swagger-ui .opblock-tag-section:nth-child(3) div#operations-user-deleteUser>div:nth-child(2)"
|
||||
},
|
||||
userOperationDeleteTryBtn: {
|
||||
selector: ".swagger-ui .opblock-tag-section:nth-child(3) div#operations-user-deleteUser button.try-out__btn"
|
||||
},
|
||||
userOperationDeleteExecuteBtn: {
|
||||
selector: ".swagger-ui .opblock-tag-section:nth-child(3) div#operations-user-deleteUser button.execute"
|
||||
},
|
||||
userOperationDeleteParameter: {
|
||||
selector: ".swagger-ui .opblock-tag-section:nth-child(3) div#operations-user-deleteUser div.parameters-col_description input"
|
||||
},
|
||||
userOperationDeleteResponseHeader: {
|
||||
selector: ".swagger-ui .opblock-tag-section:nth-child(3) .opblock-delete div.parameters-col_description input"
|
||||
},
|
||||
|
||||
}
|
||||
},
|
||||
/* Model Container */
|
||||
modelWrapper: {
|
||||
selector: ".swagger-ui .wrapper:nth-child(4)",
|
||||
elements: {
|
||||
modelContainer: {
|
||||
selector: ".swagger-ui .models"
|
||||
},
|
||||
modelCollapse: {
|
||||
selector: ".swagger-ui .models h4"
|
||||
},
|
||||
orderModel: {
|
||||
selector: "section.models div.model-container:nth-child(1)"
|
||||
},
|
||||
orderModelCallapse: {
|
||||
selector: "section.models div.model-container:nth-child(1) span.model-toggle"
|
||||
},
|
||||
categoryModel: {
|
||||
selector: "section.models div.model-container:nth-child(2)"
|
||||
},
|
||||
categoryModelCallapse: {
|
||||
selector: "section.models div.model-container:nth-child(2) span.model-toggle"
|
||||
},
|
||||
userModel: {
|
||||
selector: "section.models div.model-container:nth-child(3)"
|
||||
},
|
||||
userModelCallapse: {
|
||||
selector: "section.models div.model-container:nth-child(3) span.model-toggle"
|
||||
},
|
||||
tagModel: {
|
||||
selector: "section.models div.model-container:nth-child(4)"
|
||||
},
|
||||
tagModelCallapse: {
|
||||
selector: "section.models div.model-container:nth-child(4) span.model-toggle"
|
||||
},
|
||||
petModel: {
|
||||
selector: "section.models div.model-container:nth-child(5)"
|
||||
},
|
||||
petModelCallapse: {
|
||||
selector: "section.models div.model-container:nth-child(5) span.model-toggle"
|
||||
},
|
||||
apiResponseModel: {
|
||||
selector: "section.models div.model-container:nth-child(6)"
|
||||
},
|
||||
apiResponseModelCallapse: {
|
||||
selector: "section.models div.model-container:nth-child(6) span.model-toggle"
|
||||
},
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
}
|
||||
}
|
||||
48
test/e2e/scenarios/informationContainer.js
Normal file
48
test/e2e/scenarios/informationContainer.js
Normal file
@@ -0,0 +1,48 @@
|
||||
describe("render informationContainer", function () {
|
||||
let mainPage
|
||||
let informationContainer
|
||||
beforeEach(function (client, done) {
|
||||
|
||||
mainPage = client
|
||||
.url("localhost:3200")
|
||||
.page.main()
|
||||
client.waitForElementVisible(".download-url-input", 5000)
|
||||
.pause(5000)
|
||||
.clearValue(".download-url-input")
|
||||
.setValue(".download-url-input", "http://localhost:3200/test-specs/petstore.json")
|
||||
.click("button.download-url-button")
|
||||
.pause(1000)
|
||||
|
||||
informationContainer = mainPage.section.informationContainer
|
||||
|
||||
done()
|
||||
})
|
||||
|
||||
it("renders section", function (client) {
|
||||
mainPage.expect.section("@informationContainer").to.be.visible.before(5000)
|
||||
|
||||
client.end()
|
||||
})
|
||||
|
||||
it("renders content", function (client) {
|
||||
informationContainer.waitForElementVisible("@title", 5000)
|
||||
.assert.containsText("@title", "Swagger Petstore")
|
||||
.assert.containsText("@version", "1.0.0")
|
||||
.assert.containsText("@baseUrl", "[ Base URL: localhost:3204/ ]")
|
||||
.assert.attributeEquals("@mainUrl", "href", "http://localhost:3200/test-specs/petstore.json")
|
||||
.assert.containsText("@mainUrlContent", "http://localhost:3200/test-specs/petstore.json")
|
||||
.assert.containsText("@description", "This is a sample server Petstore server. You can find out more about Swagger at http://swagger.io or on irc.freenode.net, #swagger. For this sample, you can use the api key special-key to test the authorization filters.")
|
||||
.assert.attributeEquals("@swaggerUrl", "href", "http://swagger.io/")
|
||||
.assert.attributeEquals("@swaggerircUrl", "href", "http://swagger.io/irc/")
|
||||
.assert.attributeEquals("@termsLink", "href", "http://swagger.io/terms/")
|
||||
.assert.containsText("@termsLink", "Terms of service")
|
||||
.assert.attributeEquals("@contactDevLink", "href", "mailto:apiteam@swagger.io")
|
||||
.assert.containsText("@contactDevLink", "Contact the developer")
|
||||
.assert.attributeEquals("@contactDevLink", "href", "mailto:apiteam@swagger.io")
|
||||
.assert.containsText("@contactDevLink", "Contact the developer")
|
||||
.assert.attributeEquals("@aboutSwaggerLink", "href", "http://swagger.io/")
|
||||
.assert.containsText("@aboutSwaggerLink", "Find out more about Swagger")
|
||||
|
||||
client.end()
|
||||
})
|
||||
})
|
||||
79
test/e2e/scenarios/models.js
Normal file
79
test/e2e/scenarios/models.js
Normal file
@@ -0,0 +1,79 @@
|
||||
describe("Render Model Wrapper", function () {
|
||||
let modelWrapper, mainPage
|
||||
|
||||
beforeEach(function (client, done) {
|
||||
mainPage = client
|
||||
.url("localhost:3200")
|
||||
.page.main()
|
||||
client.waitForElementVisible(".download-url-input", 5000)
|
||||
.pause(5000)
|
||||
.clearValue(".download-url-input")
|
||||
.setValue(".download-url-input", "http://localhost:3200/test-specs/petstore.json")
|
||||
.click("button.download-url-button")
|
||||
.pause(1000)
|
||||
|
||||
modelWrapper = mainPage.section.modelWrapper
|
||||
|
||||
done()
|
||||
})
|
||||
afterEach(function (client, done){
|
||||
done()
|
||||
})
|
||||
it("Render model wrapper", function(client){
|
||||
mainPage.expect.section("@modelWrapper").to.be.visible.before(5000)
|
||||
|
||||
client.end()
|
||||
})
|
||||
|
||||
it("Render model wrapper collapse", function(client){
|
||||
modelWrapper.waitForElementVisible("@modelContainer", 5000)
|
||||
.click("@modelCollapse")
|
||||
.assert.cssClassNotPresent("@modelContainer", "is-open")
|
||||
|
||||
client.end()
|
||||
})
|
||||
|
||||
it("Testing order model", function(client){
|
||||
modelWrapper.waitForElementVisible("@orderModel")
|
||||
.click("@orderModelCallapse")
|
||||
.assert.cssClassNotPresent("@orderModelCallapse", "callapsed")
|
||||
|
||||
client.end()
|
||||
})
|
||||
|
||||
it("Testing category model", function(client){
|
||||
modelWrapper.waitForElementVisible("@categoryModel")
|
||||
.click("@categoryModelCallapse")
|
||||
.assert.cssClassNotPresent("@categoryModelCallapse", "callapsed")
|
||||
|
||||
client.end()
|
||||
})
|
||||
it("Testing user model", function(client){
|
||||
modelWrapper.waitForElementVisible("@userModel")
|
||||
.click("@userModelCallapse")
|
||||
.assert.cssClassNotPresent("@userModelCallapse", "callapsed")
|
||||
|
||||
client.end()
|
||||
})
|
||||
it("Testing tag model", function(client){
|
||||
modelWrapper.waitForElementVisible("@tagModel")
|
||||
.click("@tagModelCallapse")
|
||||
.assert.cssClassNotPresent("@tagModelCallapse", "callapsed")
|
||||
|
||||
client.end()
|
||||
})
|
||||
it("Testing pet model", function(client){
|
||||
modelWrapper.waitForElementVisible("@petModel")
|
||||
.click("@petModelCallapse")
|
||||
.assert.cssClassNotPresent("@petModelCallapse", "callapsed")
|
||||
|
||||
client.end()
|
||||
})
|
||||
it("Testing apiResponse model", function(client){
|
||||
modelWrapper.waitForElementVisible("@apiResponseModel")
|
||||
.click("@apiResponseModelCallapse")
|
||||
.assert.cssClassNotPresent("@apiResponseModelCallapse", "callapsed")
|
||||
|
||||
client.end()
|
||||
})
|
||||
})
|
||||
172
test/e2e/scenarios/operations/pet.js
Normal file
172
test/e2e/scenarios/operations/pet.js
Normal file
@@ -0,0 +1,172 @@
|
||||
describe("render pet api container", function () {
|
||||
let mainPage
|
||||
let apiWrapper
|
||||
beforeEach(function (client, done) {
|
||||
mainPage = client
|
||||
.url("localhost:3200")
|
||||
.page.main()
|
||||
|
||||
client.waitForElementVisible(".download-url-input", 5000)
|
||||
.pause(5000)
|
||||
.clearValue(".download-url-input")
|
||||
.setValue(".download-url-input", "http://localhost:3200/test-specs/petstore.json")
|
||||
.click("button.download-url-button")
|
||||
.pause(1000)
|
||||
|
||||
apiWrapper = mainPage.section.apiWrapper
|
||||
|
||||
done()
|
||||
})
|
||||
afterEach(function (client, done) {
|
||||
done()
|
||||
})
|
||||
it("render section", function (client) {
|
||||
mainPage.expect.section("@apiWrapper").to.be.visible.before(10000)
|
||||
client.end()
|
||||
})
|
||||
it("test rendered pet container", function (client) {
|
||||
apiWrapper.waitForElementVisible("@petAPIWrapper", 5000)
|
||||
.expect.element("@petAPIWrapper").to.be.visible
|
||||
|
||||
client.end()
|
||||
})
|
||||
it("collapse pet wrapper", function (client) {
|
||||
apiWrapper.waitForElementVisible("@petAPIWrapper", 5000)
|
||||
.click("@petAPIWrapperBar")
|
||||
.assert.cssClassNotPresent("@petAPIWrapper", "is-open")
|
||||
|
||||
client.end()
|
||||
})
|
||||
it("render post /pet api container", function (client) {
|
||||
apiWrapper.waitForElementVisible("@petOperationPostContainer", 10000)
|
||||
.assert.containsText("@petOperationPostTitle", "/pet")
|
||||
.click("@petOperationPostCollpase")
|
||||
.waitForElementVisible("@petOperationPostCollapseContainer", 5000)
|
||||
.click("@petOperationPostTryBtn")
|
||||
.waitForElementVisible("@petOperationPostTryText", 1000)
|
||||
.waitForElementVisible("@petOperationPostExecuteBtn", 1000)
|
||||
.click("@petOperationPostTryBtn")
|
||||
.assert.cssClassNotPresent("@petOperationPostTryBtn", "cancel")
|
||||
|
||||
client.end()
|
||||
})
|
||||
|
||||
it("Testing post /pet api Mock data", function (client) {
|
||||
apiWrapper.waitForElementVisible("@petOperationPostContainer", 5000)
|
||||
.click("@petOperationPostCollpase")
|
||||
.waitForElementVisible("@petOperationPostCollapseContainer", 5000)
|
||||
.click("@petOperationPostTryBtn")
|
||||
.waitForElementVisible("@petOperationPostExecuteBtn", 1000)
|
||||
.click("@petOperationPostExecuteBtn")
|
||||
.waitForElementVisible("@petOperationPostMockCategoryID", 2000)
|
||||
.assert.containsText("@petOperationPostMockCategoryID", "0")
|
||||
.assert.containsText("@petOperationPostMockCategoryName", "\"string\"")
|
||||
.assert.containsText("@petOperationPostMockName", "\"doggie\"")
|
||||
.assert.containsText("@petOperationPostTagID", "0")
|
||||
.assert.containsText("@petOperationPostTagName", "\"string\"")
|
||||
.assert.containsText("@petOperationPostStatus", "\"available\"")
|
||||
.click("@petOperationPostTryBtn")
|
||||
.assert.cssClassNotPresent("@petOperationPostTryBtn", "cancel")
|
||||
|
||||
client.end()
|
||||
})
|
||||
|
||||
it("render put /pet api container", function (client) {
|
||||
apiWrapper.waitForElementVisible("@petOperationPutContainer", 5000)
|
||||
.assert.containsText("@petOperationPutTitle", "/pet")
|
||||
.click("@petOperationPutCollpase")
|
||||
.waitForElementVisible("@petOperationPutCollapseContainer", 3000)
|
||||
.click("@petOperationPutTryBtn")
|
||||
.waitForElementVisible("@petOperationPutTryText", 1000)
|
||||
.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")
|
||||
.waitForElementVisible("@petOperationPutCollapseContainer", 3000)
|
||||
.click("@petOperationPutTryBtn")
|
||||
.waitForElementVisible("@petOperationPutExecuteBtn", 1000)
|
||||
.click("@petOperationPutExecuteBtn")
|
||||
.waitForElementVisible("@petOperationPutMockCategoryID")
|
||||
.assert.containsText("@petOperationPutMockCategoryID", "0")
|
||||
.assert.containsText("@petOperationPutMockCategoryName", "\"string\"")
|
||||
.assert.containsText("@petOperationPutMockName", "\"doggie\"")
|
||||
.assert.containsText("@petOperationPutTagID", "0")
|
||||
.assert.containsText("@petOperationPutTagName", "\"string\"")
|
||||
.assert.containsText("@petOperationPutStatus", "\"available\"")
|
||||
.click("@petOperationPutTryBtn")
|
||||
.assert.cssClassNotPresent("@petOperationPutTryBtn", "Cancel")
|
||||
|
||||
client.end()
|
||||
})
|
||||
|
||||
it("render get by tag /pet api container", function (client) {
|
||||
apiWrapper.waitForElementVisible("@petOperationGetByTagContainer", 5000)
|
||||
.assert.containsText("@petOperationGetByTagTitle", "/pet/findByTags")
|
||||
.click("@petOperationGetByTagCollpase")
|
||||
.waitForElementVisible("@petOperationGetByTagCollapseContainer", 3000)
|
||||
.click("@petOperationGetByTagTryBtn")
|
||||
.waitForElementVisible("@petOperationGetByTagTryAdded", 1000)
|
||||
.waitForElementVisible("@petOperationGetByTagExecuteBtn", 1000)
|
||||
.click("@petOperationGetByTagTryBtn")
|
||||
.assert.cssClassNotPresent("@petOperationGetByTagTryBtn", "cancel")
|
||||
|
||||
client.end()
|
||||
})
|
||||
|
||||
it("Testing get by tag /pet api Mock data", function (client) {
|
||||
apiWrapper.waitForElementVisible("@petOperationGetByTagContainer", 5000)
|
||||
.click("@petOperationGetByTagCollpase")
|
||||
.waitForElementVisible("@petOperationGetByTagCollapseContainer", 3000)
|
||||
.click("@petOperationGetByTagTryBtn")
|
||||
.waitForElementVisible("@petOperationGetByTagExecuteBtn", 1000)
|
||||
.click("@petOperationGetByTagExecuteBtn")
|
||||
.waitForElementVisible("@petOperationGetByTagMockCategoryID")
|
||||
.assert.containsText("@petOperationGetByTagMockCategoryID", "0")
|
||||
.assert.containsText("@petOperationGetByTagMockCategoryName", "\"string\"")
|
||||
.assert.containsText("@petOperationGetByTagMockName", "\"doggie\"")
|
||||
.assert.containsText("@petOperationGetByTagTagID", "0")
|
||||
.assert.containsText("@petOperationGetByTagTagName", "\"string\"")
|
||||
.assert.containsText("@petOperationGetByTagStatus", "\"available\"")
|
||||
.click("@petOperationGetByTagTryBtn")
|
||||
.assert.cssClassNotPresent("@petOperationGetByTagTryBtn", "cancel")
|
||||
|
||||
client.end()
|
||||
})
|
||||
|
||||
it("render delete /pet api container", function (client) {
|
||||
apiWrapper.waitForElementVisible("@petOperationDeleteContainer")
|
||||
.assert.containsText("@petOperationDeleteTitle", "/pet/{petId}")
|
||||
.click("@petOperationDeleteCollpase")
|
||||
.waitForElementVisible("@petOperationDeleteCollapseContainer", 3000)
|
||||
.click("@petOperationDeleteTryBtn")
|
||||
.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")
|
||||
.waitForElementVisible("@petOperationDeleteCollapseContainer", 3000)
|
||||
.click("@petOperationDeleteTryBtn")
|
||||
.waitForElementVisible("@petOperationDeleteExecuteBtn", 1000)
|
||||
.click("@petOperationDeleteExecuteBtn")
|
||||
.waitForElementVisible("@petOperationDeleteMockCategoryID")
|
||||
.assert.containsText("@petOperationDeleteMockCategoryID", "0")
|
||||
.assert.containsText("@petOperationDeleteMockCategoryName", "\"string\"")
|
||||
.assert.containsText("@petOperationDeleteMockName", "\"doggie\"")
|
||||
.assert.containsText("@petOperationDeleteTagID", "0")
|
||||
.assert.containsText("@petOperationDeleteTagName", "\"string\"")
|
||||
.assert.containsText("@petOperationDeleteStatus", "\"available\"")
|
||||
.click("@petOperationDeleteTryBtn")
|
||||
.assert.cssClassNotPresent("@petOperationDeleteTryBtn", "cancel")
|
||||
|
||||
client.end()
|
||||
})
|
||||
})
|
||||
113
test/e2e/scenarios/operations/store.js
Normal file
113
test/e2e/scenarios/operations/store.js
Normal file
@@ -0,0 +1,113 @@
|
||||
describe("render store api container", function(){
|
||||
let mainPage
|
||||
let apiWrapper
|
||||
beforeEach( function(client, done){
|
||||
mainPage = client
|
||||
.url("localhost:3200")
|
||||
.page.main()
|
||||
|
||||
client.waitForElementVisible(".download-url-input", 5000)
|
||||
.pause(3000)
|
||||
.clearValue(".download-url-input")
|
||||
.setValue(".download-url-input", "http://localhost:3200/test-specs/petstore.json")
|
||||
.click("button.download-url-button")
|
||||
.pause(1000)
|
||||
|
||||
apiWrapper = mainPage.section.apiWrapper
|
||||
|
||||
done()
|
||||
})
|
||||
afterEach(function (client, done) {
|
||||
done()
|
||||
})
|
||||
it("test rendered store container", function(client){
|
||||
apiWrapper.waitForElementVisible("@storeAPIWrapper", 5000)
|
||||
.expect.element("@storeAPIWrapper").to.be.visible
|
||||
|
||||
client.end()
|
||||
})
|
||||
it("callapse store wrapper", function(client){
|
||||
apiWrapper.waitForElementVisible("@storeAPIWrapper", 5000)
|
||||
.click("@storeAPIWrapperBar")
|
||||
.assert.cssClassNotPresent("@storeAPIWrapper", "is-open")
|
||||
|
||||
client.end()
|
||||
})
|
||||
it("render get /store/inventory api container", function (client) {
|
||||
apiWrapper.waitForElementVisible("@storeOperationGetContainer", 5000)
|
||||
.assert.containsText("@storeOperationGetTitle", "/store/inventory")
|
||||
.click("@storeOperationGetCollpase")
|
||||
.waitForElementVisible("@storeOperationGetCollapseContainer", 5000)
|
||||
.click("@storeOperationGetTryBtn")
|
||||
.waitForElementVisible("@storeOperationGetExecuteBtn", 1000)
|
||||
.click("@storeOperationGetTryBtn")
|
||||
.assert.cssClassNotPresent("@storeOperationGetTryBtn", "cancel")
|
||||
|
||||
client.end()
|
||||
})
|
||||
|
||||
it("Testing get /store/inventory api Mock data ", function (client) {
|
||||
apiWrapper.waitForElementVisible("@storeOperationGetContainer", 5000)
|
||||
.assert.containsText("@storeOperationGetTitle", "/store/inventory")
|
||||
.click("@storeOperationGetCollpase")
|
||||
.waitForElementVisible("@storeOperationGetCollapseContainer", 3000)
|
||||
.click("@storeOperationGetTryBtn")
|
||||
.waitForElementVisible("@storeOperationGetExecuteBtn", 1000)
|
||||
.click("@storeOperationGetExecuteBtn")
|
||||
.waitForElementVisible("@storeOperationResponseProps1")
|
||||
.assert.containsText("@storeOperationResponseProps1", "0")
|
||||
.assert.containsText("@storeOperationResponseProps2", "0")
|
||||
.assert.containsText("@storeOperationResponseProps3", "0")
|
||||
.click("@storeOperationGetTryBtn")
|
||||
.assert.cssClassNotPresent("@storeOperationGetTryBtn", "cancel")
|
||||
|
||||
client.end()
|
||||
})
|
||||
|
||||
it("render post /store/order api container", function (client) {
|
||||
apiWrapper.waitForElementVisible("@storeOperationPostContainer")
|
||||
.assert.containsText("@storeOperationPostTitle", "/store/order")
|
||||
.click("@storeOperationPostCollpase")
|
||||
.waitForElementVisible("@storeOperationPostCollapseContainer", 3000)
|
||||
.click("@storeOperationPostTryBtn")
|
||||
.waitForElementVisible("@storeOperationPostExecuteBtn", 1000)
|
||||
.click("@storeOperationPostTryBtn")
|
||||
.assert.cssClassNotPresent("@storeOperationPostTryBtn", "cancel")
|
||||
|
||||
client.end()
|
||||
})
|
||||
|
||||
it("Testing post /store/order api Mock Data", function (client) {
|
||||
apiWrapper.waitForElementVisible("@storeOperationPostContainer")
|
||||
.assert.containsText("@storeOperationPostTitle", "/store/order")
|
||||
.click("@storeOperationPostCollpase")
|
||||
.waitForElementVisible("@storeOperationPostCollapseContainer", 3000)
|
||||
.click("@storeOperationPostTryBtn")
|
||||
.waitForElementVisible("@storeOperationPostExecuteBtn", 1000)
|
||||
.click("@storeOperationPostExecuteBtn")
|
||||
.waitForElementVisible("@storeOperationPostResponseId")
|
||||
.assert.containsText("@storeOperationPostResponseId", "0")
|
||||
.assert.containsText("@storeOperationPostResponsePetId", "0")
|
||||
.assert.containsText("@storeOperationPostResponseQuantity", "0")
|
||||
.assert.containsText("@storeOperationPostResponseStatus", "placed")
|
||||
.assert.containsText("@storeOperationPostResponseComplete", "false")
|
||||
.click("@storeOperationPostTryBtn")
|
||||
.assert.cssClassNotPresent("@storeOperationPostTryBtn", "cancel")
|
||||
|
||||
client.end()
|
||||
})
|
||||
it("render delete /store/order/{orderId} api container", function (client) {
|
||||
apiWrapper.waitForElementVisible("@storeOperationDeleteContainer")
|
||||
.assert.containsText("@storeOperationDeleteTitle", "/store/order/{orderId}")
|
||||
.click("@storeOperationDeleteCollpase")
|
||||
.waitForElementVisible("@storeOperationDeleteCollapseContainer", 3000)
|
||||
.click("@storeOperationDeleteTryBtn")
|
||||
.waitForElementVisible("@storeOperationDeleteExecuteBtn", 1000)
|
||||
.click("@storeOperationDeleteExecuteBtn")
|
||||
.waitForElementVisible("@storeOperationGetResponseHeaders", "content-type: application/xml")
|
||||
.click("@storeOperationDeleteTryBtn")
|
||||
.assert.cssClassNotPresent("@storeOperationDeleteTryBtn", "cancel")
|
||||
|
||||
client.end()
|
||||
})
|
||||
})
|
||||
94
test/e2e/scenarios/operations/user.js
Normal file
94
test/e2e/scenarios/operations/user.js
Normal file
@@ -0,0 +1,94 @@
|
||||
describe("render user api container", function(){
|
||||
let mainPage
|
||||
let apiWrapper
|
||||
beforeEach( function(client, done){
|
||||
mainPage = client
|
||||
.url("localhost:3200")
|
||||
.page.main()
|
||||
|
||||
client.waitForElementVisible(".download-url-input", 5000)
|
||||
.pause(5000)
|
||||
.clearValue(".download-url-input")
|
||||
.setValue(".download-url-input", "http://localhost:3200/test-specs/petstore.json")
|
||||
.click("button.download-url-button")
|
||||
.pause(1000)
|
||||
|
||||
apiWrapper = mainPage.section.apiWrapper
|
||||
|
||||
done()
|
||||
})
|
||||
afterEach(function (client, done) {
|
||||
done()
|
||||
})
|
||||
it("test rendered user container", function(client){
|
||||
apiWrapper.waitForElementVisible("@userAPIWrapper", 5000)
|
||||
.expect.element("@userAPIWrapper").to.be.visible
|
||||
|
||||
client.end()
|
||||
})
|
||||
it("callapse user wrapper", function(client){
|
||||
apiWrapper.waitForElementVisible("@userAPIWrapper", 5000)
|
||||
.click("@userAPIWrapperBar")
|
||||
.assert.cssClassNotPresent("@userAPIWrapper", "is-open")
|
||||
|
||||
client.end()
|
||||
})
|
||||
it("render put /user/{username} api container", function (client) {
|
||||
apiWrapper.waitForElementVisible("@userOperationPutContainer", 5000)
|
||||
.assert.containsText("@userOperationPutTitle", "/user/{username}")
|
||||
.click("@userOperationPutCollpase")
|
||||
.waitForElementVisible("@userOperationPutCollapseContainer", 3000)
|
||||
.click("@userOperationPutTryBtn")
|
||||
.waitForElementVisible("@userOperationPutExecuteBtn", 1000)
|
||||
.click("@userOperationPutTryBtn")
|
||||
.assert.cssClassNotPresent("@userOperationPutTryBtn", "cancel")
|
||||
|
||||
client.end()
|
||||
})
|
||||
it("Test put /user/{username} api Mock data", function (client) {
|
||||
apiWrapper.waitForElementVisible("@userOperationPutContainer", 5000)
|
||||
.assert.containsText("@userOperationPutTitle", "/user/{username}")
|
||||
.click("@userOperationPutCollpase")
|
||||
.waitForElementVisible("@userOperationPutCollapseContainer", 3000)
|
||||
.click("@userOperationPutTryBtn")
|
||||
.waitForElementVisible("@userOperationPutParameter")
|
||||
.setValue("@userOperationPutParameter", "123")
|
||||
.waitForElementVisible("@userOperationPutExecuteBtn", 1000)
|
||||
.click("userOperationPutExecuteBtn")
|
||||
.waitForElementVisible("@userOperationPutResponseHeader")
|
||||
.assert.containsText("@userOperationPutResponseHeader", "content-type: application/xml")
|
||||
.click("@userOperationPutTryBtn")
|
||||
.assert.cssClassNotPresent("@userOperationPutTryBtn", "cancel")
|
||||
|
||||
client.end()
|
||||
})
|
||||
it("render delete /user/{username} api container", function (client) {
|
||||
apiWrapper.waitForElementVisible("@userOperationDeleteContainer", 5000)
|
||||
.assert.containsText("@userOperationDeleteTitle", "/user/{username}")
|
||||
.click("@userOperationDeleteCollpase")
|
||||
.waitForElementVisible("@userOperationDeleteCollapseContainer", 3000)
|
||||
.click("@userOperationDeleteTryBtn")
|
||||
.waitForElementVisible("@userOperationDeleteExecuteBtn", 1000)
|
||||
.click("@userOperationDeleteTryBtn")
|
||||
.assert.cssClassNotPresent("@userOperationDeleteTryBtn", "cancel")
|
||||
|
||||
client.end()
|
||||
})
|
||||
it("Test delete /user/{username} api Mock data", function (client) {
|
||||
apiWrapper.waitForElementVisible("@userOperationDeleteContainer", 5000)
|
||||
.assert.containsText("@userOperationDeleteTitle", "/user/{username}")
|
||||
.click("@userOperationDeleteCollpase")
|
||||
.waitForElementVisible("@userOperationDeleteCollapseContainer", 3000)
|
||||
.click("@userOperationDeleteTryBtn")
|
||||
.waitForElementVisible("@userOperationDeleteParameter")
|
||||
.setValue("@userOperationDeleteParameter", "123")
|
||||
.waitForElementVisible("@userOperationDeleteExecuteBtn", 1000)
|
||||
.click("userOperationDeleteExecuteBtn")
|
||||
.waitForElementVisible("@userOperationDeleteResponseHeader")
|
||||
.assert.containsText("@userOperationDeleteResponseHeader", "content-type: application/xml")
|
||||
.click("@userOperationDeleteTryBtn")
|
||||
.assert.cssClassNotPresent("@userOperationDeleteTryBtn", "cancel")
|
||||
|
||||
client.end()
|
||||
})
|
||||
})
|
||||
52
test/e2e/scenarios/schemeContainer.js
Normal file
52
test/e2e/scenarios/schemeContainer.js
Normal file
@@ -0,0 +1,52 @@
|
||||
describe("Render scheme", function () {
|
||||
let mainPage
|
||||
let schemeContainer
|
||||
beforeEach(function (client, done) {
|
||||
|
||||
mainPage = client
|
||||
.url("localhost:3200")
|
||||
.page.main()
|
||||
|
||||
schemeContainer = mainPage.section.schemeContainer
|
||||
|
||||
client.waitForElementVisible(".download-url-input", 5000)
|
||||
.pause(5000)
|
||||
.clearValue(".download-url-input")
|
||||
.setValue(".download-url-input", "http://localhost:3200/test-specs/petstore.json")
|
||||
.click("button.download-url-button")
|
||||
.pause(1000)
|
||||
|
||||
|
||||
done()
|
||||
})
|
||||
|
||||
it("render section", function (client) {
|
||||
mainPage.expect.section("@schemeContainer").to.be.visible.before(5000)
|
||||
|
||||
client.end()
|
||||
})
|
||||
it("render scheme option", function (client) {
|
||||
schemeContainer.waitForElementVisible("@httpOption", 5000)
|
||||
.expect.element("@httpOption").to.be.selected
|
||||
|
||||
client.end()
|
||||
})
|
||||
|
||||
it("render authorized button", function (client) {
|
||||
schemeContainer.waitForElementVisible("@btnAuthorize", 5000)
|
||||
.expect.element("@btnAuthorize").to.be.visible
|
||||
|
||||
client.end()
|
||||
})
|
||||
it("render click event", function(client) {
|
||||
schemeContainer.waitForElementVisible("@btnAuthorize", 5000)
|
||||
.click("@btnAuthorize")
|
||||
.assert.visible("@authorizationModal")
|
||||
.assert.containsText("@appName", "Application: your-app-name")
|
||||
.assert.containsText("@authorizationUrl", "http://petstore.swagger.io/oauth/dialog")
|
||||
.assert.containsText("@flow", "implicit")
|
||||
.assert.value("@inputClientID", "your-client-id")
|
||||
|
||||
client.end()
|
||||
})
|
||||
})
|
||||
52
test/e2e/scenarios/topbar.js
Normal file
52
test/e2e/scenarios/topbar.js
Normal file
@@ -0,0 +1,52 @@
|
||||
describe("initial render", function () {
|
||||
let mainPage
|
||||
describe("for topbar", function () {
|
||||
let topbar
|
||||
before(function (client, done) {
|
||||
done()
|
||||
})
|
||||
|
||||
after(function (client, done) {
|
||||
client.end(function () {
|
||||
done()
|
||||
})
|
||||
})
|
||||
|
||||
afterEach(function (client, done) {
|
||||
done()
|
||||
})
|
||||
|
||||
beforeEach(function (client, done) {
|
||||
mainPage = client
|
||||
.url("localhost:3200")
|
||||
.page.main()
|
||||
|
||||
topbar = mainPage.section.topbar
|
||||
|
||||
client.waitForElementVisible(".download-url-input", 10000)
|
||||
.pause(5000)
|
||||
.clearValue(".download-url-input")
|
||||
.setValue(".download-url-input", "http://localhost:3200/test-specs/petstore.json")
|
||||
.click("button.download-url-button")
|
||||
.pause(1000)
|
||||
|
||||
done()
|
||||
})
|
||||
|
||||
it("renders section", function (client) {
|
||||
mainPage.expect.section("@topbar").to.be.visible
|
||||
client.end()
|
||||
})
|
||||
|
||||
it("renders input box", function (client) {
|
||||
topbar.expect.element("@inputBox").to.be.visible
|
||||
client.end()
|
||||
})
|
||||
|
||||
it("renders explore button", function (client) {
|
||||
topbar.expect.element("@btnExplore").to.be.visible
|
||||
|
||||
client.end()
|
||||
})
|
||||
})
|
||||
})
|
||||
1043
test/e2e/specs/petstore.json
Normal file
1043
test/e2e/specs/petstore.json
Normal file
File diff suppressed because it is too large
Load Diff
@@ -1,3 +1,8 @@
|
||||
const config = require("./webpack-dist.config.js")
|
||||
|
||||
config.plugins = config.plugins.filter(plugin => {
|
||||
// Disable minification
|
||||
return plugin.constructor.name !== "UglifyJsPlugin"
|
||||
})
|
||||
|
||||
module.exports = config
|
||||
|
||||
Reference in New Issue
Block a user