Merge branch 'master' into ft/3052-extensions
This commit is contained in:
@@ -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.4.4 | 2017-11-03 | 2.0, 3.0 | [tag v3.4.4](https://github.com/swagger-api/swagger-ui/tree/v3.4.4)
|
||||
3.4.5 | 2017-11-03 | 2.0, 3.0 | [tag v3.4.5](https://github.com/swagger-api/swagger-ui/tree/v3.4.5)
|
||||
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)
|
||||
|
||||
126
dist/swagger-ui-bundle.js
vendored
126
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
File diff suppressed because one or more lines are too long
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
File diff suppressed because one or more lines are too long
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
File diff suppressed because one or more lines are too long
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "swagger-ui",
|
||||
"version": "3.4.4",
|
||||
"version": "3.4.5",
|
||||
"main": "dist/swagger-ui.js",
|
||||
"repository": "git@github.com:swagger-api/swagger-ui.git",
|
||||
"contributors": [
|
||||
@@ -45,6 +45,7 @@
|
||||
"brace": "0.7.0",
|
||||
"classnames": "^2.2.5",
|
||||
"commonmark": "^0.28.1",
|
||||
"core-js": "^2.5.1",
|
||||
"css.escape": "1.5.1",
|
||||
"deep-extend": "0.4.1",
|
||||
"expect": "1.20.2",
|
||||
@@ -80,7 +81,7 @@
|
||||
"scroll-to-element": "^2.0.0",
|
||||
"serialize-error": "2.0.0",
|
||||
"shallowequal": "0.2.2",
|
||||
"swagger-client": "^3.3.3",
|
||||
"swagger-client": "^3.3.4",
|
||||
"url-parse": "^1.1.8",
|
||||
"whatwg-fetch": "0.11.1",
|
||||
"worker-loader": "^0.7.1",
|
||||
|
||||
@@ -60,6 +60,9 @@ export default class ApiKeyAuth extends React.Component {
|
||||
<Row>
|
||||
<Markdown source={ schema.get("description") } />
|
||||
</Row>
|
||||
<Row>
|
||||
<p>Name: <code>{ schema.get("name") }</code></p>
|
||||
</Row>
|
||||
<Row>
|
||||
<p>In: <code>{ schema.get("in") }</code></p>
|
||||
</Row>
|
||||
|
||||
@@ -27,6 +27,16 @@ export default class ContentType extends React.Component {
|
||||
}
|
||||
}
|
||||
|
||||
componentWillReceiveProps(nextProps) {
|
||||
if(!nextProps.contentTypes || !nextProps.contentTypes.size) {
|
||||
return
|
||||
}
|
||||
|
||||
if(!nextProps.contentTypes.includes(nextProps.value)) {
|
||||
nextProps.onChange(nextProps.contentTypes.first())
|
||||
}
|
||||
}
|
||||
|
||||
onChangeWrapper = e => this.props.onChange(e.target.value)
|
||||
|
||||
render() {
|
||||
|
||||
@@ -8,7 +8,6 @@ export default class Execute extends Component {
|
||||
specActions: PropTypes.object.isRequired,
|
||||
operation: PropTypes.object.isRequired,
|
||||
path: PropTypes.string.isRequired,
|
||||
getComponent: PropTypes.func.isRequired,
|
||||
method: PropTypes.string.isRequired,
|
||||
onExecute: PropTypes.func
|
||||
}
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
import React from "react"
|
||||
import PropTypes from "prop-types"
|
||||
import ImPropTypes from "react-immutable-proptypes"
|
||||
import { Iterable } from "immutable"
|
||||
|
||||
const Headers = ( { headers } )=>{
|
||||
return (
|
||||
@@ -28,19 +29,29 @@ 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,
|
||||
response: PropTypes.instanceOf(Iterable).isRequired,
|
||||
path: PropTypes.string.isRequired,
|
||||
method: PropTypes.string.isRequired,
|
||||
displayRequestDuration: PropTypes.bool.isRequired,
|
||||
specSelectors: PropTypes.object.isRequired,
|
||||
getComponent: PropTypes.func.isRequired,
|
||||
getConfigs: PropTypes.func.isRequired
|
||||
}
|
||||
|
||||
shouldComponentUpdate(nextProps) {
|
||||
// BUG: props.response is always coming back as a new Immutable instance
|
||||
// same issue as responses.jsx (tryItOutResponse)
|
||||
return this.props.response !== nextProps.response
|
||||
|| this.props.path !== nextProps.path
|
||||
|| this.props.method !== nextProps.method
|
||||
|| this.props.displayRequestDuration !== nextProps.displayRequestDuration
|
||||
}
|
||||
|
||||
render() {
|
||||
const { response, getComponent, getConfigs, displayRequestDuration, specSelectors, pathMethod } = this.props
|
||||
const { response, getComponent, getConfigs, displayRequestDuration, specSelectors, path, method } = this.props
|
||||
const { showMutatedRequest } = getConfigs()
|
||||
|
||||
const curlRequest = showMutatedRequest ? specSelectors.mutatedRequestFor(pathMethod[0], pathMethod[1]) : specSelectors.requestFor(pathMethod[0], pathMethod[1])
|
||||
const curlRequest = showMutatedRequest ? specSelectors.mutatedRequestFor(path, method) : specSelectors.requestFor(path, method)
|
||||
const status = response.get("status")
|
||||
const url = response.get("url")
|
||||
const headers = response.get("headers").toJS()
|
||||
@@ -118,7 +129,6 @@ export default class LiveResponse extends React.Component {
|
||||
|
||||
static propTypes = {
|
||||
getComponent: PropTypes.func.isRequired,
|
||||
request: ImPropTypes.map,
|
||||
response: ImPropTypes.map
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,32 +1,22 @@
|
||||
import React, { PureComponent } from "react"
|
||||
import PropTypes from "prop-types"
|
||||
import { getList } from "core/utils"
|
||||
import * as CustomPropTypes from "core/proptypes"
|
||||
import { getExtensions, sanitizeUrl } from "core/utils"
|
||||
|
||||
//import "less/opblock"
|
||||
import { Iterable } from "immutable"
|
||||
|
||||
export default class Operation extends PureComponent {
|
||||
static propTypes = {
|
||||
path: PropTypes.string.isRequired,
|
||||
method: PropTypes.string.isRequired,
|
||||
operation: PropTypes.object.isRequired,
|
||||
showSummary: PropTypes.bool,
|
||||
isShown: PropTypes.bool.isRequired,
|
||||
operation: PropTypes.instanceOf(Iterable).isRequired,
|
||||
response: PropTypes.instanceOf(Iterable),
|
||||
request: PropTypes.instanceOf(Iterable),
|
||||
|
||||
tagKey: PropTypes.string,
|
||||
operationKey: PropTypes.string,
|
||||
jumpToKey: CustomPropTypes.arrayOrString.isRequired,
|
||||
|
||||
allowTryItOut: PropTypes.bool,
|
||||
|
||||
displayOperationId: PropTypes.bool,
|
||||
displayRequestDuration: PropTypes.bool,
|
||||
|
||||
response: PropTypes.object,
|
||||
request: PropTypes.object,
|
||||
toggleShown: PropTypes.func.isRequired,
|
||||
onTryoutClick: PropTypes.func.isRequired,
|
||||
onCancelClick: PropTypes.func.isRequired,
|
||||
onExecute: PropTypes.func.isRequired,
|
||||
|
||||
getComponent: PropTypes.func.isRequired,
|
||||
getConfigs: PropTypes.func.isRequired,
|
||||
authActions: PropTypes.object,
|
||||
authSelectors: PropTypes.object,
|
||||
specActions: PropTypes.object.isRequired,
|
||||
@@ -34,89 +24,68 @@ export default class Operation extends PureComponent {
|
||||
oas3Actions: PropTypes.object.isRequired,
|
||||
layoutActions: PropTypes.object.isRequired,
|
||||
layoutSelectors: PropTypes.object.isRequired,
|
||||
fn: PropTypes.object.isRequired,
|
||||
getConfigs: PropTypes.func.isRequired
|
||||
fn: PropTypes.object.isRequired
|
||||
}
|
||||
|
||||
static defaultProps = {
|
||||
showSummary: true,
|
||||
operation: null,
|
||||
response: null,
|
||||
allowTryItOut: true,
|
||||
displayOperationId: false,
|
||||
displayRequestDuration: false
|
||||
}
|
||||
|
||||
constructor(props, context) {
|
||||
super(props, context)
|
||||
this.state = {
|
||||
tryItOutEnabled: false
|
||||
}
|
||||
}
|
||||
|
||||
componentWillReceiveProps(nextProps) {
|
||||
if(nextProps.response !== this.props.response) {
|
||||
this.setState({ executeInProgress: false })
|
||||
}
|
||||
}
|
||||
|
||||
toggleShown =() => {
|
||||
let { layoutActions, tagKey, operationKey, isShown } = this.props
|
||||
const isShownKey = ["operations", tagKey, operationKey]
|
||||
|
||||
layoutActions.show(isShownKey, !isShown)
|
||||
}
|
||||
|
||||
onTryoutClick =() => {
|
||||
this.setState({tryItOutEnabled: !this.state.tryItOutEnabled})
|
||||
}
|
||||
|
||||
onCancelClick =() => {
|
||||
let { specActions, path, method } = this.props
|
||||
this.setState({tryItOutEnabled: !this.state.tryItOutEnabled})
|
||||
specActions.clearValidateParams([path, method])
|
||||
}
|
||||
|
||||
onExecute = () => {
|
||||
this.setState({ executeInProgress: true })
|
||||
request: null
|
||||
}
|
||||
|
||||
render() {
|
||||
let {
|
||||
operationKey,
|
||||
tagKey,
|
||||
isShown,
|
||||
jumpToKey,
|
||||
path,
|
||||
method,
|
||||
operation,
|
||||
showSummary,
|
||||
response,
|
||||
request,
|
||||
allowTryItOut,
|
||||
displayOperationId,
|
||||
displayRequestDuration,
|
||||
toggleShown,
|
||||
onTryoutClick,
|
||||
onCancelClick,
|
||||
onExecute,
|
||||
fn,
|
||||
getComponent,
|
||||
getConfigs,
|
||||
specActions,
|
||||
specSelectors,
|
||||
authActions,
|
||||
authSelectors,
|
||||
getConfigs,
|
||||
oas3Actions
|
||||
} = this.props
|
||||
let operationProps = this.props.operation
|
||||
|
||||
let summary = operation.get("summary")
|
||||
let description = operation.get("description")
|
||||
let deprecated = operation.get("deprecated")
|
||||
let extensions = getExtensions(operation)
|
||||
let externalDocs = operation.get("externalDocs")
|
||||
let {
|
||||
isShown,
|
||||
isAuthorized,
|
||||
jumpToKey,
|
||||
path,
|
||||
method,
|
||||
op,
|
||||
tag,
|
||||
showSummary,
|
||||
operationId,
|
||||
allowTryItOut,
|
||||
displayOperationId,
|
||||
displayRequestDuration,
|
||||
isDeepLinkingEnabled,
|
||||
tryItOutEnabled,
|
||||
executeInProgress
|
||||
} = operationProps.toJS()
|
||||
|
||||
let {
|
||||
summary,
|
||||
description,
|
||||
deprecated,
|
||||
externalDocs,
|
||||
schemes
|
||||
} = op.operation
|
||||
|
||||
let operation = operationProps.getIn(["op", "operation"])
|
||||
let security = operationProps.get("security")
|
||||
let responses = operation.get("responses")
|
||||
let security = operation.get("security") || specSelectors.security()
|
||||
let produces = operation.get("produces")
|
||||
let schemes = operation.get("schemes")
|
||||
let parameters = getList(operation, ["parameters"])
|
||||
let operationId = operation.get("__originalOperationId")
|
||||
let operationScheme = specSelectors.operationScheme(path, method)
|
||||
let isShownKey = ["operations", tag, operationId]
|
||||
let extensions = getExtensions(operation)
|
||||
|
||||
const Responses = getComponent("responses")
|
||||
const Parameters = getComponent( "parameters" )
|
||||
@@ -129,9 +98,7 @@ export default class Operation extends PureComponent {
|
||||
const Schemes = getComponent( "schemes" )
|
||||
const OperationExt = getComponent( "OperationExt" )
|
||||
|
||||
const { deepLinking, showExtensions } = getConfigs()
|
||||
|
||||
const isDeepLinkingEnabled = deepLinking && deepLinking !== "false"
|
||||
const { showExtensions } = getConfigs()
|
||||
|
||||
// Merge in Live Response
|
||||
if(responses && response && response.size > 0) {
|
||||
@@ -139,18 +106,17 @@ export default class Operation extends PureComponent {
|
||||
response = response.set("notDocumented", notDocumented)
|
||||
}
|
||||
|
||||
let { tryItOutEnabled } = this.state
|
||||
let onChangeKey = [ path, method ] // Used to add values to _this_ operation ( indexed by path and method )
|
||||
|
||||
return (
|
||||
<div className={deprecated ? "opblock opblock-deprecated" : isShown ? `opblock opblock-${method} is-open` : `opblock opblock-${method}`} id={`operations-${tagKey}-${operationKey}`} >
|
||||
<div className={`opblock-summary opblock-summary-${method}`} onClick={this.toggleShown} >
|
||||
<div className={deprecated ? "opblock opblock-deprecated" : isShown ? `opblock opblock-${method} is-open` : `opblock opblock-${method}`} id={isShownKey.join("-")} >
|
||||
<div className={`opblock-summary opblock-summary-${method}`} onClick={toggleShown} >
|
||||
<span className="opblock-summary-method">{method.toUpperCase()}</span>
|
||||
<span className={ deprecated ? "opblock-summary-path__deprecated" : "opblock-summary-path" } >
|
||||
<a
|
||||
className="nostyle"
|
||||
onClick={isDeepLinkingEnabled ? (e) => e.preventDefault() : null}
|
||||
href={isDeepLinkingEnabled ? `#/${tagKey}/${operationKey}` : null}>
|
||||
href={isDeepLinkingEnabled ? `#/${isShownKey.join("/")}` : null}>
|
||||
<span>{path}</span>
|
||||
</a>
|
||||
<JumpToPath path={jumpToKey} />
|
||||
@@ -167,7 +133,7 @@ export default class Operation extends PureComponent {
|
||||
{
|
||||
(!security || !security.count()) ? null :
|
||||
<AuthorizeOperationBtn
|
||||
isAuthorized={ authSelectors.isAuthorized(security) }
|
||||
isAuthorized={ isAuthorized }
|
||||
onClick={() => {
|
||||
const applicableDefinitions = authSelectors.definitionsForRequirements(security)
|
||||
authActions.showDefinitions(applicableDefinitions)
|
||||
@@ -203,8 +169,8 @@ export default class Operation extends PureComponent {
|
||||
parameters={parameters}
|
||||
operation={operation}
|
||||
onChangeKey={onChangeKey}
|
||||
onTryoutClick = { this.onTryoutClick }
|
||||
onCancelClick = { this.onCancelClick }
|
||||
onTryoutClick = { onTryoutClick }
|
||||
onCancelClick = { onCancelClick }
|
||||
tryItOutEnabled = { tryItOutEnabled }
|
||||
allowTryItOut={allowTryItOut}
|
||||
|
||||
@@ -229,25 +195,23 @@ export default class Operation extends PureComponent {
|
||||
{ !tryItOutEnabled || !allowTryItOut ? null :
|
||||
|
||||
<Execute
|
||||
getComponent={getComponent}
|
||||
operation={ operation }
|
||||
specActions={ specActions }
|
||||
specSelectors={ specSelectors }
|
||||
path={ path }
|
||||
method={ method }
|
||||
onExecute={ this.onExecute } />
|
||||
onExecute={ onExecute } />
|
||||
}
|
||||
|
||||
{ (!tryItOutEnabled || !response || !allowTryItOut) ? null :
|
||||
<Clear
|
||||
onClick={ this.onClearClick }
|
||||
specActions={ specActions }
|
||||
path={ path }
|
||||
method={ method }/>
|
||||
}
|
||||
</div>
|
||||
|
||||
{this.state.executeInProgress ? <div className="loading-container"><div className="loading"></div></div> : null}
|
||||
{executeInProgress ? <div className="loading-container"><div className="loading"></div></div> : null}
|
||||
|
||||
{ !responses ? null :
|
||||
<Responses
|
||||
@@ -261,7 +225,8 @@ export default class Operation extends PureComponent {
|
||||
specActions={ specActions }
|
||||
produces={ produces }
|
||||
producesValue={ operation.get("produces_value") }
|
||||
pathMethod={ [path, method] }
|
||||
path={ path }
|
||||
method={ method }
|
||||
displayRequestDuration={ displayRequestDuration }
|
||||
fn={fn} />
|
||||
}
|
||||
|
||||
@@ -1,8 +1,6 @@
|
||||
import React from "react"
|
||||
import PropTypes from "prop-types"
|
||||
import { helpers } from "swagger-client"
|
||||
import { createDeepLinkPath, sanitizeUrl } from "core/utils"
|
||||
const { opId } = helpers
|
||||
|
||||
export default class Operations extends React.Component {
|
||||
|
||||
@@ -21,28 +19,20 @@ export default class Operations extends React.Component {
|
||||
render() {
|
||||
let {
|
||||
specSelectors,
|
||||
specActions,
|
||||
oas3Actions,
|
||||
getComponent,
|
||||
layoutSelectors,
|
||||
layoutActions,
|
||||
authActions,
|
||||
authSelectors,
|
||||
getConfigs,
|
||||
fn
|
||||
getConfigs
|
||||
} = this.props
|
||||
|
||||
let taggedOps = specSelectors.taggedOperations()
|
||||
|
||||
const Operation = getComponent("operation")
|
||||
const OperationContainer = getComponent("OperationContainer", true)
|
||||
const Collapse = getComponent("Collapse")
|
||||
const Markdown = getComponent("Markdown")
|
||||
|
||||
let showSummary = layoutSelectors.showSummary()
|
||||
let {
|
||||
docExpansion,
|
||||
displayOperationId,
|
||||
displayRequestDuration,
|
||||
maxDisplayedTags,
|
||||
deepLinking
|
||||
} = getConfigs()
|
||||
@@ -120,49 +110,15 @@ export default class Operations extends React.Component {
|
||||
<Collapse isOpened={showTag}>
|
||||
{
|
||||
operations.map( op => {
|
||||
const path = op.get("path")
|
||||
const method = op.get("method")
|
||||
|
||||
const path = op.get("path", "")
|
||||
const method = op.get("method", "")
|
||||
const jumpToKey = `paths.${path}.${method}`
|
||||
|
||||
const operationId =
|
||||
op.getIn(["operation", "operationId"]) || op.getIn(["operation", "__originalOperationId"]) || opId(op.get("operation"), path, method) || op.get("id")
|
||||
const tagKey = createDeepLinkPath(tag)
|
||||
const operationKey = createDeepLinkPath(operationId)
|
||||
|
||||
const allowTryItOut = specSelectors.allowTryItOutFor(op.get("path"), op.get("method"))
|
||||
const response = specSelectors.responseFor(op.get("path"), op.get("method"))
|
||||
const request = specSelectors.requestFor(op.get("path"), op.get("method"))
|
||||
|
||||
return <Operation
|
||||
{...op.toObject()}
|
||||
tagKey={tagKey}
|
||||
operationKey={operationKey}
|
||||
isShown={layoutSelectors.isShown(["operations", tagKey, operationKey], docExpansion === "full")}
|
||||
jumpToKey={jumpToKey}
|
||||
showSummary={showSummary}
|
||||
key={tagKey + operationKey}
|
||||
response={ response }
|
||||
request={ request }
|
||||
allowTryItOut={allowTryItOut}
|
||||
|
||||
displayOperationId={displayOperationId}
|
||||
displayRequestDuration={displayRequestDuration}
|
||||
|
||||
specActions={ specActions }
|
||||
specSelectors={ specSelectors }
|
||||
|
||||
oas3Actions={oas3Actions}
|
||||
|
||||
layoutActions={ layoutActions }
|
||||
layoutSelectors={ layoutSelectors }
|
||||
|
||||
authActions={ authActions }
|
||||
authSelectors={ authSelectors }
|
||||
|
||||
getComponent={ getComponent }
|
||||
fn={fn}
|
||||
getConfigs={ getConfigs }
|
||||
return <OperationContainer
|
||||
key={`${path}-${method}`}
|
||||
op={op}
|
||||
path={path}
|
||||
method={method}
|
||||
tag={tag}
|
||||
/>
|
||||
}).toArray()
|
||||
}
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
import React from "react"
|
||||
import PropTypes from "prop-types"
|
||||
import cx from "classnames"
|
||||
import { fromJS, Seq } from "immutable"
|
||||
import { fromJS, Seq, Iterable } from "immutable"
|
||||
import { getSampleSchema, fromJSOrdered } from "core/utils"
|
||||
|
||||
const getExampleComponent = ( sampleResponse, examples, HighlightCode ) => {
|
||||
@@ -42,7 +42,7 @@ export default class Response extends React.Component {
|
||||
|
||||
static propTypes = {
|
||||
code: PropTypes.string.isRequired,
|
||||
response: PropTypes.object,
|
||||
response: PropTypes.instanceOf(Iterable),
|
||||
className: PropTypes.string,
|
||||
getComponent: PropTypes.func.isRequired,
|
||||
getConfigs: PropTypes.func.isRequired,
|
||||
|
||||
@@ -1,41 +1,52 @@
|
||||
import React from "react"
|
||||
import PropTypes from "prop-types"
|
||||
import { fromJS } from "immutable"
|
||||
import { fromJS, Iterable } from "immutable"
|
||||
import { defaultStatusCode, getAcceptControllingResponse } from "core/utils"
|
||||
|
||||
export default class Responses extends React.Component {
|
||||
|
||||
static propTypes = {
|
||||
request: PropTypes.object,
|
||||
tryItOutResponse: PropTypes.object,
|
||||
responses: PropTypes.object.isRequired,
|
||||
produces: PropTypes.object,
|
||||
tryItOutResponse: PropTypes.instanceOf(Iterable),
|
||||
responses: PropTypes.instanceOf(Iterable).isRequired,
|
||||
produces: PropTypes.instanceOf(Iterable),
|
||||
producesValue: PropTypes.any,
|
||||
displayRequestDuration: PropTypes.bool.isRequired,
|
||||
path: PropTypes.string.isRequired,
|
||||
method: PropTypes.string.isRequired,
|
||||
getComponent: PropTypes.func.isRequired,
|
||||
getConfigs: 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
|
||||
}
|
||||
|
||||
static defaultProps = {
|
||||
request: null,
|
||||
tryItOutResponse: null,
|
||||
produces: fromJS(["application/json"]),
|
||||
displayRequestDuration: false
|
||||
}
|
||||
|
||||
onChangeProducesWrapper = ( val ) => this.props.specActions.changeProducesValue(this.props.pathMethod, val)
|
||||
shouldComponentUpdate(nextProps) {
|
||||
// BUG: props.tryItOutResponse is always coming back as a new Immutable instance
|
||||
let render = this.props.tryItOutResponse !== nextProps.tryItOutResponse
|
||||
|| this.props.responses !== nextProps.responses
|
||||
|| this.props.produces !== nextProps.produces
|
||||
|| this.props.producesValue !== nextProps.producesValue
|
||||
|| this.props.displayRequestDuration !== nextProps.displayRequestDuration
|
||||
|| this.props.path !== nextProps.path
|
||||
|| this.props.method !== nextProps.method
|
||||
return render
|
||||
}
|
||||
|
||||
onChangeProducesWrapper = ( val ) => this.props.specActions.changeProducesValue([this.props.path, this.props.method], val)
|
||||
|
||||
onResponseContentTypeChange = ({ controlsAcceptHeader, value }) => {
|
||||
const { oas3Actions, pathMethod } = this.props
|
||||
const { oas3Actions, path, method } = this.props
|
||||
if(controlsAcceptHeader) {
|
||||
oas3Actions.setResponseContentType({
|
||||
value,
|
||||
pathMethod
|
||||
path,
|
||||
method
|
||||
})
|
||||
}
|
||||
}
|
||||
@@ -43,7 +54,6 @@ export default class Responses extends React.Component {
|
||||
render() {
|
||||
let {
|
||||
responses,
|
||||
request,
|
||||
tryItOutResponse,
|
||||
getComponent,
|
||||
getConfigs,
|
||||
@@ -81,12 +91,12 @@ export default class Responses extends React.Component {
|
||||
{
|
||||
!tryItOutResponse ? null
|
||||
: <div>
|
||||
<LiveResponse request={ request }
|
||||
response={ tryItOutResponse }
|
||||
<LiveResponse response={ tryItOutResponse }
|
||||
getComponent={ getComponent }
|
||||
getConfigs={ getConfigs }
|
||||
specSelectors={ specSelectors }
|
||||
pathMethod={ this.props.pathMethod }
|
||||
path={ this.props.path }
|
||||
method={ this.props.method }
|
||||
displayRequestDuration={ displayRequestDuration } />
|
||||
<h4>Responses</h4>
|
||||
</div>
|
||||
|
||||
203
src/core/containers/OperationContainer.jsx
Normal file
203
src/core/containers/OperationContainer.jsx
Normal file
@@ -0,0 +1,203 @@
|
||||
import React, { PureComponent } from "react"
|
||||
import PropTypes from "prop-types"
|
||||
import { helpers } from "swagger-client"
|
||||
import { Iterable, fromJS } from "immutable"
|
||||
|
||||
const { opId } = helpers
|
||||
|
||||
export default class OperationContainer extends PureComponent {
|
||||
constructor(props, context) {
|
||||
super(props, context)
|
||||
this.state = {
|
||||
tryItOutEnabled: false,
|
||||
executeInProgress: false
|
||||
}
|
||||
}
|
||||
|
||||
static propTypes = {
|
||||
op: PropTypes.instanceOf(Iterable).isRequired,
|
||||
tag: PropTypes.string.isRequired,
|
||||
path: PropTypes.string.isRequired,
|
||||
method: PropTypes.string.isRequired,
|
||||
operationId: PropTypes.string.isRequired,
|
||||
showSummary: PropTypes.bool.isRequired,
|
||||
isShown: PropTypes.bool.isRequired,
|
||||
jumpToKey: PropTypes.string.isRequired,
|
||||
allowTryItOut: PropTypes.bool,
|
||||
displayOperationId: PropTypes.bool,
|
||||
isAuthorized: PropTypes.bool,
|
||||
displayRequestDuration: PropTypes.bool,
|
||||
response: PropTypes.instanceOf(Iterable),
|
||||
request: PropTypes.instanceOf(Iterable),
|
||||
security: PropTypes.instanceOf(Iterable),
|
||||
isDeepLinkingEnabled: PropTypes.bool.isRequired,
|
||||
|
||||
getComponent: PropTypes.func.isRequired,
|
||||
authActions: PropTypes.object,
|
||||
oas3Actions: PropTypes.object,
|
||||
authSelectors: PropTypes.object,
|
||||
specActions: PropTypes.object.isRequired,
|
||||
specSelectors: PropTypes.object.isRequired,
|
||||
layoutActions: PropTypes.object.isRequired,
|
||||
layoutSelectors: PropTypes.object.isRequired,
|
||||
fn: PropTypes.object.isRequired,
|
||||
getConfigs: PropTypes.func.isRequired
|
||||
}
|
||||
|
||||
static defaultProps = {
|
||||
showSummary: true,
|
||||
response: null,
|
||||
allowTryItOut: true,
|
||||
displayOperationId: false,
|
||||
displayRequestDuration: false
|
||||
}
|
||||
|
||||
mapStateToProps(nextState, props) {
|
||||
const { op, layoutSelectors, getConfigs } = props
|
||||
const { docExpansion, deepLinking, displayOperationId, displayRequestDuration } = getConfigs()
|
||||
const showSummary = layoutSelectors.showSummary()
|
||||
const operationId = op.getIn(["operation", "operationId"]) || op.getIn(["operation", "__originalOperationId"]) || opId(op.get("operation"), props.path, props.method) || op.get("id")
|
||||
const isShownKey = ["operations", props.tag, operationId]
|
||||
const isDeepLinkingEnabled = deepLinking && deepLinking !== "false"
|
||||
const allowTryItOut = typeof props.allowTryItOut === "undefined" ?
|
||||
props.specSelectors.allowTryItOutFor(props.path, props.method) : props.allowTryItOut
|
||||
const security = op.getIn(["operation", "security"]) || props.specSelectors.security()
|
||||
|
||||
return {
|
||||
operationId,
|
||||
isDeepLinkingEnabled,
|
||||
showSummary,
|
||||
displayOperationId,
|
||||
displayRequestDuration,
|
||||
allowTryItOut,
|
||||
security,
|
||||
isAuthorized: props.authSelectors.isAuthorized(security),
|
||||
isShown: layoutSelectors.isShown(isShownKey, docExpansion === "full" ),
|
||||
jumpToKey: `paths.${props.path}.${props.method}`,
|
||||
response: props.specSelectors.responseFor(props.path, props.method),
|
||||
request: props.specSelectors.requestFor(props.path, props.method)
|
||||
}
|
||||
}
|
||||
|
||||
componentWillReceiveProps(nextProps) {
|
||||
const defaultContentType = "application/json"
|
||||
let { specActions, path, method, op } = nextProps
|
||||
let operation = op.get("operation")
|
||||
let producesValue = operation.get("produces_value")
|
||||
let produces = operation.get("produces")
|
||||
let consumes = operation.get("consumes")
|
||||
let consumesValue = operation.get("consumes_value")
|
||||
|
||||
if(nextProps.response !== this.props.response) {
|
||||
this.setState({ executeInProgress: false })
|
||||
}
|
||||
|
||||
if (producesValue === undefined) {
|
||||
producesValue = produces && produces.size ? produces.first() : defaultContentType
|
||||
specActions.changeProducesValue([path, method], producesValue)
|
||||
}
|
||||
|
||||
if (consumesValue === undefined) {
|
||||
consumesValue = consumes && consumes.size ? consumes.first() : defaultContentType
|
||||
specActions.changeConsumesValue([path, method], consumesValue)
|
||||
}
|
||||
}
|
||||
|
||||
toggleShown =() => {
|
||||
let { layoutActions, tag, operationId, isShown } = this.props
|
||||
layoutActions.show(["operations", tag, operationId], !isShown)
|
||||
}
|
||||
|
||||
onTryoutClick =() => {
|
||||
this.setState({tryItOutEnabled: !this.state.tryItOutEnabled})
|
||||
}
|
||||
|
||||
onCancelClick =() => {
|
||||
let { specActions, path, method } = this.props
|
||||
this.setState({tryItOutEnabled: !this.state.tryItOutEnabled})
|
||||
specActions.clearValidateParams([path, method])
|
||||
}
|
||||
|
||||
onExecute = () => {
|
||||
this.setState({ executeInProgress: true })
|
||||
}
|
||||
|
||||
render() {
|
||||
let {
|
||||
op,
|
||||
tag,
|
||||
path,
|
||||
method,
|
||||
security,
|
||||
isAuthorized,
|
||||
operationId,
|
||||
showSummary,
|
||||
isShown,
|
||||
jumpToKey,
|
||||
allowTryItOut,
|
||||
response,
|
||||
request,
|
||||
displayOperationId,
|
||||
displayRequestDuration,
|
||||
isDeepLinkingEnabled,
|
||||
specSelectors,
|
||||
specActions,
|
||||
getComponent,
|
||||
getConfigs,
|
||||
layoutSelectors,
|
||||
layoutActions,
|
||||
authActions,
|
||||
authSelectors,
|
||||
oas3Actions,
|
||||
fn
|
||||
} = this.props
|
||||
|
||||
const Operation = getComponent( "operation" )
|
||||
|
||||
const operationProps = fromJS({
|
||||
op,
|
||||
tag,
|
||||
path,
|
||||
method,
|
||||
security,
|
||||
isAuthorized,
|
||||
operationId,
|
||||
showSummary,
|
||||
isShown,
|
||||
jumpToKey,
|
||||
allowTryItOut,
|
||||
request,
|
||||
displayOperationId,
|
||||
displayRequestDuration,
|
||||
isDeepLinkingEnabled,
|
||||
executeInProgress: this.state.executeInProgress,
|
||||
tryItOutEnabled: this.state.tryItOutEnabled
|
||||
})
|
||||
|
||||
return (
|
||||
<Operation
|
||||
operation={operationProps}
|
||||
response={response}
|
||||
request={request}
|
||||
isShown={isShown}
|
||||
|
||||
toggleShown={this.toggleShown}
|
||||
onTryoutClick={this.onTryoutClick}
|
||||
onCancelClick={this.onCancelClick}
|
||||
onExecute={this.onExecute}
|
||||
|
||||
specActions={ specActions }
|
||||
specSelectors={ specSelectors }
|
||||
oas3Actions={oas3Actions}
|
||||
layoutActions={ layoutActions }
|
||||
layoutSelectors={ layoutSelectors }
|
||||
authActions={ authActions }
|
||||
authSelectors={ authSelectors }
|
||||
getComponent={ getComponent }
|
||||
getConfigs={ getConfigs }
|
||||
fn={fn}
|
||||
/>
|
||||
)
|
||||
}
|
||||
|
||||
}
|
||||
@@ -7,8 +7,7 @@ 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
|
||||
window.Perf = require("react-addons-perf")
|
||||
}
|
||||
|
||||
// eslint-disable-next-line no-undef
|
||||
|
||||
@@ -73,7 +73,7 @@ export const authorizePassword = ( auth ) => ( { authActions } ) => {
|
||||
let { schema, name, username, password, passwordType, clientId, clientSecret } = auth
|
||||
let form = {
|
||||
grant_type: "password",
|
||||
scope: encodeURIComponent(auth.scopes.join(scopeSeparator))
|
||||
scope: auth.scopes.join(scopeSeparator)
|
||||
}
|
||||
let query = {}
|
||||
let headers = {}
|
||||
|
||||
@@ -28,10 +28,10 @@ export function setRequestContentType ({ value, pathMethod }) {
|
||||
}
|
||||
}
|
||||
|
||||
export function setResponseContentType ({ value, pathMethod }) {
|
||||
export function setResponseContentType ({ value, path, method }) {
|
||||
return {
|
||||
type: UPDATE_RESPONSE_CONTENT_TYPE,
|
||||
payload: { value, pathMethod }
|
||||
payload: { value, path, method }
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -1,10 +1,12 @@
|
||||
import React from "react"
|
||||
import PropTypes from "prop-types"
|
||||
import ImPropTypes from "react-immutable-proptypes"
|
||||
import { fromJS } from "immutable"
|
||||
|
||||
const Callbacks = (props) => {
|
||||
let { callbacks, getComponent } = props
|
||||
// const Markdown = getComponent("Markdown")
|
||||
const Operation = getComponent("operation", true)
|
||||
const OperationContainer = getComponent("OperationContainer", true)
|
||||
|
||||
if(!callbacks) {
|
||||
return <span>No callbacks</span>
|
||||
@@ -16,24 +18,22 @@ const Callbacks = (props) => {
|
||||
{ callback.map((pathItem, pathItemName) => {
|
||||
return <div key={pathItemName}>
|
||||
{ pathItem.map((operation, method) => {
|
||||
return <Operation
|
||||
operation={operation}
|
||||
let op = fromJS({
|
||||
operation
|
||||
})
|
||||
return <OperationContainer
|
||||
{...props}
|
||||
op={op}
|
||||
key={method}
|
||||
tag={""}
|
||||
method={method}
|
||||
isShownKey={["callbacks", operation.get("id"), callbackName]}
|
||||
path={pathItemName}
|
||||
allowTryItOut={false}
|
||||
{...props}></Operation>
|
||||
// return <pre>{JSON.stringify(operation)}</pre>
|
||||
/>
|
||||
}) }
|
||||
</div>
|
||||
}) }
|
||||
</div>
|
||||
// return <div>
|
||||
// <h2>{name}</h2>
|
||||
// {callback.description && <Markdown source={callback.description}/>}
|
||||
// <pre>{JSON.stringify(callback)}</pre>
|
||||
// </div>
|
||||
})
|
||||
return <div>
|
||||
{callbackElements}
|
||||
@@ -42,7 +42,7 @@ const Callbacks = (props) => {
|
||||
|
||||
Callbacks.propTypes = {
|
||||
getComponent: PropTypes.func.isRequired,
|
||||
callbacks: PropTypes.array.isRequired
|
||||
callbacks: ImPropTypes.iterable.isRequired
|
||||
|
||||
}
|
||||
|
||||
|
||||
@@ -48,6 +48,13 @@ export default class RequestBodyEditor extends PureComponent {
|
||||
}
|
||||
}
|
||||
|
||||
componentDidUpdate(prevProps) {
|
||||
if(this.props.requestBody !== prevProps.requestBody) {
|
||||
// force recalc of value if the request body definition has changed
|
||||
this.setValueToSample(this.props.mediaType)
|
||||
}
|
||||
}
|
||||
|
||||
setValueToSample = (explicitMediaType) => {
|
||||
this.onChange(this.sample(explicitMediaType))
|
||||
}
|
||||
|
||||
@@ -22,6 +22,10 @@ const RequestBody = ({
|
||||
|
||||
const mediaTypeValue = requestBodyContent.get(contentType)
|
||||
|
||||
if(!mediaTypeValue) {
|
||||
return null
|
||||
}
|
||||
|
||||
return <div>
|
||||
{ requestBodyDescription &&
|
||||
<Markdown source={requestBodyDescription} />
|
||||
|
||||
@@ -18,8 +18,7 @@ export default {
|
||||
let [path, method] = pathMethod
|
||||
return state.setIn( [ "requestData", path, method, "requestContentType" ], value)
|
||||
},
|
||||
[UPDATE_RESPONSE_CONTENT_TYPE]: (state, { payload: { value, pathMethod } } ) =>{
|
||||
let [path, method] = pathMethod
|
||||
[UPDATE_RESPONSE_CONTENT_TYPE]: (state, { payload: { value, path, method } } ) =>{
|
||||
return state.setIn( [ "requestData", path, method, "responseContentType" ], value)
|
||||
},
|
||||
[UPDATE_SERVER_VARIABLE_VALUE]: (state, { payload: { server, key, val } } ) =>{
|
||||
|
||||
@@ -20,8 +20,14 @@ const RootWrapper = (reduxStore, ComponentToWrap) => class extends Component {
|
||||
}
|
||||
|
||||
const makeContainer = (getSystem, component, reduxStore) => {
|
||||
const mapStateToProps = function(state, ownProps) {
|
||||
const propsForContainerComponent = Object.assign({}, ownProps, getSystem())
|
||||
const ori = component.prototype.mapStateToProps || (state => { return {state} })
|
||||
return ori(state, propsForContainerComponent)
|
||||
}
|
||||
|
||||
let wrappedWithSystem = SystemWrapper(getSystem, component, reduxStore)
|
||||
let connected = connect(state => ({state}))(wrappedWithSystem)
|
||||
let connected = connect( mapStateToProps )(wrappedWithSystem)
|
||||
if(reduxStore)
|
||||
return RootWrapper(reduxStore, connected)
|
||||
return connected
|
||||
@@ -114,5 +120,5 @@ export const getComponent = (getSystem, getStore, getComponents, componentName,
|
||||
return makeContainer(getSystem, component, getStore())
|
||||
|
||||
// container == truthy
|
||||
return makeContainer(getSystem, component)
|
||||
return makeContainer(getSystem, wrapRender(component))
|
||||
}
|
||||
|
||||
@@ -13,6 +13,8 @@ import downloadUrlPlugin from "core/plugins/download-url"
|
||||
import configsPlugin from "plugins/configs"
|
||||
import deepLinkingPlugin from "core/plugins/deep-linking"
|
||||
|
||||
import OperationContainer from "core/containers/OperationContainer"
|
||||
|
||||
import App from "core/components/app"
|
||||
import AuthorizationPopup from "core/components/auth/authorization-popup"
|
||||
import AuthorizeBtn from "core/components/auth/authorize-btn"
|
||||
@@ -118,7 +120,8 @@ export default function() {
|
||||
VersionStamp,
|
||||
OperationExt,
|
||||
OperationExtRow,
|
||||
ParameterExt
|
||||
ParameterExt,
|
||||
OperationContainer
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -289,8 +289,7 @@ export default class Store {
|
||||
|
||||
getMapStateToProps() {
|
||||
return () => {
|
||||
let obj = Object.assign({}, this.getSystem())
|
||||
return obj
|
||||
return Object.assign({}, this.getSystem())
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -565,6 +565,7 @@
|
||||
p
|
||||
{
|
||||
margin: 0;
|
||||
@include text_code($response-col-description-inner-markdown-font-color);
|
||||
}
|
||||
|
||||
a
|
||||
@@ -575,6 +576,12 @@
|
||||
color: $response-col-description-inner-markdown-link-font-color-hover;
|
||||
}
|
||||
}
|
||||
|
||||
th
|
||||
{
|
||||
@include text_code($response-col-description-inner-markdown-font-color);
|
||||
border-bottom: 1px solid $response-col-description-inner-markdown-font-color;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -1,7 +1,11 @@
|
||||
/* eslint-env mocha */
|
||||
import React, { PureComponent } from "react"
|
||||
import expect from "expect"
|
||||
import System from "core/system"
|
||||
import { fromJS } from "immutable"
|
||||
import { render } from "enzyme"
|
||||
import ViewPlugin from "core/plugins/view/index.js"
|
||||
import { connect, Provider } from "react-redux"
|
||||
|
||||
describe("bound system", function(){
|
||||
|
||||
@@ -444,4 +448,239 @@ describe("bound system", function(){
|
||||
|
||||
})
|
||||
|
||||
describe("getComponent", function() {
|
||||
it("returns a component from the system", function() {
|
||||
const system = new System({
|
||||
plugins: [
|
||||
ViewPlugin,
|
||||
{
|
||||
components: {
|
||||
test: ({ name }) => <div>{name} component</div>
|
||||
}
|
||||
}
|
||||
]
|
||||
})
|
||||
|
||||
// When
|
||||
var Component = system.getSystem().getComponent("test")
|
||||
const renderedComponent = render(<Component name="Test" />)
|
||||
expect(renderedComponent.text()).toEqual("Test component")
|
||||
})
|
||||
|
||||
it("allows container components to provide their own `mapStateToProps` function", function() {
|
||||
// Given
|
||||
class ContainerComponent extends PureComponent {
|
||||
mapStateToProps(nextState, props) {
|
||||
return {
|
||||
"fromMapState": "This came from mapStateToProps"
|
||||
}
|
||||
}
|
||||
|
||||
static defaultProps = {
|
||||
"fromMapState" : ""
|
||||
}
|
||||
|
||||
render() {
|
||||
const { exampleSelectors, fromMapState, fromOwnProps } = this.props
|
||||
return (
|
||||
<div>{ fromMapState } {exampleSelectors.foo()} {fromOwnProps}</div>
|
||||
)
|
||||
}
|
||||
}
|
||||
const system = new System({
|
||||
plugins: [
|
||||
ViewPlugin,
|
||||
{
|
||||
components: {
|
||||
ContainerComponent
|
||||
}
|
||||
},
|
||||
{
|
||||
statePlugins: {
|
||||
example: {
|
||||
selectors: {
|
||||
foo() { return "and this came from the system" }
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
]
|
||||
})
|
||||
|
||||
// When
|
||||
var Component = system.getSystem().getComponent("ContainerComponent", true)
|
||||
const renderedComponent = render(
|
||||
<Provider store={system.getStore()}>
|
||||
<Component fromOwnProps="and this came from my own props" />
|
||||
</Provider>
|
||||
)
|
||||
|
||||
// Then
|
||||
expect(renderedComponent.text()).toEqual("This came from mapStateToProps and this came from the system and this came from my own props")
|
||||
})
|
||||
|
||||
it("gives the system and own props as props to a container's `mapStateToProps` function", function() {
|
||||
// Given
|
||||
class ContainerComponent extends PureComponent {
|
||||
mapStateToProps(nextState, props) {
|
||||
const { exampleSelectors, fromMapState, fromOwnProps } = props
|
||||
return {
|
||||
"fromMapState": `This came from mapStateToProps ${exampleSelectors.foo()} ${fromOwnProps}`
|
||||
}
|
||||
}
|
||||
|
||||
static defaultProps = {
|
||||
"fromMapState" : ""
|
||||
}
|
||||
|
||||
render() {
|
||||
const { fromMapState } = this.props
|
||||
return (
|
||||
<div>{ fromMapState }</div>
|
||||
)
|
||||
}
|
||||
}
|
||||
const system = new System({
|
||||
plugins: [
|
||||
ViewPlugin,
|
||||
{
|
||||
components: {
|
||||
ContainerComponent
|
||||
}
|
||||
},
|
||||
{
|
||||
statePlugins: {
|
||||
example: {
|
||||
selectors: {
|
||||
foo() { return "and this came from the system" }
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
]
|
||||
})
|
||||
|
||||
// When
|
||||
var Component = system.getSystem().getComponent("ContainerComponent", true)
|
||||
const renderedComponent = render(
|
||||
<Provider store={system.getStore()}>
|
||||
<Component fromOwnProps="and this came from my own props" />
|
||||
</Provider>
|
||||
)
|
||||
|
||||
// Then
|
||||
expect(renderedComponent.text()).toEqual("This came from mapStateToProps and this came from the system and this came from my own props")
|
||||
})
|
||||
|
||||
it("should catch errors thrown inside of React Component Class render methods", function() {
|
||||
// Given
|
||||
// eslint-disable-next-line react/require-render-return
|
||||
class BrokenComponent extends React.Component {
|
||||
render() {
|
||||
throw new Error("This component is broken")
|
||||
}
|
||||
}
|
||||
const system = new System({
|
||||
plugins: [
|
||||
ViewPlugin,
|
||||
{
|
||||
components: {
|
||||
BrokenComponent
|
||||
}
|
||||
}
|
||||
]
|
||||
})
|
||||
|
||||
// When
|
||||
var Component = system.getSystem().getComponent("BrokenComponent")
|
||||
const renderedComponent = render(<Component />)
|
||||
|
||||
// Then
|
||||
expect(renderedComponent.text()).toEqual("😱 Could not render BrokenComponent, see the console.")
|
||||
})
|
||||
|
||||
it("should catch errors thrown inside of pure component render methods", function() {
|
||||
// Given
|
||||
// eslint-disable-next-line react/require-render-return
|
||||
class BrokenComponent extends PureComponent {
|
||||
render() {
|
||||
throw new Error("This component is broken")
|
||||
}
|
||||
}
|
||||
|
||||
const system = new System({
|
||||
plugins: [
|
||||
ViewPlugin,
|
||||
{
|
||||
components: {
|
||||
BrokenComponent
|
||||
}
|
||||
}
|
||||
]
|
||||
})
|
||||
|
||||
// When
|
||||
var Component = system.getSystem().getComponent("BrokenComponent")
|
||||
const renderedComponent = render(<Component />)
|
||||
|
||||
// Then
|
||||
expect(renderedComponent.text()).toEqual("😱 Could not render BrokenComponent, see the console.")
|
||||
})
|
||||
|
||||
it("should catch errors thrown inside of stateless component functions", function() {
|
||||
// Given
|
||||
// eslint-disable-next-line react/require-render-return
|
||||
let BrokenComponent = function BrokenComponent() { throw new Error("This component is broken") }
|
||||
const system = new System({
|
||||
plugins: [
|
||||
ViewPlugin,
|
||||
{
|
||||
components: {
|
||||
BrokenComponent
|
||||
}
|
||||
}
|
||||
]
|
||||
})
|
||||
|
||||
// When
|
||||
var Component = system.getSystem().getComponent("BrokenComponent")
|
||||
const renderedComponent = render(<Component />)
|
||||
|
||||
// Then
|
||||
expect(renderedComponent.text().startsWith("😱 Could not render")).toEqual(true)
|
||||
})
|
||||
|
||||
it("should catch errors thrown inside of container components", function() {
|
||||
// Given
|
||||
// eslint-disable-next-line react/require-render-return
|
||||
class BrokenComponent extends React.Component {
|
||||
render() {
|
||||
throw new Error("This component is broken")
|
||||
}
|
||||
}
|
||||
|
||||
const system = new System({
|
||||
plugins: [
|
||||
ViewPlugin,
|
||||
{
|
||||
components: {
|
||||
BrokenComponent
|
||||
}
|
||||
}
|
||||
]
|
||||
})
|
||||
|
||||
// When
|
||||
var Component = system.getSystem().getComponent("BrokenComponent", true)
|
||||
const renderedComponent = render(
|
||||
<Provider store={system.getStore()}>
|
||||
<Component />
|
||||
</Provider>
|
||||
)
|
||||
|
||||
// Then
|
||||
expect(renderedComponent.text()).toEqual("😱 Could not render BrokenComponent, see the console.")
|
||||
})
|
||||
})
|
||||
|
||||
})
|
||||
|
||||
Reference in New Issue
Block a user