Skip to content

Commit

Permalink
fix: use specPath prop to resolve operations in OperationContainer (s…
Browse files Browse the repository at this point in the history
…wagger-api#4272)

* Use `parameterWithMeta` to get parameter data in <ParameterRow>

* Prefer specPath when fetching resolved subtrees in OperationContainer

* Add test for OAS3 callback rendering

* Remove debugger statement
  • Loading branch information
shockey authored Mar 1, 2018
1 parent 22036b1 commit 8777d8b
Show file tree
Hide file tree
Showing 6 changed files with 128 additions and 11 deletions.
2 changes: 1 addition & 1 deletion src/core/components/operation.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -156,7 +156,7 @@ export default class Operation extends PureComponent {

<Collapse isOpened={isShown}>
<div className="opblock-body">
{ operation && operation.size ? null :
{ (operation && operation.size) || operation === null ? null :
<img height={"32px"} width={"32px"} src={require("core/../img/rolling-load.svg")} className="opblock-loading-animation" />
}
{ deprecated && <h4 className="opblock-title_normal"> Warning: Deprecated</h4>}
Expand Down
43 changes: 37 additions & 6 deletions src/core/containers/OperationContainer.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -82,23 +82,23 @@ export default class OperationContainer extends PureComponent {
}

componentWillReceiveProps(nextProps) {
const { path, method, specActions, specSelectors, response, isShown } = nextProps
const resolvedSubtree = specSelectors.specResolvedSubtree(["paths", path, method])
const { response, isShown } = nextProps
const resolvedSubtree = this.getResolvedSubtree()

if(response !== this.props.response) {
this.setState({ executeInProgress: false })
}

if(isShown && resolvedSubtree === undefined) {
specActions.requestResolvedSubtree(["paths", path, method])
this.requestResolvedSubtree()
}
}

toggleShown =() => {
let { layoutActions, specActions, tag, operationId, path, method, isShown } = this.props
let { layoutActions, tag, operationId, isShown } = this.props
if(!isShown) {
// transitioning from collapsed to expanded
specActions.requestResolvedSubtree(["paths", path, method])
this.requestResolvedSubtree()
}
layoutActions.show(["operations", tag, operationId], !isShown)
}
Expand All @@ -117,6 +117,37 @@ export default class OperationContainer extends PureComponent {
this.setState({ executeInProgress: true })
}

getResolvedSubtree = () => {
const {
specSelectors,
path,
method,
specPath
} = this.props

if(specPath) {
return specSelectors.specResolvedSubtree(specPath.toJS()) || Map()
}

return specSelectors.specResolvedSubtree(["paths", path, method]) || Map()
}

requestResolvedSubtree = () => {
const {
specActions,
path,
method,
specPath
} = this.props


if(specPath) {
return specActions.requestResolvedSubtree(specPath.toJS())
}

return specActions.requestResolvedSubtree(["paths", path, method])
}

render() {
let {
op: unresolvedOp,
Expand Down Expand Up @@ -151,7 +182,7 @@ export default class OperationContainer extends PureComponent {

const Operation = getComponent( "operation" )

const resolvedSubtree = specSelectors.specResolvedSubtree(["paths", path, method]) || Map()
const resolvedSubtree = this.getResolvedSubtree()

const operationProps = fromJS({
op: resolvedSubtree || Map(),
Expand Down
7 changes: 4 additions & 3 deletions src/core/plugins/oas3/components/callbacks.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ import ImPropTypes from "react-immutable-proptypes"
import { fromJS } from "immutable"

const Callbacks = (props) => {
let { callbacks, getComponent } = props
let { callbacks, getComponent, specPath } = props
// const Markdown = getComponent("Markdown")
const OperationContainer = getComponent("OperationContainer", true)

Expand All @@ -28,6 +28,7 @@ const Callbacks = (props) => {
tag={""}
method={method}
path={pathItemName}
specPath={specPath.push(callbackName, pathItemName, method)}
allowTryItOut={false}
/>
}) }
Expand All @@ -42,8 +43,8 @@ const Callbacks = (props) => {

Callbacks.propTypes = {
getComponent: PropTypes.func.isRequired,
callbacks: ImPropTypes.iterable.isRequired

callbacks: ImPropTypes.iterable.isRequired,
specPath: ImPropTypes.list.isRequired,
}

export default Callbacks
5 changes: 4 additions & 1 deletion src/core/plugins/oas3/wrap-components/parameters.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -161,7 +161,10 @@ class Parameters extends Component {
</div> : "" }

{this.state.callbackVisible ? <div className="callbacks-container opblock-description-wrapper">
<Callbacks callbacks={Map(operation.get("callbacks"))} />
<Callbacks
callbacks={Map(operation.get("callbacks"))}
specPath={specPath.slice(0, -1).push("callbacks")}
/>
</div> : "" }
{
isOAS3() && requestBody && this.state.parametersVisible &&
Expand Down
41 changes: 41 additions & 0 deletions test/e2e/scenarios/oas3/callbacks.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,41 @@
describe("render pet api container", function () {
let mainPage
let apiWrapper
beforeEach(function (client, done) {
mainPage = client
.url("localhost:3200")
.page.main()

client.waitForElementVisible(".download-url-input", 5000)
.pause(5000)
.clearValue(".download-url-input")
.setValue(".download-url-input", "http://localhost:3200/test-specs/callbacks.openapi.yaml")
.click("button.download-url-button")
.pause(1000)

apiWrapper = mainPage.section.apiWrapper

done()
})
afterEach(function (client, done) {
done()
})
describe("POST /pet", () => {
it("should render a callback correctly", function (client) {
apiWrapper.waitForElementVisible("#operations-pet-addPet", 10000)
// Expand the operation
.click("#operations-pet-addPet")
.waitForElementVisible("#operations-pet-addPet > div:nth-child(2) > div", 5000)
// Switch to Callbacks tab
.click("#operations-pet-addPet div.tab-header > div.tab-item.false > h4 > span")
.waitForElementVisible("#operations-pet-addPet div.callbacks-container", 5000)
.assert.containsText("#operations--post_request_body__url > div > span.opblock-summary-path", "$request.body#/url")
.click("#operations--post_request_body__url")
.waitForElementVisible("#operations--post_request_body__url div.response-col_description__inner > div > div > p", 5000)
.assert.containsText("#operations--post_request_body__url div.response-col_description__inner > div > div > p", "webhook successfully processed and no retries will be performed")


client.end()
})
})
})
41 changes: 41 additions & 0 deletions test/e2e/specs/callbacks.openapi.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,41 @@
openapi: 3.0.0
servers:
- url: http://petstore.swagger.io/v2
info:
version: 1.0.0
title: Swagger Petstore
termsOfService: http://swagger.io/terms/
contact:
email: [email protected]
license:
name: Apache 2.0
url: http://www.apache.org/licenses/LICENSE-2.0.html
paths:
"/pet":
post:
tags:
- pet
summary: Add a new pet to the store
description: ''
operationId: addPet
parameters: []
responses:
'405':
description: Invalid input
security:
- petstore_auth:
- write:pets
- read:pets
callbacks:
myWebhook:
'$request.body#/url':
post:
requestBody:
description: Callback payload
content:
'application/json':
schema:
type: string
responses:
'200':
description: webhook successfully processed and no retries will be performed

0 comments on commit 8777d8b

Please sign in to comment.