Compare commits
17
Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
14ef0cc379 | ||
|
|
08cfc77fde | ||
|
|
b8cf080e6c | ||
|
|
245428e7cd | ||
|
|
624a81201f | ||
|
|
b0be261ef8 | ||
|
|
6c5a370ef7 | ||
|
|
fb7f12551f | ||
|
|
49e0466641 | ||
|
|
ad57f5a549 | ||
|
|
ebf94dfccf | ||
|
|
6ba93ad43f | ||
|
|
54153dd929 | ||
|
|
83232dc2d8 | ||
|
|
ad43965d16 | ||
|
|
861cc65cff | ||
|
|
4900b11079 |
+1
-2
@@ -15,7 +15,6 @@ before_deploy:
|
||||
- npm run build
|
||||
env:
|
||||
- DOCKER_IMAGE_NAME=swaggerapi/swagger-ui
|
||||
script: npm run test:ci
|
||||
deploy:
|
||||
- provider: npm
|
||||
email: apiteam@swagger.io
|
||||
@@ -35,7 +34,7 @@ deploy:
|
||||
node: '6.9'
|
||||
after_success:
|
||||
- if [ $DOCKER_HUB_USERNAME ]; then
|
||||
docker login --email=$DOCKER_HUB_EMAIL --username=$DOCKER_HUB_USERNAME --password=$DOCKER_HUB_PASSWORD;
|
||||
docker login --username=$DOCKER_HUB_USERNAME --password=$DOCKER_HUB_PASSWORD;
|
||||
|
||||
if [ ! -z "$TRAVIS_TAG" ]; then
|
||||
DOCKER_IMAGE_TAG=$TRAVIS_TAG;
|
||||
|
||||
@@ -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.11.0 | 2018-02-09 | 2.0, 3.0 | [tag v3.11.0](https://github.com/swagger-api/swagger-ui/tree/v3.11.0)
|
||||
3.13.0 | 2018-03-16 | 2.0, 3.0 | [tag v3.13.0](https://github.com/swagger-api/swagger-ui/tree/v3.13.0)
|
||||
3.0.21 | 2017-07-26 | 2.0 | [tag v3.0.21](https://github.com/swagger-api/swagger-ui/tree/v3.0.21)
|
||||
2.2.10 | 2017-01-04 | 1.1, 1.2, 2.0 | [tag v2.2.10](https://github.com/swagger-api/swagger-ui/tree/v2.2.10)
|
||||
2.1.5 | 2016-07-20 | 1.1, 1.2, 2.0 | [tag v2.1.5](https://github.com/swagger-api/swagger-ui/tree/v2.1.5)
|
||||
|
||||
Vendored
+14
-20
File diff suppressed because one or more lines are too long
Vendored
+1
-1
File diff suppressed because one or more lines are too long
Vendored
+3
-3
File diff suppressed because one or more lines are too long
+1
-1
File diff suppressed because one or more lines are too long
Vendored
+2
-1
File diff suppressed because one or more lines are too long
Vendored
+2
-2
File diff suppressed because one or more lines are too long
Vendored
+1
-1
File diff suppressed because one or more lines are too long
@@ -0,0 +1,43 @@
|
||||
# Plug points
|
||||
|
||||
Swagger-UI exposes most of its internal logic through the plugin system.
|
||||
|
||||
Often, it is beneficial to override the core internals to achieve custom behavior.
|
||||
|
||||
### Note: Semantic Versioning
|
||||
|
||||
Swagger-UI's internal APIs are _not_ part of our public contract, which means that they can change without the major version changing.
|
||||
|
||||
If your custom plugins wrap, extend, override, or consume any internal core APIs, we recommend specifying a specific minor version of Swagger-UI to use in your application, because they will _not_ change between patch versions.
|
||||
|
||||
If you're installing Swagger-UI via NPM, for example, you can do this by using a tilde:
|
||||
|
||||
```js
|
||||
{
|
||||
"dependencies": {
|
||||
"swagger-ui": "~3.11.0"
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
### `fn.opsFilter`
|
||||
|
||||
When using the `filter` option, tag names will be filtered by the user-provided value. If you'd like to customize this behavior, you can override the default `opsFilter` function.
|
||||
|
||||
For example, you can implement a multiple-phrase filter:
|
||||
|
||||
```js
|
||||
const MultiplePhraseFilterPlugin = function() {
|
||||
return {
|
||||
fn: {
|
||||
opsFilter: (taggedOps, phrase) => {
|
||||
const phrases = phrase.split(", ")
|
||||
|
||||
return taggedOps.filter((val, key) => {
|
||||
return phrases.some(item => key.indexOf(item) > -1)
|
||||
})
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
```
|
||||
@@ -2,6 +2,22 @@
|
||||
|
||||
A plugin is a function that returns an object - more specifically, the object may contain functions and components that augment and modify Swagger-UI's functionality.
|
||||
|
||||
### Note: Semantic Versioning
|
||||
|
||||
Swagger-UI's internal APIs are _not_ part of our public contract, which means that they can change without the major version changing.
|
||||
|
||||
If your custom plugins wrap, extend, override, or consume any internal core APIs, we recommend specifying a specific minor version of Swagger-UI to use in your application, because they will _not_ change between patch versions.
|
||||
|
||||
If you're installing Swagger-UI via NPM, for example, you can do this by using a tilde:
|
||||
|
||||
```js
|
||||
{
|
||||
"dependencies": {
|
||||
"swagger-ui": "~3.11.0"
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
### Format
|
||||
|
||||
A plugin return value may contain any of these keys, where `stateKey` is a name for a piece of state:
|
||||
|
||||
@@ -59,6 +59,7 @@ Parameter Name | Description
|
||||
`operationsSorter` | `Function=(a => a)`. Apply a sort to the operation list of each API. It can be 'alpha' (sort by paths alphanumerically), 'method' (sort by HTTP method) or a function (see Array.prototype.sort() to know how sort function works). Default is the order returned by the server unchanged.
|
||||
`showExtensions` | `Boolean=false`. Controls the display of vendor extension (`x-`) fields and values for Operations, Parameters, and Schema.
|
||||
`tagsSorter` | `Function=(a => a)`. Apply a sort to the tag list of each API. It can be 'alpha' (sort by paths alphanumerically) or a function (see [Array.prototype.sort()](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/sort) to learn how to write a sort function). Two tag name strings are passed to the sorter for each pass. Default is the order determined by Swagger-UI.
|
||||
`onComplete` | `Function=NOOP`. Provides a mechanism to be notified when Swagger-UI has finished rendering a newly provided definition.
|
||||
|
||||
##### Network
|
||||
|
||||
@@ -77,3 +78,11 @@ Parameter Name | Description
|
||||
--- | ---
|
||||
`modelPropertyMacro` | `Function`. Function to set default values to each property in model. Accepts one argument modelPropertyMacro(property), property is immutable
|
||||
`parameterMacro` | `Function`. Function to set default value to parameters. Accepts two arguments parameterMacro(operation, parameter). Operation and parameter are objects passed for context, both remain immutable
|
||||
|
||||
### Instance methods
|
||||
|
||||
Method Name | Description
|
||||
--- | ---
|
||||
`initOAuth` | `(configObj) => void`. Provide Swagger-UI with information about your OAuth server - see the OAuth2 documentation for more information.
|
||||
`preauthorizeBasic` | `(authDefinitionKey, username, password) => action`. Programmatically set values for a Basic authorization scheme.
|
||||
`preauthorizeApiKey` | `(authDefinitionKey, apiKeyValue) => action`. Programmatically set values for an API key authorization scheme.
|
||||
|
||||
@@ -1,7 +1,5 @@
|
||||
# OAuth2 configuration
|
||||
You can configure OAuth2 authorization by calling `initOAuth` method with passed configs under the instance of `SwaggerUIBundle`
|
||||
default `client_id` and `client_secret`, `realm`, an application name `appName`, `scopeSeparator`, `additionalQueryStringParams`,
|
||||
`useBasicAuthenticationWithAccessCodeGrant`.
|
||||
You can configure OAuth2 authorization by calling the `initOAuth` method.
|
||||
|
||||
Config Name | Description
|
||||
--- | ---
|
||||
@@ -11,7 +9,7 @@ realm | realm query parameter (for oauth1) added to `authorizationUrl` and `toke
|
||||
appName | application name, displayed in authorization popup. MUST be a string
|
||||
scopeSeparator | scope separator for passing scopes, encoded before calling, default value is a space (encoded value `%20`). MUST be a string
|
||||
additionalQueryStringParams | Additional query parameters added to `authorizationUrl` and `tokenUrl`. MUST be an object
|
||||
useBasicAuthenticationWithAccessCodeGrant | Only activated for the `accessCode` flow. During the `authorization_code` request to the `tokenUrl`, pass the [Client Password](https://tools.ietf.org/html/rfc6749#section-2.3.1) using the HTTP Basic Authentication scheme (`Authorization` header with `Basic base64encoded[client_id:client_secret]`). The default is `false`
|
||||
useBasicAuthenticationWithAccessCodeGrant | Only activated for the `accessCode` flow. During the `authorization_code` request to the `tokenUrl`, pass the [Client Password](https://tools.ietf.org/html/rfc6749#section-2.3.1) using the HTTP Basic Authentication scheme (`Authorization` header with `Basic base64encode(client_id + client_secret)`). The default is `false`
|
||||
|
||||
```javascript
|
||||
const ui = SwaggerUI({...})
|
||||
|
||||
+27
-28
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "swagger-ui",
|
||||
"version": "3.11.0",
|
||||
"version": "3.13.0",
|
||||
"main": "dist/swagger-ui.js",
|
||||
"repository": "git@github.com:swagger-api/swagger-ui.git",
|
||||
"contributors": [
|
||||
@@ -14,32 +14,31 @@
|
||||
],
|
||||
"license": "Apache-2.0",
|
||||
"scripts": {
|
||||
"build": "npm run build:core && npm run build:bundle && npm run build:standalone",
|
||||
"build:bundle": "webpack --config webpack-dist-bundle.config.js --colors",
|
||||
"build:core": "webpack --config webpack-dist.config.js --colors",
|
||||
"build:standalone": "webpack --config webpack-dist-standalone.config.js --colors",
|
||||
"deps:check": "npm run deps:license && npm run deps:size",
|
||||
"deps:license": "license-checker --production --csv --out $npm_package_config_deps_check_dir/licenses.csv && license-checker --development --csv --out $npm_package_config_deps_check_dir/licenses-dev.csv",
|
||||
"deps:size": "webpack -p --config webpack.check.js --json | webpack-bundle-size-analyzer >| $npm_package_config_deps_check_dir/sizes.txt",
|
||||
"dev": "npm-run-all --parallel hot-server open-localhost",
|
||||
"hot-server": "webpack-dev-server --host 0.0.0.0 --config webpack-hot-dev-server.config.js --inline --hot --progress --content-base dev-helpers/",
|
||||
"lint": "eslint --cache --ext '.js,.jsx' src test",
|
||||
"lint:errors": "eslint --cache --quiet --ext '.js,.jsx' src test",
|
||||
"lint:fix": "eslint --cache --ext '.js,.jsx' src test --fix",
|
||||
"open-localhost": "node -e 'require(\"open\")(\"http://localhost:3200\")'",
|
||||
"build": "npm run build-core && npm run build-bundle && npm run build-standalone",
|
||||
"build-bundle": "webpack --config webpack-dist-bundle.config.js --colors",
|
||||
"build-core": "webpack --config webpack-dist.config.js --colors",
|
||||
"build-standalone": "webpack --config webpack-dist-standalone.config.js --colors",
|
||||
"predev": "npm install",
|
||||
"test": "npm run lint:errors && npm run test:nodejs",
|
||||
"test:ci": "npm-run-all lint:errors test:nodejs test:ci:e2e",
|
||||
"test:browser": "karma start --config karma.conf.js",
|
||||
"test:ci:e2e": "if [ \"$ENABLE_CI_E2E\" = \"true\" ]; then npm-run-all --parallel -r test:e2e:mock-api test:e2e:all:cbt; else exit 0; fi",
|
||||
"test:coverage": "nyc npm run test:nodejs",
|
||||
"test:e2e": "npm-run-all --parallel -r hot-server test:e2e:mock-api test:e2e:all",
|
||||
"test:e2e:all": "sleep 3 && nightwatch test/e2e/scenarios/ --config test/e2e/nightwatch.json",
|
||||
"test:e2e:all:cbt": "sleep 3 && nightwatch test/e2e/scenarios/ --config test/e2e/nightwatch-cbt.json",
|
||||
"test:e2e:initial-render": "nightwatch test/e2e/scenarios/ --config test/e2e/nightwatch.json --group initial-render",
|
||||
"test:e2e:mock-api": "json-server --static test/e2e/specs --watch test/e2e/db.json --port 3204",
|
||||
"test:nodejs": "mocha --recursive --compilers js:babel-core/register test/core test/components test/bugs test/swagger-ui-dist-package test/xss",
|
||||
"watch": "webpack --config webpack-watch.config.js --watch --progress"
|
||||
"dev": "npm-run-all --parallel hot-server open-localhost",
|
||||
"watch": "webpack --config webpack-watch.config.js --watch --progress",
|
||||
"open-localhost": "node -e 'require(\"open\")(\"http://localhost:3200\")'",
|
||||
"hot-server": "webpack-dev-server --host 0.0.0.0 --config webpack-hot-dev-server.config.js --inline --hot --progress --content-base dev-helpers/",
|
||||
"deps-license": "license-checker --production --csv --out $npm_package_config_deps_check_dir/licenses.csv && license-checker --development --csv --out $npm_package_config_deps_check_dir/licenses-dev.csv",
|
||||
"deps-size": "webpack -p --config webpack.check.js --json | webpack-bundle-size-analyzer >| $npm_package_config_deps_check_dir/sizes.txt",
|
||||
"deps-check": "npm run deps-license && npm run deps-size",
|
||||
"lint": "eslint --cache --ext '.js,.jsx' src test",
|
||||
"lint-errors": "eslint --cache --quiet --ext '.js,.jsx' src test",
|
||||
"lint-fix": "eslint --cache --ext '.js,.jsx' src test --fix",
|
||||
"test": "npm run lint-errors && npm run just-test-in-node",
|
||||
"test-in-node": "npm run lint-errors && npm run just-test-in-node",
|
||||
"just-test": "karma start --config karma.conf.js",
|
||||
"just-test-in-node": "mocha --recursive --compilers js:babel-core/register test/core test/components test/bugs test/swagger-ui-dist-package test/xss",
|
||||
"just-check-coverage": "nyc npm run just-test-in-node",
|
||||
"test-e2e": "sleep 3 && nightwatch test/e2e/scenarios/ --config test/e2e/nightwatch.json",
|
||||
"e2e-initial-render": "nightwatch test/e2e/scenarios/ --config test/e2e/nightwatch.json --group initial-render",
|
||||
"mock-api": "json-server --watch test/e2e/db.json --port 3204",
|
||||
"hot-e2e-server": "webpack-dev-server --content-base test/e2e/helpers --host 0.0.0.0 --config webpack-hot-dev-server.config.js --inline --hot --progress",
|
||||
"e2e": "npm-run-all --parallel -r hot-e2e-server mock-api test-e2e"
|
||||
},
|
||||
"dependencies": {
|
||||
"@braintree/sanitize-url": "^2.0.2",
|
||||
@@ -85,7 +84,7 @@
|
||||
"scroll-to-element": "^2.0.0",
|
||||
"serialize-error": "2.0.0",
|
||||
"shallowequal": "0.2.2",
|
||||
"swagger-client": "^3.5.0",
|
||||
"swagger-client": "^3.5.1",
|
||||
"url-parse": "^1.1.8",
|
||||
"whatwg-fetch": "0.11.1",
|
||||
"worker-loader": "^0.7.1",
|
||||
@@ -106,7 +105,6 @@
|
||||
"babel-preset-react": "^6.23.0",
|
||||
"babel-preset-stage-0": "^6.22.0",
|
||||
"babel-runtime": "^6.23.0",
|
||||
"cbt_tunnels": "^0.3.0",
|
||||
"chromedriver": "^2.30.1",
|
||||
"copy-webpack-plugin": "^4.0.1",
|
||||
"css-loader": "0.28.4",
|
||||
@@ -147,6 +145,7 @@
|
||||
"standard": "^10.0.2",
|
||||
"standard-loader": "^6.0.1",
|
||||
"style-loader": "0.18.2",
|
||||
"tachyons-sass": "^4.9.2",
|
||||
"url-loader": "0.5.9",
|
||||
"webpack": "^2.6.1",
|
||||
"webpack-bundle-size-analyzer": "^2.5.0"
|
||||
|
||||
@@ -46,7 +46,7 @@ export default class ArrayModel extends Component {
|
||||
properties.size ? properties.entrySeq().map( ( [ key, v ] ) => <Property key={`${key}-${v}`} propKey={ key } propVal={ v } propStyle={ propStyle } />) : null
|
||||
}
|
||||
{
|
||||
!description ? null :
|
||||
!description ? (properties.size ? <div className="markdown"></div> : null) :
|
||||
<Markdown source={ description } />
|
||||
}
|
||||
<span>
|
||||
|
||||
@@ -81,11 +81,11 @@ export default class Auths extends React.Component {
|
||||
}).toArray()
|
||||
}
|
||||
<div className="auth-btn-wrapper">
|
||||
<Button className="btn modal-btn auth btn-done" onClick={ this.close }>Done</Button>
|
||||
{
|
||||
nonOauthDefinitions.size === authorizedAuth.size ? <Button className="btn modal-btn auth" onClick={ this.logoutClick }>Logout</Button>
|
||||
: <Button type="submit" className="btn modal-btn auth authorize">Authorize</Button>
|
||||
}
|
||||
<Button className="btn modal-btn auth btn-done" onClick={ this.close }>Close</Button>
|
||||
</div>
|
||||
</form>
|
||||
}
|
||||
|
||||
@@ -39,6 +39,13 @@ export default class Oauth2 extends React.Component {
|
||||
}
|
||||
}
|
||||
|
||||
close = (e) => {
|
||||
e.preventDefault()
|
||||
let { authActions } = this.props
|
||||
|
||||
authActions.showDefinitions(false)
|
||||
}
|
||||
|
||||
authorize =() => {
|
||||
let { authActions, errActions, getConfigs, authSelectors } = this.props
|
||||
let configs = getConfigs()
|
||||
@@ -231,6 +238,7 @@ export default class Oauth2 extends React.Component {
|
||||
: <Button className="btn modal-btn auth authorize" onClick={ this.authorize }>Authorize</Button>
|
||||
)
|
||||
}
|
||||
<Button className="btn modal-btn auth btn-done" onClick={ this.close }>Close</Button>
|
||||
</div>
|
||||
|
||||
</div>
|
||||
|
||||
@@ -5,7 +5,7 @@ import ImPropTypes from "react-immutable-proptypes"
|
||||
import { sanitizeUrl } from "core/utils"
|
||||
|
||||
|
||||
class Path extends React.Component {
|
||||
export class InfoBasePath extends React.Component {
|
||||
static propTypes = {
|
||||
host: PropTypes.string,
|
||||
basePath: PropTypes.string
|
||||
@@ -68,6 +68,17 @@ class License extends React.Component {
|
||||
}
|
||||
}
|
||||
|
||||
export class InfoUrl extends React.PureComponent {
|
||||
static propTypes = {
|
||||
url: PropTypes.string.isRequired
|
||||
}
|
||||
|
||||
render() {
|
||||
const { url } = this.props
|
||||
return <a target="_blank" href={ sanitizeUrl(url) }><span className="url"> { url } </span></a>
|
||||
}
|
||||
}
|
||||
|
||||
export default class Info extends React.Component {
|
||||
static propTypes = {
|
||||
info: PropTypes.object,
|
||||
@@ -90,6 +101,8 @@ export default class Info extends React.Component {
|
||||
|
||||
const Markdown = getComponent("Markdown")
|
||||
const VersionStamp = getComponent("VersionStamp")
|
||||
const InfoUrl = getComponent("InfoUrl")
|
||||
const InfoBasePath = getComponent("InfoBasePath")
|
||||
|
||||
return (
|
||||
<div className="info">
|
||||
@@ -97,8 +110,8 @@ export default class Info extends React.Component {
|
||||
<h2 className="title" >{ title }
|
||||
{ version && <VersionStamp version={version}></VersionStamp> }
|
||||
</h2>
|
||||
{ host || basePath ? <Path host={ host } basePath={ basePath } /> : null }
|
||||
{ url && <a target="_blank" href={ sanitizeUrl(url) }><span className="url"> { url } </span></a> }
|
||||
{ host || basePath ? <InfoBasePath host={ host } basePath={ basePath } /> : null }
|
||||
{ url && <InfoUrl url={url} /> }
|
||||
</hgroup>
|
||||
|
||||
<div className="description">
|
||||
|
||||
@@ -63,7 +63,7 @@ export default class Models extends Component {
|
||||
|
||||
const content = <ModelWrapper name={ name }
|
||||
expandDepth={ defaultModelsExpandDepth }
|
||||
schema={ schema }
|
||||
schema={ schema || Im.Map() }
|
||||
specPath={Im.List([...specPathBase, name])}
|
||||
getComponent={ getComponent }
|
||||
specSelectors={ specSelectors }
|
||||
|
||||
@@ -101,7 +101,7 @@ class ValidatorImage extends React.Component {
|
||||
if (this.state.error) {
|
||||
return <img alt={"Error"} />
|
||||
} else if (!this.state.loaded) {
|
||||
return <img alt= {"Loading..."} />
|
||||
return null
|
||||
}
|
||||
return <img src={this.props.src} alt={this.props.alt} />
|
||||
}
|
||||
|
||||
@@ -24,11 +24,18 @@ export default class ParameterRow extends Component {
|
||||
|
||||
let { specSelectors, pathMethod, param } = props
|
||||
let defaultValue = param.get("default")
|
||||
let xExampleValue = param.get("x-example")
|
||||
let parameter = specSelectors.parameterWithMeta(pathMethod, param.get("name"), param.get("in"))
|
||||
let value = parameter ? parameter.get("value") : ""
|
||||
if ( defaultValue !== undefined && value === undefined ) {
|
||||
this.onChangeWrapper(defaultValue)
|
||||
|
||||
if( param.get("in") !== "body" ) {
|
||||
if ( xExampleValue !== undefined && value === undefined && specSelectors.isSwagger2() ) {
|
||||
this.onChangeWrapper(xExampleValue)
|
||||
} else if ( defaultValue !== undefined && value === undefined ) {
|
||||
this.onChangeWrapper(defaultValue)
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
componentWillReceiveProps(props) {
|
||||
|
||||
@@ -46,6 +46,7 @@ const sanitizeOptions = {
|
||||
"td": [ "colspan" ],
|
||||
"*": [ "class" ]
|
||||
},
|
||||
allowedSchemesByTag: { img: [ "http", "https", "data" ] },
|
||||
textFilter: function(text) {
|
||||
return text.replace(/"/g, "\"")
|
||||
}
|
||||
|
||||
@@ -8,6 +8,8 @@ export default function() {
|
||||
afterLoad(system) {
|
||||
this.rootInjects = this.rootInjects || {}
|
||||
this.rootInjects.initOAuth = system.authActions.configureAuth
|
||||
this.rootInjects.preauthorizeApiKey = preauthorizeApiKey.bind(null, system)
|
||||
this.rootInjects.preauthorizeBasic = preauthorizeBasic.bind(null, system)
|
||||
},
|
||||
statePlugins: {
|
||||
auth: {
|
||||
@@ -21,3 +23,50 @@ export default function() {
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
export function preauthorizeBasic(system, key, username, password) {
|
||||
const {
|
||||
authActions: { authorize },
|
||||
specSelectors: { specJson, isOAS3 }
|
||||
} = system
|
||||
|
||||
const definitionBase = isOAS3() ? ["components", "securitySchemes"] : ["securityDefinitions"]
|
||||
|
||||
const schema = specJson().getIn([...definitionBase, key])
|
||||
|
||||
if(!schema) {
|
||||
return null
|
||||
}
|
||||
|
||||
return authorize({
|
||||
[key]: {
|
||||
value: {
|
||||
username,
|
||||
password,
|
||||
},
|
||||
schema: schema.toJS()
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
export function preauthorizeApiKey(system, key, value) {
|
||||
const {
|
||||
authActions: { authorize },
|
||||
specSelectors: { specJson, isOAS3 }
|
||||
} = system
|
||||
|
||||
const definitionBase = isOAS3() ? ["components", "securitySchemes"] : ["securityDefinitions"]
|
||||
|
||||
const schema = specJson().getIn([...definitionBase, key])
|
||||
|
||||
if(!schema) {
|
||||
return null
|
||||
}
|
||||
|
||||
return authorize({
|
||||
[key]: {
|
||||
value,
|
||||
schema: schema.toJS()
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
@@ -2,6 +2,7 @@
|
||||
|
||||
import { createSelector } from "reselect"
|
||||
import { Map } from "immutable"
|
||||
import win from "../window"
|
||||
|
||||
export default function downloadUrlPlugin (toolbox) {
|
||||
let { fn } = toolbox
|
||||
@@ -12,6 +13,7 @@ export default function downloadUrlPlugin (toolbox) {
|
||||
const config = getConfigs()
|
||||
url = url || specSelectors.url()
|
||||
specActions.updateLoadingStatus("loading")
|
||||
errActions.clear({source: "fetch"})
|
||||
fetch({
|
||||
url,
|
||||
loadSpec: true,
|
||||
@@ -26,7 +28,10 @@ export default function downloadUrlPlugin (toolbox) {
|
||||
function next(res) {
|
||||
if(res instanceof Error || res.status >= 400) {
|
||||
specActions.updateLoadingStatus("failed")
|
||||
return errActions.newThrownErr( new Error((res.message || res.statusText) + " " + url) )
|
||||
errActions.newThrownErr(Object.assign( new Error((res.message || res.statusText) + " " + url), {source: "fetch"}))
|
||||
// Check if the failure was possibly due to CORS or mixed content
|
||||
if (!res.status && res instanceof Error) checkPossibleFailReasons()
|
||||
return
|
||||
}
|
||||
specActions.updateLoadingStatus("success")
|
||||
specActions.updateSpec(res.text)
|
||||
@@ -35,6 +40,38 @@ export default function downloadUrlPlugin (toolbox) {
|
||||
}
|
||||
}
|
||||
|
||||
function checkPossibleFailReasons() {
|
||||
try {
|
||||
let specUrl
|
||||
|
||||
if("URL" in win ) {
|
||||
specUrl = new URL(url)
|
||||
} else {
|
||||
// legacy browser, use <a href> to parse the URL
|
||||
specUrl = document.createElement("a")
|
||||
specUrl.href = url
|
||||
}
|
||||
|
||||
if(specUrl.protocol !== "https:" && win.location.protocol === "https:") {
|
||||
const error = Object.assign(
|
||||
new Error(`Possible mixed-content issue? The page was loaded over https:// but a ${specUrl.protocol}// URL was specified. Check that you are not attempting to load mixed content.`),
|
||||
{source: "fetch"}
|
||||
)
|
||||
errActions.newThrownErr(error)
|
||||
return
|
||||
}
|
||||
if(specUrl.origin !== win.location.origin) {
|
||||
const error = Object.assign(
|
||||
new Error(`Possible cross-origin (CORS) issue? The URL origin (${specUrl.origin}) does not match the page (${win.location.origin}). Check the server returns the correct 'Access-Control-Allow-*' headers.`),
|
||||
{source: "fetch"}
|
||||
)
|
||||
errActions.newThrownErr(error)
|
||||
}
|
||||
} catch (e) {
|
||||
return
|
||||
}
|
||||
}
|
||||
|
||||
},
|
||||
|
||||
updateLoadingStatus: (status) => {
|
||||
|
||||
@@ -27,6 +27,7 @@ export default class RequestBodyEditor extends PureComponent {
|
||||
|
||||
this.state = {
|
||||
isEditBox: false,
|
||||
userDidModify: false,
|
||||
value: ""
|
||||
}
|
||||
}
|
||||
@@ -59,6 +60,11 @@ export default class RequestBodyEditor extends PureComponent {
|
||||
this.onChange(this.sample(explicitMediaType))
|
||||
}
|
||||
|
||||
resetValueToSample = (explicitMediaType) => {
|
||||
this.setState({ userDidModify: false })
|
||||
this.setValueToSample(explicitMediaType)
|
||||
}
|
||||
|
||||
sample = (explicitMediaType) => {
|
||||
let { requestBody, mediaType } = this.props
|
||||
let schema = requestBody.getIn(["content", explicitMediaType || mediaType, "schema"]).toJS()
|
||||
@@ -78,6 +84,7 @@ export default class RequestBodyEditor extends PureComponent {
|
||||
const isJson = /json/i.test(mediaType)
|
||||
const inputValue = isJson ? e.target.value.trim() : e.target.value
|
||||
|
||||
this.setState({ userDidModify: true })
|
||||
this.onChange(inputValue)
|
||||
}
|
||||
|
||||
@@ -87,13 +94,14 @@ export default class RequestBodyEditor extends PureComponent {
|
||||
let {
|
||||
isExecute,
|
||||
getComponent,
|
||||
mediaType,
|
||||
} = this.props
|
||||
|
||||
const Button = getComponent("Button")
|
||||
const TextArea = getComponent("TextArea")
|
||||
const HighlightCode = getComponent("highlightCode")
|
||||
|
||||
let { value, isEditBox } = this.state
|
||||
let { value, isEditBox, userDidModify } = this.state
|
||||
|
||||
return (
|
||||
<div className="body-param">
|
||||
@@ -104,14 +112,18 @@ export default class RequestBodyEditor extends PureComponent {
|
||||
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 className="body-param-edit">
|
||||
{
|
||||
!isExecute ? null
|
||||
: <Button className={isEditBox ? "btn cancel body-param__example-edit" : "btn edit body-param__example-edit"}
|
||||
onClick={this.toggleIsEditBox}>{ isEditBox ? "Cancel" : "Edit"}
|
||||
</Button>
|
||||
|
||||
}
|
||||
{ userDidModify &&
|
||||
<Button className="btn ml3" onClick={() => { this.resetValueToSample(mediaType) }}>Reset</Button>
|
||||
}
|
||||
</div>
|
||||
</div>
|
||||
|
||||
</div>
|
||||
|
||||
@@ -0,0 +1,28 @@
|
||||
let engaged = false
|
||||
|
||||
export default function() {
|
||||
|
||||
return {
|
||||
statePlugins: {
|
||||
spec: {
|
||||
wrapActions: {
|
||||
updateSpec: (ori) => (...args) => {
|
||||
engaged = true
|
||||
return ori(...args)
|
||||
},
|
||||
updateJsonSpec: (ori, system) => (...args) => {
|
||||
const cb = system.getConfigs().onComplete
|
||||
if(engaged && typeof cb === "function") {
|
||||
// call `onComplete` on next tick, which allows React to
|
||||
// reconcile the DOM before we notify the user
|
||||
setTimeout(cb, 0)
|
||||
engaged = false
|
||||
}
|
||||
|
||||
return ori(...args)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -29,6 +29,10 @@ export const sampleFromSchema = (schema, config={}) => {
|
||||
let { type, example, properties, additionalProperties, items } = objectify(schema)
|
||||
let { includeReadOnly, includeWriteOnly } = config
|
||||
|
||||
if(example && example.$$ref) {
|
||||
delete example.$$ref
|
||||
}
|
||||
|
||||
if(example !== undefined)
|
||||
return example
|
||||
|
||||
|
||||
@@ -13,6 +13,7 @@ import downloadUrlPlugin from "core/plugins/download-url"
|
||||
import configsPlugin from "core/plugins/configs"
|
||||
import deepLinkingPlugin from "core/plugins/deep-linking"
|
||||
import filter from "core/plugins/filter"
|
||||
import onComplete from "core/plugins/on-complete"
|
||||
|
||||
import OperationContainer from "core/containers/OperationContainer"
|
||||
|
||||
@@ -45,7 +46,10 @@ import Headers from "core/components/headers"
|
||||
import Errors from "core/components/errors"
|
||||
import ContentType from "core/components/content-type"
|
||||
import Overview from "core/components/overview"
|
||||
import Info from "core/components/info"
|
||||
import Info, {
|
||||
InfoUrl,
|
||||
InfoBasePath
|
||||
} from "core/components/info"
|
||||
import Footer from "core/components/footer"
|
||||
import ParamBody from "core/components/param-body"
|
||||
import Curl from "core/components/curl"
|
||||
@@ -124,7 +128,9 @@ export default function() {
|
||||
OperationExtRow,
|
||||
ParameterExt,
|
||||
OperationContainer,
|
||||
DeepLink
|
||||
DeepLink,
|
||||
InfoUrl,
|
||||
InfoBasePath
|
||||
}
|
||||
}
|
||||
|
||||
@@ -154,6 +160,7 @@ export default function() {
|
||||
SplitPaneModePlugin,
|
||||
downloadUrlPlugin,
|
||||
deepLinkingPlugin,
|
||||
filter
|
||||
filter,
|
||||
onComplete
|
||||
]
|
||||
}
|
||||
|
||||
+2
-2
@@ -350,7 +350,7 @@ export function extractFileNameFromContentDispositionHeader(value){
|
||||
if (responseFilename !== null && responseFilename.length > 1) {
|
||||
return responseFilename[1]
|
||||
}
|
||||
return null
|
||||
return null
|
||||
}
|
||||
|
||||
// PascalCase, aka UpperCamelCase
|
||||
@@ -559,7 +559,7 @@ export const validateParam = (param, isXml, isOAS3 = false) => {
|
||||
} else if ( type === "array" ) {
|
||||
let itemType
|
||||
|
||||
if ( !value.count() ) { return errors }
|
||||
if ( !listCheck || !value.count() ) { return errors }
|
||||
|
||||
itemType = paramDetails.getIn(["items", "type"])
|
||||
|
||||
|
||||
@@ -45,7 +45,10 @@ export default class Topbar extends React.Component {
|
||||
setSearch = (spec) => {
|
||||
let search = parseSearch()
|
||||
search["urls.primaryName"] = spec.name
|
||||
window.location.search = serializeSearch(search)
|
||||
const newUrl = `${window.location.protocol}//${window.location.host}${window.location.pathname}`
|
||||
if(window && window.history && window.history.pushState) {
|
||||
window.history.replaceState(null, "", `${newUrl}?${serializeSearch(search)}`)
|
||||
}
|
||||
}
|
||||
|
||||
setSelectedUrl = (selectedUrl) => {
|
||||
|
||||
@@ -21,6 +21,7 @@ export default class StandaloneLayout extends React.Component {
|
||||
let Container = getComponent("Container")
|
||||
let Row = getComponent("Row")
|
||||
let Col = getComponent("Col")
|
||||
let Errors = getComponent("errors", true)
|
||||
|
||||
const Topbar = getComponent("Topbar", true)
|
||||
const BaseLayout = getComponent("BaseLayout", true)
|
||||
@@ -45,8 +46,8 @@ export default class StandaloneLayout extends React.Component {
|
||||
<div className="info">
|
||||
<div className="loading-container">
|
||||
<h4 className="title">Failed to load API definition.</h4>
|
||||
<p>{lastErrMsg}</p>
|
||||
</div>
|
||||
<Errors/>
|
||||
</div>
|
||||
</div>
|
||||
}
|
||||
{ loadingStatus === "failedConfig" &&
|
||||
|
||||
@@ -21,6 +21,7 @@
|
||||
.authorize
|
||||
{
|
||||
padding-right: 20px;
|
||||
margin-right: 10px;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
.swagger-ui
|
||||
{
|
||||
@import '~tachyons-sass/tachyons.scss';
|
||||
@import 'mixins';
|
||||
@import 'variables';
|
||||
@import 'colors';
|
||||
|
||||
@@ -24,6 +24,18 @@ describe("Markdown component", function() {
|
||||
const el = render(<Markdown source={str} />)
|
||||
expect(el.html()).toEqual(`<div class="markdown"><p><img src="http://image.source" title="Image title"></p>\n</div>`)
|
||||
})
|
||||
|
||||
it("allows image elements with https scheme", function() {
|
||||
const str = ``
|
||||
const el = render(<Markdown source={str} />)
|
||||
expect(el.html()).toEqual(`<div class="markdown"><p><img src="https://image.source" title="Image title"></p>\n</div>`)
|
||||
})
|
||||
|
||||
it("allows image elements with data scheme", function() {
|
||||
const str = `<img src="data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAEAAAABCAYAAAAfFcSJAAAADUlEQVR42mNk+M9QDwADhgGAWjR9awAAAABJRU5ErkJggg==">`
|
||||
const el = render(<Markdown source={str} />)
|
||||
expect(el.html()).toEqual(`<div class="markdown"><p>` + str + `</p>\n</div>`)
|
||||
})
|
||||
|
||||
it("allows heading elements", function() {
|
||||
const str = `
|
||||
@@ -51,6 +63,18 @@ describe("Markdown component", function() {
|
||||
expect(el.html()).toEqual(`<div class="renderedMarkdown"><div><p><img src="http://image.source" title="Image title"></p></div></div>`)
|
||||
})
|
||||
|
||||
it("allows image elements with https scheme", function() {
|
||||
const str = ``
|
||||
const el = render(<OAS3Markdown source={str} />)
|
||||
expect(el.html()).toEqual(`<div class="renderedMarkdown"><div><p><img src="https://image.source" title="Image title"></p></div></div>`)
|
||||
})
|
||||
|
||||
it("allows image elements with data scheme", function() {
|
||||
const str = `<img src="data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAEAAAABCAYAAAAfFcSJAAAADUlEQVR42mNk+M9QDwADhgGAWjR9awAAAABJRU5ErkJggg==">`
|
||||
const el = render(<OAS3Markdown source={str} />)
|
||||
expect(el.html()).toEqual(`<div class="renderedMarkdown"><div>` + str + `</div></div>`)
|
||||
})
|
||||
|
||||
it("allows heading elements", function() {
|
||||
const str = `
|
||||
# h1
|
||||
|
||||
@@ -0,0 +1,154 @@
|
||||
/* eslint-env mocha */
|
||||
import expect from "expect"
|
||||
import { fromJS } from "immutable"
|
||||
import { preauthorizeBasic, preauthorizeApiKey } from "corePlugins/auth"
|
||||
import { authorize } from "corePlugins/auth/actions"
|
||||
|
||||
const S2_SYSTEM = {
|
||||
authActions: {
|
||||
authorize
|
||||
},
|
||||
specSelectors: {
|
||||
isOAS3: () => false,
|
||||
specJson: () => {
|
||||
return fromJS({
|
||||
swagger: "2.0",
|
||||
securityDefinitions: {
|
||||
"APIKeyHeader": {
|
||||
"type": "apiKey",
|
||||
"in": "header",
|
||||
"name": "X-API-Key"
|
||||
},
|
||||
"basicAuth": {
|
||||
"type": "basic"
|
||||
}
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
const OAI3_SYSTEM = {
|
||||
authActions: {
|
||||
authorize
|
||||
},
|
||||
specSelectors: {
|
||||
isOAS3: () => true,
|
||||
specJson: () => {
|
||||
return fromJS({
|
||||
openapi: "3.0.0",
|
||||
components: {
|
||||
securitySchemes: {
|
||||
basicAuth: {
|
||||
type: "http",
|
||||
scheme: "basic"
|
||||
},
|
||||
APIKeyHeader: {
|
||||
type: "apiKey",
|
||||
in: "header",
|
||||
name: "X-API-Key"
|
||||
}
|
||||
}
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
describe("auth plugin - preauthorizers", () => {
|
||||
describe("preauthorizeBasic", () => {
|
||||
it("should return a valid authorize action in Swagger 2", () => {
|
||||
const res = preauthorizeBasic(S2_SYSTEM, "basicAuth", "user", "pass")
|
||||
|
||||
expect(res).toEqual({
|
||||
type: "authorize",
|
||||
payload: {
|
||||
basicAuth: {
|
||||
schema: {
|
||||
type: "basic"
|
||||
},
|
||||
value: {
|
||||
username: "user",
|
||||
password: "pass"
|
||||
}
|
||||
}
|
||||
}
|
||||
})
|
||||
})
|
||||
it("should return a valid authorize action in OpenAPI 3", () => {
|
||||
const res = preauthorizeBasic(OAI3_SYSTEM, "basicAuth", "user", "pass")
|
||||
|
||||
expect(res).toEqual({
|
||||
type: "authorize",
|
||||
payload: {
|
||||
basicAuth: {
|
||||
schema: {
|
||||
type: "http",
|
||||
scheme: "basic"
|
||||
},
|
||||
value: {
|
||||
username: "user",
|
||||
password: "pass"
|
||||
}
|
||||
}
|
||||
}
|
||||
})
|
||||
})
|
||||
it("should return null when the authorization name is invalid in Swagger 2", () => {
|
||||
const res = preauthorizeBasic(S2_SYSTEM, "fakeBasicAuth", "user", "pass")
|
||||
|
||||
expect(res).toEqual(null)
|
||||
})
|
||||
it("should return null when the authorization name is invalid in OpenAPI 3", () => {
|
||||
const res = preauthorizeBasic(OAI3_SYSTEM, "fakeBasicAuth", "user", "pass")
|
||||
|
||||
expect(res).toEqual(null)
|
||||
})
|
||||
})
|
||||
describe("preauthorizeApiKey", () => {
|
||||
it("should return a valid authorize action in Swagger 2", () => {
|
||||
const res = preauthorizeApiKey(S2_SYSTEM, "APIKeyHeader", "Asdf1234")
|
||||
|
||||
expect(res).toEqual({
|
||||
type: "authorize",
|
||||
payload: {
|
||||
APIKeyHeader: {
|
||||
schema: {
|
||||
type: "apiKey",
|
||||
name: "X-API-Key",
|
||||
"in": "header"
|
||||
},
|
||||
value: "Asdf1234"
|
||||
}
|
||||
}
|
||||
})
|
||||
})
|
||||
it("should return a valid authorize action in OpenAPI 3", () => {
|
||||
const res = preauthorizeApiKey(OAI3_SYSTEM, "APIKeyHeader", "Asdf1234")
|
||||
|
||||
expect(res).toEqual({
|
||||
type: "authorize",
|
||||
payload: {
|
||||
APIKeyHeader: {
|
||||
schema: {
|
||||
type: "apiKey",
|
||||
"in": "header",
|
||||
name: "X-API-Key"
|
||||
},
|
||||
value: "Asdf1234"
|
||||
}
|
||||
}
|
||||
})
|
||||
})
|
||||
it("should return null when the authorization name is invalid in Swagger 2", () => {
|
||||
const res = preauthorizeApiKey(S2_SYSTEM, "FakeAPIKeyHeader", "Asdf1234")
|
||||
|
||||
expect(res).toEqual(null)
|
||||
})
|
||||
it("should return null when the authorization name is invalid in OpenAPI 3", () => {
|
||||
const res = preauthorizeApiKey(OAI3_SYSTEM, "FakeAPIKeyHeader", "Asdf1234")
|
||||
|
||||
expect(res).toEqual(null)
|
||||
})
|
||||
})
|
||||
})
|
||||
@@ -701,6 +701,36 @@ describe("bound system", function(){
|
||||
})
|
||||
})
|
||||
|
||||
describe("rootInjects", function() {
|
||||
it("should attach a rootInject function as an instance method", function() {
|
||||
// This is the same thing as the `afterLoad` tests, but is here for posterity
|
||||
|
||||
// Given
|
||||
const system = new System({
|
||||
plugins: [
|
||||
{
|
||||
afterLoad(system) {
|
||||
this.rootInjects.wow = system.dogeSelectors.wow
|
||||
},
|
||||
statePlugins: {
|
||||
doge: {
|
||||
selectors: {
|
||||
wow: () => (system) => {
|
||||
return "so selective"
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
]
|
||||
})
|
||||
|
||||
// When
|
||||
var res = system.getSystem().wow()
|
||||
expect(res).toEqual("so selective")
|
||||
})
|
||||
})
|
||||
|
||||
describe("error catching", function() {
|
||||
it("should encapsulate thrown errors in an afterLoad method", function() {
|
||||
// Given
|
||||
|
||||
@@ -1,32 +0,0 @@
|
||||
/* eslint-disable no-console */
|
||||
var cbt = require("cbt_tunnels")
|
||||
|
||||
|
||||
module.exports = {
|
||||
baseAppUrl: "http://swagger-ui-ci-asset-deployment-test.surge.sh",
|
||||
|
||||
// use rawgit.com to get test/e2e/specs/petstore.json from master
|
||||
// not a great solution, but CBT's proxy is too slow to fetch
|
||||
// the data directly.
|
||||
specPath: "https://rawgit.com/swagger-api/swagger-ui/master/test/e2e/specs/petstore.json",
|
||||
visibleTimeout: 10000,
|
||||
|
||||
before: function(done) {
|
||||
console.log("Starting up tunnel")
|
||||
cbt.start({
|
||||
username: process.env.CBT_USERNAME || "",
|
||||
authkey: process.env.CBT_AUTHKEY || ""
|
||||
}, function(err, data) {
|
||||
if (err) {
|
||||
done(err)
|
||||
} else {
|
||||
done(data)
|
||||
}
|
||||
})
|
||||
},
|
||||
after: function(done) {
|
||||
console.log("Closing Down Tunnel")
|
||||
cbt.stop()
|
||||
done()
|
||||
}
|
||||
}
|
||||
@@ -1,6 +0,0 @@
|
||||
var cbt = require("cbt_tunnels")
|
||||
|
||||
module.exports = {
|
||||
baseAppUrl: "http://localhost:3200",
|
||||
specPath: "http://localhost:3200/test-specs/petstore.json"
|
||||
}
|
||||
@@ -0,0 +1,111 @@
|
||||
<!-- HTML for dev server -->
|
||||
<!DOCTYPE html>
|
||||
<html lang="en">
|
||||
<head>
|
||||
<meta charset="UTF-8">
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1">
|
||||
<title>Swagger UI</title>
|
||||
<link href="https://fonts.googleapis.com/css?family=Open+Sans:400,700|Source+Code+Pro:300,600|Titillium+Web:400,600,700" rel="stylesheet">
|
||||
<link rel="stylesheet" type="text/css" href="./swagger-ui.css" >
|
||||
<link rel="icon" type="image/png" href="./favicon-32x32.png" sizes="32x32" />
|
||||
<link rel="icon" type="image/png" href="./favicon-16x16.png" sizes="16x16" />
|
||||
<style>
|
||||
html
|
||||
{
|
||||
box-sizing: border-box;
|
||||
overflow: -moz-scrollbars-vertical;
|
||||
overflow-y: scroll;
|
||||
}
|
||||
*,
|
||||
*:before,
|
||||
*:after
|
||||
{
|
||||
box-sizing: inherit;
|
||||
}
|
||||
body {
|
||||
margin:0;
|
||||
background: #fafafa;
|
||||
}
|
||||
</style>
|
||||
</head>
|
||||
|
||||
<body>
|
||||
|
||||
<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" style="position:absolute;width:0;height:0">
|
||||
<defs>
|
||||
<symbol viewBox="0 0 20 20" id="unlocked">
|
||||
<path d="M15.8 8H14V5.6C14 2.703 12.665 1 10 1 7.334 1 6 2.703 6 5.6V6h2v-.801C8 3.754 8.797 3 10 3c1.203 0 2 .754 2 2.199V8H4c-.553 0-1 .646-1 1.199V17c0 .549.428 1.139.951 1.307l1.197.387C5.672 18.861 6.55 19 7.1 19h5.8c.549 0 1.428-.139 1.951-.307l1.196-.387c.524-.167.953-.757.953-1.306V9.199C17 8.646 16.352 8 15.8 8z"></path>
|
||||
</symbol>
|
||||
|
||||
<symbol viewBox="0 0 20 20" id="locked">
|
||||
<path d="M15.8 8H14V5.6C14 2.703 12.665 1 10 1 7.334 1 6 2.703 6 5.6V8H4c-.553 0-1 .646-1 1.199V17c0 .549.428 1.139.951 1.307l1.197.387C5.672 18.861 6.55 19 7.1 19h5.8c.549 0 1.428-.139 1.951-.307l1.196-.387c.524-.167.953-.757.953-1.306V9.199C17 8.646 16.352 8 15.8 8zM12 8H8V5.199C8 3.754 8.797 3 10 3c1.203 0 2 .754 2 2.199V8z"/>
|
||||
</symbol>
|
||||
|
||||
<symbol viewBox="0 0 20 20" id="close">
|
||||
<path d="M14.348 14.849c-.469.469-1.229.469-1.697 0L10 11.819l-2.651 3.029c-.469.469-1.229.469-1.697 0-.469-.469-.469-1.229 0-1.697l2.758-3.15-2.759-3.152c-.469-.469-.469-1.228 0-1.697.469-.469 1.228-.469 1.697 0L10 8.183l2.651-3.031c.469-.469 1.228-.469 1.697 0 .469.469.469 1.229 0 1.697l-2.758 3.152 2.758 3.15c.469.469.469 1.229 0 1.698z"/>
|
||||
</symbol>
|
||||
|
||||
<symbol viewBox="0 0 20 20" id="large-arrow">
|
||||
<path d="M13.25 10L6.109 2.58c-.268-.27-.268-.707 0-.979.268-.27.701-.27.969 0l7.83 7.908c.268.271.268.709 0 .979l-7.83 7.908c-.268.271-.701.27-.969 0-.268-.269-.268-.707 0-.979L13.25 10z"/>
|
||||
</symbol>
|
||||
|
||||
<symbol viewBox="0 0 20 20" id="large-arrow-down">
|
||||
<path d="M17.418 6.109c.272-.268.709-.268.979 0s.271.701 0 .969l-7.908 7.83c-.27.268-.707.268-.979 0l-7.908-7.83c-.27-.268-.27-.701 0-.969.271-.268.709-.268.979 0L10 13.25l7.418-7.141z"/>
|
||||
</symbol>
|
||||
|
||||
|
||||
<symbol viewBox="0 0 24 24" id="jump-to">
|
||||
<path d="M19 7v4H5.83l3.58-3.59L8 6l-6 6 6 6 1.41-1.41L5.83 13H21V7z"/>
|
||||
</symbol>
|
||||
|
||||
<symbol viewBox="0 0 24 24" id="expand">
|
||||
<path d="M10 18h4v-2h-4v2zM3 6v2h18V6H3zm3 7h12v-2H6v2z"/>
|
||||
</symbol>
|
||||
|
||||
</defs>
|
||||
</svg>
|
||||
|
||||
<div id="swagger-ui"></div>
|
||||
|
||||
<script src="./swagger-ui-bundle.js"> </script>
|
||||
<script src="./swagger-ui-standalone-preset.js"> </script>
|
||||
<script>
|
||||
window.onload = function() {
|
||||
window["SwaggerUIBundle"] = window["swagger-ui-bundle"]
|
||||
window["SwaggerUIStandalonePreset"] = window["swagger-ui-standalone-preset"]
|
||||
// Build a system
|
||||
const ui = SwaggerUIBundle({
|
||||
url: "http://petstore.swagger.io/v2/swagger.json",
|
||||
dom_id: '#swagger-ui',
|
||||
presets: [
|
||||
SwaggerUIBundle.presets.apis,
|
||||
SwaggerUIStandalonePreset
|
||||
],
|
||||
plugins: [
|
||||
SwaggerUIBundle.plugins.DownloadUrl
|
||||
],
|
||||
layout: "StandaloneLayout",
|
||||
onComplete: () => {
|
||||
if(window.completeCount) {
|
||||
window.completeCount++
|
||||
} else {
|
||||
window.completeCount = 1
|
||||
}
|
||||
}
|
||||
})
|
||||
|
||||
window.ui = ui
|
||||
|
||||
ui.initOAuth({
|
||||
clientId: "your-client-id",
|
||||
clientSecret: "your-client-secret-if-required",
|
||||
realm: "your-realms",
|
||||
appName: "your-app-name",
|
||||
scopeSeparator: " ",
|
||||
additionalQueryStringParams: {}
|
||||
})
|
||||
}
|
||||
</script>
|
||||
</body>
|
||||
|
||||
</html>
|
||||
@@ -1,57 +0,0 @@
|
||||
{
|
||||
"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/e2e/cbt-globals.js",
|
||||
|
||||
"test_runner" : {
|
||||
"type" : "mocha",
|
||||
"options" : {
|
||||
"ui" : "bdd",
|
||||
"reporter" : "list"
|
||||
}
|
||||
},
|
||||
|
||||
"test_workers": {
|
||||
"enabled": true,
|
||||
"workers": 3
|
||||
},
|
||||
|
||||
"selenium" : {
|
||||
"start_process" : false,
|
||||
"server_path" : "",
|
||||
"log_path" : "",
|
||||
"host" : "127.0.0.1",
|
||||
"port" : 4444,
|
||||
"cli_args" : {
|
||||
"webdriver.chrome.driver" : "",
|
||||
"webdriver.ie.driver" : ""
|
||||
}
|
||||
},
|
||||
|
||||
"test_settings" : {
|
||||
"default" : {
|
||||
"launch_url" : "http://localhost",
|
||||
"selenium_port" : 80,
|
||||
"selenium_host" : "hub.crossbrowsertesting.com",
|
||||
"silent": true,
|
||||
"screenshots" : {
|
||||
"enabled" : false,
|
||||
"path" : ""
|
||||
},
|
||||
"username": "${CBT_USERNAME}",
|
||||
"access_key": "${CBT_AUTHKEY}",
|
||||
"desiredCapabilities": {
|
||||
"acceptSslCerts": "1",
|
||||
"browserName": "chrome",
|
||||
"javascriptEnabled": "1",
|
||||
"record_network" : "true",
|
||||
"record_video" : "true",
|
||||
"max_duration": 1200
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -5,7 +5,7 @@
|
||||
"custom_commands_path" : "",
|
||||
"custom_assertions_path" : "",
|
||||
"page_objects_path" : "test/e2e/pages",
|
||||
"globals_path" : "test/e2e/globals.js",
|
||||
"globals_path" : "",
|
||||
"test_workers" : {
|
||||
"enabled" : true,
|
||||
"workers" : "auto"
|
||||
@@ -60,4 +60,4 @@
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -20,7 +20,7 @@ module.exports = {
|
||||
version: {
|
||||
selector: ".version"
|
||||
},
|
||||
baseAppUrl: {
|
||||
baseUrl: {
|
||||
selector: ".base-url"
|
||||
},
|
||||
mainUrl: {
|
||||
|
||||
@@ -2,35 +2,35 @@ describe("render informationContainer", function () {
|
||||
let mainPage
|
||||
let informationContainer
|
||||
beforeEach(function (client, done) {
|
||||
|
||||
|
||||
mainPage = client
|
||||
.url(client.globals.baseAppUrl)
|
||||
.url("localhost:3200")
|
||||
.page.main()
|
||||
client.waitForElementVisible(".download-url-input", client.globals.visibleTimeout || 5000)
|
||||
.pause(client.globals.visibleTimeout || 5000)
|
||||
client.waitForElementVisible(".download-url-input", 5000)
|
||||
.pause(5000)
|
||||
.clearValue(".download-url-input")
|
||||
.setValue(".download-url-input", client.globals.specPath)
|
||||
.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(client.globals.visibleTimeout || 5000)
|
||||
mainPage.expect.section("@informationContainer").to.be.visible.before(5000)
|
||||
|
||||
client.end()
|
||||
})
|
||||
|
||||
it("renders content", function (client) {
|
||||
informationContainer.waitForElementVisible("@title", client.globals.visibleTimeout || 5000)
|
||||
informationContainer.waitForElementVisible("@title", 5000)
|
||||
.assert.containsText("@title", "Swagger Petstore")
|
||||
.assert.containsText("@version", "1.0.0")
|
||||
.assert.containsText("@baseAppUrl", "[ Base URL: localhost:3204/ ]")
|
||||
.assert.attributeEquals("@mainUrl", "href", client.globals.specPath)
|
||||
.assert.containsText("@mainUrlContent", client.globals.specPath)
|
||||
.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/")
|
||||
@@ -42,7 +42,7 @@ describe("render informationContainer", function () {
|
||||
.assert.containsText("@contactDevLink", "Contact the developer")
|
||||
.assert.attributeEquals("@aboutSwaggerLink", "href", "http://swagger.io/")
|
||||
.assert.containsText("@aboutSwaggerLink", "Find out more about Swagger")
|
||||
|
||||
|
||||
client.end()
|
||||
})
|
||||
})
|
||||
})
|
||||
@@ -3,12 +3,12 @@ describe("Render Model Wrapper", function () {
|
||||
|
||||
beforeEach(function (client, done) {
|
||||
mainPage = client
|
||||
.url(client.globals.baseAppUrl)
|
||||
.url("localhost:3200")
|
||||
.page.main()
|
||||
client.waitForElementVisible(".download-url-input", client.globals.visibleTimeout || 5000)
|
||||
.pause(client.globals.visibleTimeout || 5000)
|
||||
client.waitForElementVisible(".download-url-input", 5000)
|
||||
.pause(5000)
|
||||
.clearValue(".download-url-input")
|
||||
.setValue(".download-url-input", client.globals.specPath)
|
||||
.setValue(".download-url-input", "http://localhost:3200/test-specs/petstore.json")
|
||||
.click("button.download-url-button")
|
||||
.pause(1000)
|
||||
|
||||
@@ -20,13 +20,13 @@ describe("Render Model Wrapper", function () {
|
||||
done()
|
||||
})
|
||||
it("Render model wrapper", function(client){
|
||||
mainPage.expect.section("@modelWrapper").to.be.visible.before(client.globals.visibleTimeout || 5000)
|
||||
mainPage.expect.section("@modelWrapper").to.be.visible.before(5000)
|
||||
|
||||
client.end()
|
||||
})
|
||||
|
||||
it("Render model wrapper collapse", function(client){
|
||||
modelWrapper.waitForElementVisible("@modelContainer", client.globals.visibleTimeout || 5000)
|
||||
modelWrapper.waitForElementVisible("@modelContainer", 5000)
|
||||
.click("@modelCollapse")
|
||||
.assert.cssClassNotPresent("@modelContainer", "is-open")
|
||||
|
||||
|
||||
@@ -0,0 +1,22 @@
|
||||
const expect = require("expect")
|
||||
|
||||
describe("onComplete option", function () {
|
||||
let mainPage
|
||||
beforeEach(function (client, done) {
|
||||
mainPage = client
|
||||
.url("localhost:3200")
|
||||
.page.main()
|
||||
|
||||
client.waitForElementVisible(".opblock-tag-section", 5000)
|
||||
done()
|
||||
})
|
||||
|
||||
it("triggers the page-provided onComplete exactly 1 times", function (client, done) {
|
||||
client.execute(function() {
|
||||
return window.completeCount
|
||||
}, [], (result) => {
|
||||
expect(result.value).toEqual(1)
|
||||
client.end()
|
||||
})
|
||||
})
|
||||
})
|
||||
@@ -3,13 +3,13 @@ describe("render pet api container", function () {
|
||||
let apiWrapper
|
||||
beforeEach(function (client, done) {
|
||||
mainPage = client
|
||||
.url(client.globals.baseAppUrl)
|
||||
.url("localhost:3200")
|
||||
.page.main()
|
||||
|
||||
client.waitForElementVisible(".download-url-input", client.globals.visibleTimeout || 5000)
|
||||
.pause(client.globals.visibleTimeout || 5000)
|
||||
client.waitForElementVisible(".download-url-input", 5000)
|
||||
.pause(5000)
|
||||
.clearValue(".download-url-input")
|
||||
.setValue(".download-url-input", client.globals.specPath)
|
||||
.setValue(".download-url-input", "http://localhost:3200/test-specs/petstore.json")
|
||||
.click("button.download-url-button")
|
||||
.pause(1000)
|
||||
|
||||
@@ -25,13 +25,13 @@ describe("render pet api container", function () {
|
||||
client.end()
|
||||
})
|
||||
it("test rendered pet container", function (client) {
|
||||
apiWrapper.waitForElementVisible("@petAPIWrapper", client.globals.visibleTimeout || 5000)
|
||||
apiWrapper.waitForElementVisible("@petAPIWrapper", 5000)
|
||||
.expect.element("@petAPIWrapper").to.be.visible
|
||||
|
||||
client.end()
|
||||
})
|
||||
it("collapse pet wrapper", function (client) {
|
||||
apiWrapper.waitForElementVisible("@petAPIWrapper", client.globals.visibleTimeout || 5000)
|
||||
apiWrapper.waitForElementVisible("@petAPIWrapper", 5000)
|
||||
.click("@petAPIWrapperBar")
|
||||
.assert.cssClassNotPresent("@petAPIWrapper", "is-open")
|
||||
|
||||
@@ -41,7 +41,7 @@ describe("render pet api container", function () {
|
||||
apiWrapper.waitForElementVisible("@petOperationPostContainer", 10000)
|
||||
.assert.containsText("@petOperationPostTitle", "/pet")
|
||||
.click("@petOperationPostCollpase")
|
||||
.waitForElementVisible("@petOperationPostCollapseContainer", client.globals.visibleTimeout || 5000)
|
||||
.waitForElementVisible("@petOperationPostCollapseContainer", 5000)
|
||||
.click("@petOperationPostTryBtn")
|
||||
.waitForElementVisible("@petOperationPostTryText", 1000)
|
||||
.waitForElementVisible("@petOperationPostExecuteBtn", 1000)
|
||||
@@ -52,9 +52,9 @@ describe("render pet api container", function () {
|
||||
})
|
||||
|
||||
it("Testing post /pet api Mock data", function (client) {
|
||||
apiWrapper.waitForElementVisible("@petOperationPostContainer", client.globals.visibleTimeout || 5000)
|
||||
apiWrapper.waitForElementVisible("@petOperationPostContainer", 5000)
|
||||
.click("@petOperationPostCollpase")
|
||||
.waitForElementVisible("@petOperationPostCollapseContainer", client.globals.visibleTimeout || 5000)
|
||||
.waitForElementVisible("@petOperationPostCollapseContainer", 5000)
|
||||
.click("@petOperationPostTryBtn")
|
||||
.waitForElementVisible("@petOperationPostExecuteBtn", 1000)
|
||||
.click("@petOperationPostExecuteBtn")
|
||||
@@ -72,7 +72,7 @@ describe("render pet api container", function () {
|
||||
})
|
||||
|
||||
it("render put /pet api container", function (client) {
|
||||
apiWrapper.waitForElementVisible("@petOperationPutContainer", client.globals.visibleTimeout || 5000)
|
||||
apiWrapper.waitForElementVisible("@petOperationPutContainer", 5000)
|
||||
.assert.containsText("@petOperationPutTitle", "/pet")
|
||||
.click("@petOperationPutCollpase")
|
||||
.waitForElementVisible("@petOperationPutCollapseContainer", 3000)
|
||||
@@ -86,7 +86,7 @@ describe("render pet api container", function () {
|
||||
})
|
||||
|
||||
it("Testing put /pet api Mock data", function (client) {
|
||||
apiWrapper.waitForElementVisible("@petOperationPutContainer", client.globals.visibleTimeout || 5000)
|
||||
apiWrapper.waitForElementVisible("@petOperationPutContainer", 5000)
|
||||
.click("@petOperationPutCollpase")
|
||||
.waitForElementVisible("@petOperationPutCollapseContainer", 3000)
|
||||
.click("@petOperationPutTryBtn")
|
||||
@@ -106,7 +106,7 @@ describe("render pet api container", function () {
|
||||
})
|
||||
|
||||
it("render get by tag /pet api container", function (client) {
|
||||
apiWrapper.waitForElementVisible("@petOperationGetByTagContainer", client.globals.visibleTimeout || 5000)
|
||||
apiWrapper.waitForElementVisible("@petOperationGetByTagContainer", 5000)
|
||||
.assert.containsText("@petOperationGetByTagTitle", "/pet/findByTags")
|
||||
.click("@petOperationGetByTagCollpase")
|
||||
.waitForElementVisible("@petOperationGetByTagCollapseContainer", 3000)
|
||||
@@ -120,7 +120,7 @@ describe("render pet api container", function () {
|
||||
})
|
||||
|
||||
it("Testing get by tag /pet api Mock data", function (client) {
|
||||
apiWrapper.waitForElementVisible("@petOperationGetByTagContainer", client.globals.visibleTimeout || 5000)
|
||||
apiWrapper.waitForElementVisible("@petOperationGetByTagContainer", 5000)
|
||||
.click("@petOperationGetByTagCollpase")
|
||||
.waitForElementVisible("@petOperationGetByTagCollapseContainer", 3000)
|
||||
.click("@petOperationGetByTagTryBtn")
|
||||
@@ -140,7 +140,7 @@ describe("render pet api container", function () {
|
||||
})
|
||||
|
||||
it("render get by ID /pet/{petId} api container", function (client) {
|
||||
apiWrapper.waitForElementVisible("@petOperationGetByIdContainer", client.globals.visibleTimeout || 5000)
|
||||
apiWrapper.waitForElementVisible("@petOperationGetByIdContainer", 5000)
|
||||
.assert.containsText("@petOperationGetByIdTitle", "/pet/{petId}")
|
||||
.click("@petOperationGetByIdCollpase")
|
||||
.waitForElementVisible("@petOperationGetByIdCollapseContainer", 3000)
|
||||
@@ -153,7 +153,7 @@ describe("render pet api container", function () {
|
||||
})
|
||||
|
||||
it("render get by ID /pet/{petId} api Mock data", function (client) {
|
||||
apiWrapper.waitForElementVisible("@petOperationGetByIdContainer", client.globals.visibleTimeout || 5000)
|
||||
apiWrapper.waitForElementVisible("@petOperationGetByIdContainer", 5000)
|
||||
.assert.containsText("@petOperationGetByIdTitle", "/pet/{petId}")
|
||||
.click("@petOperationGetByIdCollpase")
|
||||
.waitForElementVisible("@petOperationGetByIdCollapseContainer", 3000)
|
||||
|
||||
@@ -3,13 +3,13 @@ describe("render store api container", function(){
|
||||
let apiWrapper
|
||||
beforeEach( function(client, done){
|
||||
mainPage = client
|
||||
.url(client.globals.baseAppUrl)
|
||||
.url("localhost:3200")
|
||||
.page.main()
|
||||
|
||||
client.waitForElementVisible(".download-url-input", client.globals.visibleTimeout || 5000)
|
||||
client.waitForElementVisible(".download-url-input", 5000)
|
||||
.pause(3000)
|
||||
.clearValue(".download-url-input")
|
||||
.setValue(".download-url-input", client.globals.specPath)
|
||||
.setValue(".download-url-input", "http://localhost:3200/test-specs/petstore.json")
|
||||
.click("button.download-url-button")
|
||||
.pause(1000)
|
||||
|
||||
@@ -21,23 +21,23 @@ describe("render store api container", function(){
|
||||
done()
|
||||
})
|
||||
it("test rendered store container", function(client){
|
||||
apiWrapper.waitForElementVisible("@storeAPIWrapper", client.globals.visibleTimeout || 5000)
|
||||
apiWrapper.waitForElementVisible("@storeAPIWrapper", 5000)
|
||||
.expect.element("@storeAPIWrapper").to.be.visible
|
||||
|
||||
client.end()
|
||||
})
|
||||
it("callapse store wrapper", function(client){
|
||||
apiWrapper.waitForElementVisible("@storeAPIWrapper", client.globals.visibleTimeout || 5000)
|
||||
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", client.globals.visibleTimeout || 5000)
|
||||
apiWrapper.waitForElementVisible("@storeOperationGetContainer", 5000)
|
||||
.assert.containsText("@storeOperationGetTitle", "/store/inventory")
|
||||
.click("@storeOperationGetCollpase")
|
||||
.waitForElementVisible("@storeOperationGetCollapseContainer", client.globals.visibleTimeout || 5000)
|
||||
.waitForElementVisible("@storeOperationGetCollapseContainer", 5000)
|
||||
.click("@storeOperationGetTryBtn")
|
||||
.waitForElementVisible("@storeOperationGetExecuteBtn", 1000)
|
||||
.click("@storeOperationGetTryBtn")
|
||||
@@ -47,7 +47,7 @@ describe("render store api container", function(){
|
||||
})
|
||||
|
||||
it("Testing get /store/inventory api Mock data ", function (client) {
|
||||
apiWrapper.waitForElementVisible("@storeOperationGetContainer", client.globals.visibleTimeout || 5000)
|
||||
apiWrapper.waitForElementVisible("@storeOperationGetContainer", 5000)
|
||||
.assert.containsText("@storeOperationGetTitle", "/store/inventory")
|
||||
.click("@storeOperationGetCollpase")
|
||||
.waitForElementVisible("@storeOperationGetCollapseContainer", 3000)
|
||||
|
||||
@@ -3,13 +3,13 @@ describe("render user api container", function(){
|
||||
let apiWrapper
|
||||
beforeEach( function(client, done){
|
||||
mainPage = client
|
||||
.url(client.globals.baseAppUrl)
|
||||
.url("localhost:3200")
|
||||
.page.main()
|
||||
|
||||
client.waitForElementVisible(".download-url-input", client.globals.visibleTimeout || 5000)
|
||||
.pause(client.globals.visibleTimeout || 5000)
|
||||
client.waitForElementVisible(".download-url-input", 5000)
|
||||
.pause(5000)
|
||||
.clearValue(".download-url-input")
|
||||
.setValue(".download-url-input", client.globals.specPath)
|
||||
.setValue(".download-url-input", "http://localhost:3200/test-specs/petstore.json")
|
||||
.click("button.download-url-button")
|
||||
.pause(1000)
|
||||
|
||||
@@ -21,20 +21,20 @@ describe("render user api container", function(){
|
||||
done()
|
||||
})
|
||||
it("test rendered user container", function(client){
|
||||
apiWrapper.waitForElementVisible("@userAPIWrapper", client.globals.visibleTimeout || 5000)
|
||||
apiWrapper.waitForElementVisible("@userAPIWrapper", 5000)
|
||||
.expect.element("@userAPIWrapper").to.be.visible
|
||||
|
||||
client.end()
|
||||
})
|
||||
it("callapse user wrapper", function(client){
|
||||
apiWrapper.waitForElementVisible("@userAPIWrapper", client.globals.visibleTimeout || 5000)
|
||||
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", client.globals.visibleTimeout || 5000)
|
||||
apiWrapper.waitForElementVisible("@userOperationPutContainer", 5000)
|
||||
.assert.containsText("@userOperationPutTitle", "/user/{username}")
|
||||
.click("@userOperationPutCollpase")
|
||||
.waitForElementVisible("@userOperationPutCollapseContainer", 3000)
|
||||
@@ -46,7 +46,7 @@ describe("render user api container", function(){
|
||||
client.end()
|
||||
})
|
||||
it("Test put /user/{username} api Mock data", function (client) {
|
||||
apiWrapper.waitForElementVisible("@userOperationPutContainer", client.globals.visibleTimeout || 5000)
|
||||
apiWrapper.waitForElementVisible("@userOperationPutContainer", 5000)
|
||||
.assert.containsText("@userOperationPutTitle", "/user/{username}")
|
||||
.click("@userOperationPutCollpase")
|
||||
.waitForElementVisible("@userOperationPutCollapseContainer", 3000)
|
||||
@@ -63,7 +63,7 @@ describe("render user api container", function(){
|
||||
client.end()
|
||||
})
|
||||
it("render delete /user/{username} api container", function (client) {
|
||||
apiWrapper.waitForElementVisible("@userOperationDeleteContainer", client.globals.visibleTimeout || 5000)
|
||||
apiWrapper.waitForElementVisible("@userOperationDeleteContainer", 5000)
|
||||
.assert.containsText("@userOperationDeleteTitle", "/user/{username}")
|
||||
.click("@userOperationDeleteCollpase")
|
||||
.waitForElementVisible("@userOperationDeleteCollapseContainer", 3000)
|
||||
@@ -75,7 +75,7 @@ describe("render user api container", function(){
|
||||
client.end()
|
||||
})
|
||||
it("Test delete /user/{username} api Mock data", function (client) {
|
||||
apiWrapper.waitForElementVisible("@userOperationDeleteContainer", client.globals.visibleTimeout || 5000)
|
||||
apiWrapper.waitForElementVisible("@userOperationDeleteContainer", 5000)
|
||||
.assert.containsText("@userOperationDeleteTitle", "/user/{username}")
|
||||
.click("@userOperationDeleteCollpase")
|
||||
.waitForElementVisible("@userOperationDeleteCollapseContainer", 3000)
|
||||
|
||||
@@ -4,15 +4,15 @@ describe("Render scheme", function () {
|
||||
beforeEach(function (client, done) {
|
||||
|
||||
mainPage = client
|
||||
.url(client.globals.baseAppUrl)
|
||||
.url("localhost:3200")
|
||||
.page.main()
|
||||
|
||||
schemeContainer = mainPage.section.schemeContainer
|
||||
|
||||
client.waitForElementVisible(".download-url-input", client.globals.visibleTimeout || 5000)
|
||||
.pause(client.globals.visibleTimeout || 5000)
|
||||
client.waitForElementVisible(".download-url-input", 5000)
|
||||
.pause(5000)
|
||||
.clearValue(".download-url-input")
|
||||
.setValue(".download-url-input", client.globals.specPath)
|
||||
.setValue(".download-url-input", "http://localhost:3200/test-specs/petstore.json")
|
||||
.click("button.download-url-button")
|
||||
.pause(1000)
|
||||
|
||||
@@ -21,25 +21,25 @@ describe("Render scheme", function () {
|
||||
})
|
||||
|
||||
it("render section", function (client) {
|
||||
mainPage.expect.section("@schemeContainer").to.be.visible.before(client.globals.visibleTimeout || 5000)
|
||||
mainPage.expect.section("@schemeContainer").to.be.visible.before(5000)
|
||||
|
||||
client.end()
|
||||
})
|
||||
it("render scheme option", function (client) {
|
||||
schemeContainer.waitForElementVisible("@httpOption", client.globals.visibleTimeout || 5000)
|
||||
schemeContainer.waitForElementVisible("@httpOption", 5000)
|
||||
.expect.element("@httpOption").to.be.selected
|
||||
|
||||
client.end()
|
||||
})
|
||||
|
||||
it("render authorized button", function (client) {
|
||||
schemeContainer.waitForElementVisible("@btnAuthorize", client.globals.visibleTimeout || 5000)
|
||||
schemeContainer.waitForElementVisible("@btnAuthorize", 5000)
|
||||
.expect.element("@btnAuthorize").to.be.visible
|
||||
|
||||
client.end()
|
||||
})
|
||||
it("render click event", function(client) {
|
||||
schemeContainer.waitForElementVisible("@btnAuthorize", client.globals.visibleTimeout || 5000)
|
||||
schemeContainer.waitForElementVisible("@btnAuthorize", 5000)
|
||||
.click("@btnAuthorize")
|
||||
.assert.visible("@authorizationModal")
|
||||
.assert.containsText("@appName", "Application: your-app-name")
|
||||
@@ -49,4 +49,4 @@ describe("Render scheme", function () {
|
||||
|
||||
client.end()
|
||||
})
|
||||
})
|
||||
})
|
||||
@@ -18,15 +18,15 @@ describe("initial render", function () {
|
||||
|
||||
beforeEach(function (client, done) {
|
||||
mainPage = client
|
||||
.url(client.globals.baseAppUrl)
|
||||
.url("localhost:3200")
|
||||
.page.main()
|
||||
|
||||
topbar = mainPage.section.topbar
|
||||
|
||||
client.waitForElementVisible(".download-url-input", 10000)
|
||||
.pause(client.globals.visibleTimeout || 5000)
|
||||
.pause(5000)
|
||||
.clearValue(".download-url-input")
|
||||
.setValue(".download-url-input", client.globals.specPath)
|
||||
.setValue(".download-url-input", "http://localhost:3200/test-specs/petstore.json")
|
||||
.click("button.download-url-button")
|
||||
.pause(1000)
|
||||
|
||||
|
||||
@@ -63,7 +63,6 @@ module.exports = require("./make-webpack-config")(rules, {
|
||||
},
|
||||
devServer: {
|
||||
port: 3200,
|
||||
contentBase: path.join(__dirname, "dev-helpers"),
|
||||
publicPath: "/",
|
||||
noInfo: true,
|
||||
hot: true,
|
||||
|
||||
Reference in New Issue
Block a user