* default to empty `ImmutableMap` when grabbing op metadata * pass `errors` into JsonSchema components * Account for Immutable data structure in JavaScriptonSchema... ...and create empty Lists instead of Maps by default. * Pass ImmutableList through to JsonSchema child components * Add lazy resolving spec state extensions * TEMPORARY: disable conventional resolved spec * WIP * Use resolveSubtree in Operation display * Freebie: short-circuit Markdown component if it is given plaintext * NEW DEFAULT BEHAVIOR: `defaultModelsExpandDepth: 1` does not expand individual models * Render faked Model expander to trigger resolution * Baseline support for Editor lifecycles * Display operation summaries before the operation is resolved * Test migrations * WIP * Swagger2 TIO Body params * a bit of cleanup * Debounce string param inputs * Reach into unresolved operation for deprecated flag, if available * Fire subtree request outside of render * Remove debugging flags * Fix logical errors in spec statePlugins * TODOs become TODONEs! * Migrate deeplinking feature to non-resolved spec action * ESLint fixesbubble
@@ -63,6 +63,7 @@ | |||||
"react-addons-shallow-compare": "0.14.8", | "react-addons-shallow-compare": "0.14.8", | ||||
"react-addons-test-utils": "^15.6.2", | "react-addons-test-utils": "^15.6.2", | ||||
"react-collapse": "^4.0.3", | "react-collapse": "^4.0.3", | ||||
"react-debounce-input": "^3.2.0", | |||||
"react-dom": "^15.6.2", | "react-dom": "^15.6.2", | ||||
"react-height": "^2.0.0", | "react-height": "^2.0.0", | ||||
"react-hot-loader": "1.3.1", | "react-hot-loader": "1.3.1", | ||||
@@ -8,14 +8,17 @@ export default class ModelCollapse extends Component { | |||||
children: PropTypes.any, | children: PropTypes.any, | ||||
title: PropTypes.element, | title: PropTypes.element, | ||||
modelName: PropTypes.string, | modelName: PropTypes.string, | ||||
onToggle: PropTypes.func | |||||
classes: PropTypes.string, | |||||
onToggle: PropTypes.func, | |||||
hideSelfOnExpand: PropTypes.bool, | |||||
} | } | ||||
static defaultProps = { | static defaultProps = { | ||||
collapsedContent: "{...}", | collapsedContent: "{...}", | ||||
expanded: false, | expanded: false, | ||||
title: null, | title: null, | ||||
onToggle: () => {} | |||||
onToggle: () => {}, | |||||
hideSelfOnExpand: false | |||||
} | } | ||||
constructor(props, context) { | constructor(props, context) { | ||||
@@ -29,17 +32,23 @@ export default class ModelCollapse extends Component { | |||||
} | } | ||||
} | } | ||||
componentWillReceiveProps(nextProps){ | |||||
componentDidMount() { | |||||
const { hideSelfOnExpand, expanded, modelName } = this.props | |||||
if(hideSelfOnExpand && expanded) { | |||||
// We just mounted pre-expanded, and we won't be going back.. | |||||
// So let's give our parent an `onToggle` call.. | |||||
// Since otherwise it will never be called. | |||||
this.props.onToggle(modelName, expanded) | |||||
} | |||||
} | |||||
if(this.props.expanded!= nextProps.expanded){ | |||||
componentWillReceiveProps(nextProps){ | |||||
if(this.props.expanded !== nextProps.expanded){ | |||||
this.setState({expanded: nextProps.expanded}) | this.setState({expanded: nextProps.expanded}) | ||||
} | } | ||||
} | } | ||||
toggleCollapsed=()=>{ | toggleCollapsed=()=>{ | ||||
if(this.props.onToggle){ | if(this.props.onToggle){ | ||||
this.props.onToggle(this.props.modelName,!this.state.expanded) | this.props.onToggle(this.props.modelName,!this.state.expanded) | ||||
} | } | ||||
@@ -50,9 +59,18 @@ export default class ModelCollapse extends Component { | |||||
} | } | ||||
render () { | render () { | ||||
const {title} = this.props | |||||
const { title, classes } = this.props | |||||
if(this.state.expanded ) { | |||||
if(this.props.hideSelfOnExpand) { | |||||
return <span className={classes || ""}> | |||||
{this.props.children} | |||||
</span> | |||||
} | |||||
} | |||||
return ( | return ( | ||||
<span> | |||||
<span className={classes || ""}> | |||||
{ title && <span onClick={this.toggleCollapsed} style={{ "cursor": "pointer" }}>{title}</span> } | { title && <span onClick={this.toggleCollapsed} style={{ "cursor": "pointer" }}>{title}</span> } | ||||
<span onClick={ this.toggleCollapsed } style={{ "cursor": "pointer" }}> | <span onClick={ this.toggleCollapsed } style={{ "cursor": "pointer" }}> | ||||
<span className={ "model-toggle" + ( this.state.expanded ? "" : " collapsed" ) }></span> | <span className={ "model-toggle" + ( this.state.expanded ? "" : " collapsed" ) }></span> | ||||
@@ -6,11 +6,29 @@ export default class Models extends Component { | |||||
static propTypes = { | static propTypes = { | ||||
getComponent: PropTypes.func, | getComponent: PropTypes.func, | ||||
specSelectors: PropTypes.object, | specSelectors: PropTypes.object, | ||||
specActions: PropTypes.object.isRequired, | |||||
layoutSelectors: PropTypes.object, | layoutSelectors: PropTypes.object, | ||||
layoutActions: PropTypes.object, | layoutActions: PropTypes.object, | ||||
getConfigs: PropTypes.func.isRequired | getConfigs: PropTypes.func.isRequired | ||||
} | } | ||||
getSchemaBasePath = () => { | |||||
const isOAS3 = this.props.specSelectors.isOAS3() | |||||
return isOAS3 ? ["components", "schemas"] : ["definitions"] | |||||
} | |||||
getCollapsedContent = () => { | |||||
return " " | |||||
} | |||||
handleToggle = (name, isExpanded) => { | |||||
const { layoutActions } = this.props | |||||
layoutActions.show(["models", name], isExpanded) | |||||
if(isExpanded) { | |||||
this.props.specActions.requestResolvedSubtree([...this.getSchemaBasePath(), name]) | |||||
} | |||||
} | |||||
render(){ | render(){ | ||||
let { specSelectors, getComponent, layoutSelectors, layoutActions, getConfigs } = this.props | let { specSelectors, getComponent, layoutSelectors, layoutActions, getConfigs } = this.props | ||||
let definitions = specSelectors.definitions() | let definitions = specSelectors.definitions() | ||||
@@ -18,10 +36,11 @@ export default class Models extends Component { | |||||
if (!definitions.size || defaultModelsExpandDepth < 0) return null | if (!definitions.size || defaultModelsExpandDepth < 0) return null | ||||
let showModels = layoutSelectors.isShown("models", defaultModelsExpandDepth > 0 && docExpansion !== "none") | let showModels = layoutSelectors.isShown("models", defaultModelsExpandDepth > 0 && docExpansion !== "none") | ||||
const specPathBase = specSelectors.isOAS3() ? ["components", "schemas"] : ["definitions"] | |||||
const specPathBase = this.getSchemaBasePath() | |||||
const ModelWrapper = getComponent("ModelWrapper") | const ModelWrapper = getComponent("ModelWrapper") | ||||
const Collapse = getComponent("Collapse") | const Collapse = getComponent("Collapse") | ||||
const ModelCollapse = getComponent("ModelCollapse") | |||||
return <section className={ showModels ? "models is-open" : "models"}> | return <section className={ showModels ? "models is-open" : "models"}> | ||||
<h4 onClick={() => layoutActions.show("models", !showModels)}> | <h4 onClick={() => layoutActions.show("models", !showModels)}> | ||||
@@ -32,18 +51,40 @@ export default class Models extends Component { | |||||
</h4> | </h4> | ||||
<Collapse isOpened={showModels}> | <Collapse isOpened={showModels}> | ||||
{ | { | ||||
definitions.entrySeq().map( ( [ name, model ])=>{ | |||||
definitions.entrySeq().map( ( [ name ])=>{ | |||||
const schema = specSelectors.specResolvedSubtree([...specPathBase, name]) | |||||
if(layoutSelectors.isShown(["models", name], false) && schema === undefined) { | |||||
// Firing an action in a container render is not great, | |||||
// but it works for now. | |||||
this.props.specActions.requestResolvedSubtree([...this.getSchemaBasePath(), name]) | |||||
} | |||||
const content = <ModelWrapper name={ name } | |||||
expandDepth={ defaultModelsExpandDepth } | |||||
schema={ schema } | |||||
specPath={Im.List([...specPathBase, name])} | |||||
getComponent={ getComponent } | |||||
specSelectors={ specSelectors } | |||||
getConfigs = {getConfigs} | |||||
layoutSelectors = {layoutSelectors} | |||||
layoutActions = {layoutActions}/> | |||||
const title = <span className="model-box"> | |||||
<span className="model model-title">{name}</span> | |||||
</span> | |||||
return <div id={ `model-${name}` } className="model-container" key={ `models-section-${name}` }> | return <div id={ `model-${name}` } className="model-container" key={ `models-section-${name}` }> | ||||
<ModelWrapper name={ name } | |||||
expandDepth={ defaultModelsExpandDepth } | |||||
schema={ model } | |||||
specPath={Im.List([...specPathBase, name])} | |||||
getComponent={ getComponent } | |||||
specSelectors={ specSelectors } | |||||
getConfigs = {getConfigs} | |||||
layoutSelectors = {layoutSelectors} | |||||
layoutActions = {layoutActions}/> | |||||
<ModelCollapse | |||||
classes="model-box" | |||||
collapsedContent={this.getCollapsedContent(name)} | |||||
onToggle={this.handleToggle} | |||||
title={title} | |||||
modelName={name} | |||||
hideSelfOnExpand={true} | |||||
expanded={defaultModelsExpandDepth > 1} | |||||
>{content}</ModelCollapse> | |||||
</div> | </div> | ||||
}).toArray() | }).toArray() | ||||
} | } | ||||
@@ -9,6 +9,7 @@ export default class Operation extends PureComponent { | |||||
static propTypes = { | static propTypes = { | ||||
specPath: ImPropTypes.list.isRequired, | specPath: ImPropTypes.list.isRequired, | ||||
operation: PropTypes.instanceOf(Iterable).isRequired, | operation: PropTypes.instanceOf(Iterable).isRequired, | ||||
summary: PropTypes.string, | |||||
response: PropTypes.instanceOf(Iterable), | response: PropTypes.instanceOf(Iterable), | ||||
request: PropTypes.instanceOf(Iterable), | request: PropTypes.instanceOf(Iterable), | ||||
@@ -34,7 +35,8 @@ export default class Operation extends PureComponent { | |||||
operation: null, | operation: null, | ||||
response: null, | response: null, | ||||
request: null, | request: null, | ||||
specPath: List() | |||||
specPath: List(), | |||||
summary: "" | |||||
} | } | ||||
render() { | render() { | ||||
@@ -59,6 +61,8 @@ export default class Operation extends PureComponent { | |||||
let operationProps = this.props.operation | let operationProps = this.props.operation | ||||
let { | let { | ||||
summary, | |||||
deprecated, | |||||
isShown, | isShown, | ||||
isAuthorized, | isAuthorized, | ||||
path, | path, | ||||
@@ -76,14 +80,13 @@ export default class Operation extends PureComponent { | |||||
} = operationProps.toJS() | } = operationProps.toJS() | ||||
let { | let { | ||||
summary, | |||||
summary: resolvedSummary, | |||||
description, | description, | ||||
deprecated, | |||||
externalDocs, | externalDocs, | ||||
schemes | schemes | ||||
} = op.operation | |||||
} = op | |||||
let operation = operationProps.getIn(["op", "operation"]) | |||||
let operation = operationProps.getIn(["op"]) | |||||
let security = operationProps.get("security") | let security = operationProps.get("security") | ||||
let responses = operation.get("responses") | let responses = operation.get("responses") | ||||
let produces = operation.get("produces") | let produces = operation.get("produces") | ||||
@@ -132,7 +135,7 @@ export default class Operation extends PureComponent { | |||||
{ !showSummary ? null : | { !showSummary ? null : | ||||
<div className="opblock-summary-description"> | <div className="opblock-summary-description"> | ||||
{ summary } | |||||
{ resolvedSummary || summary } | |||||
</div> | </div> | ||||
} | } | ||||
@@ -47,7 +47,7 @@ export default class ParamBody extends PureComponent { | |||||
updateValues = (props) => { | updateValues = (props) => { | ||||
let { specSelectors, pathMethod, param, isExecute, consumesValue="" } = props | let { specSelectors, pathMethod, param, isExecute, consumesValue="" } = props | ||||
let parameter = specSelectors ? specSelectors.getParameter(pathMethod, param.get("name"), param.get("in")) : fromJS({}) | |||||
let parameter = specSelectors ? specSelectors.parameterWithMeta(pathMethod, param.get("name"), param.get("in")) : fromJS({}) | |||||
let isXml = /xml/i.test(consumesValue) | let isXml = /xml/i.test(consumesValue) | ||||
let isJson = /json/i.test(consumesValue) | let isJson = /json/i.test(consumesValue) | ||||
let paramValue = isXml ? parameter.get("value_xml") : parameter.get("value") | let paramValue = isXml ? parameter.get("value_xml") : parameter.get("value") | ||||
@@ -107,7 +107,7 @@ export default class ParamBody extends PureComponent { | |||||
const HighlightCode = getComponent("highlightCode") | const HighlightCode = getComponent("highlightCode") | ||||
const ContentType = getComponent("contentType") | const ContentType = getComponent("contentType") | ||||
// for domains where specSelectors not passed | // for domains where specSelectors not passed | ||||
let parameter = specSelectors ? specSelectors.getParameter(pathMethod, param.get("name"), param.get("in")) : param | |||||
let parameter = specSelectors ? specSelectors.parameterWithMeta(pathMethod, param.get("name"), param.get("in")) : param | |||||
let errors = parameter.get("errors", List()) | let errors = parameter.get("errors", List()) | ||||
let consumesValue = specSelectors.contentTypeValues(pathMethod).get("requestContentType") | let consumesValue = specSelectors.contentTypeValues(pathMethod).get("requestContentType") | ||||
let consumes = this.props.consumes && this.props.consumes.size ? this.props.consumes : ParamBody.defaultProp.consumes | let consumes = this.props.consumes && this.props.consumes.size ? this.props.consumes : ParamBody.defaultProp.consumes | ||||
@@ -24,7 +24,7 @@ export default class ParameterRow extends Component { | |||||
let { specSelectors, pathMethod, param } = props | let { specSelectors, pathMethod, param } = props | ||||
let defaultValue = param.get("default") | let defaultValue = param.get("default") | ||||
let parameter = specSelectors.getParameter(pathMethod, param.get("name"), param.get("in")) | |||||
let parameter = specSelectors.parameterWithMeta(pathMethod, param.get("name"), param.get("in")) | |||||
let value = parameter ? parameter.get("value") : "" | let value = parameter ? parameter.get("value") : "" | ||||
if ( defaultValue !== undefined && value === undefined ) { | if ( defaultValue !== undefined && value === undefined ) { | ||||
this.onChangeWrapper(defaultValue) | this.onChangeWrapper(defaultValue) | ||||
@@ -37,7 +37,7 @@ export default class ParameterRow extends Component { | |||||
let example = param.get("example") | let example = param.get("example") | ||||
let defaultValue = param.get("default") | let defaultValue = param.get("default") | ||||
let parameter = specSelectors.getParameter(pathMethod, param.get("name"), param.get("in")) | |||||
let parameter = specSelectors.parameterWithMeta(pathMethod, param.get("name"), param.get("in")) | |||||
let enumValue | let enumValue | ||||
if(isOAS3()) { | if(isOAS3()) { | ||||
@@ -104,8 +104,7 @@ export default class ParameterRow extends Component { | |||||
let isFormDataSupported = "FormData" in win | let isFormDataSupported = "FormData" in win | ||||
let required = param.get("required") | let required = param.get("required") | ||||
let itemType = param.getIn(isOAS3 && isOAS3() ? ["schema", "items", "type"] : ["items", "type"]) | let itemType = param.getIn(isOAS3 && isOAS3() ? ["schema", "items", "type"] : ["items", "type"]) | ||||
let parameter = specSelectors.getParameter(pathMethod, param.get("name"), param.get("in")) | |||||
let value = parameter ? parameter.get("value") : "" | |||||
let value = param ? param.get("value") : "" | |||||
let extensions = getExtensions(param) | let extensions = getExtensions(param) | ||||
@@ -101,7 +101,7 @@ export default class Parameters extends Component { | |||||
specPath={specPath.push(i.toString())} | specPath={specPath.push(i.toString())} | ||||
getComponent={ getComponent } | getComponent={ getComponent } | ||||
getConfigs={ getConfigs } | getConfigs={ getConfigs } | ||||
param={ parameter } | |||||
param={ specSelectors.parameterWithMeta(pathMethod, parameter.get("name"), parameter.get("in")) } | |||||
key={ `${parameter.get( "in" )}.${parameter.get("name")}` } | key={ `${parameter.get( "in" )}.${parameter.get("name")}` } | ||||
onChange={ this.onChange } | onChange={ this.onChange } | ||||
onChangeConsumes={this.onChangeConsumesWrapper} | onChangeConsumes={this.onChangeConsumesWrapper} | ||||
@@ -3,7 +3,17 @@ import PropTypes from "prop-types" | |||||
import Remarkable from "remarkable" | import Remarkable from "remarkable" | ||||
import sanitize from "sanitize-html" | import sanitize from "sanitize-html" | ||||
// eslint-disable-next-line no-useless-escape | |||||
const isPlainText = (str) => /^[A-Z\s0-9!?\.]+$/gi.test(str) | |||||
function Markdown({ source }) { | function Markdown({ source }) { | ||||
if(isPlainText(source)) { | |||||
// If the source text is not Markdown, | |||||
// let's save some time and just render it. | |||||
return <div className="markdown"> | |||||
{source} | |||||
</div> | |||||
} | |||||
const html = new Remarkable({ | const html = new Remarkable({ | ||||
html: true, | html: true, | ||||
typographer: true, | typographer: true, | ||||
@@ -2,7 +2,7 @@ import React, { PureComponent } from "react" | |||||
import PropTypes from "prop-types" | import PropTypes from "prop-types" | ||||
import ImPropTypes from "react-immutable-proptypes" | import ImPropTypes from "react-immutable-proptypes" | ||||
import { helpers } from "swagger-client" | import { helpers } from "swagger-client" | ||||
import { Iterable, fromJS } from "immutable" | |||||
import { Iterable, fromJS, Map } from "immutable" | |||||
const { opId } = helpers | const { opId } = helpers | ||||
@@ -82,13 +82,24 @@ export default class OperationContainer extends PureComponent { | |||||
} | } | ||||
componentWillReceiveProps(nextProps) { | componentWillReceiveProps(nextProps) { | ||||
if(nextProps.response !== this.props.response) { | |||||
const { path, method, specActions, specSelectors, response, isShown } = nextProps | |||||
const resolvedSubtree = specSelectors.specResolvedSubtree(["paths", path, method]) | |||||
if(response !== this.props.response) { | |||||
this.setState({ executeInProgress: false }) | this.setState({ executeInProgress: false }) | ||||
} | } | ||||
if(isShown && resolvedSubtree === undefined) { | |||||
specActions.requestResolvedSubtree(["paths", path, method]) | |||||
} | |||||
} | } | ||||
toggleShown =() => { | toggleShown =() => { | ||||
let { layoutActions, tag, operationId, isShown } = this.props | |||||
let { layoutActions, specActions, tag, operationId, path, method, isShown } = this.props | |||||
if(!isShown) { | |||||
// transitioning from collapsed to expanded | |||||
specActions.requestResolvedSubtree(["paths", path, method]) | |||||
} | |||||
layoutActions.show(["operations", tag, operationId], !isShown) | layoutActions.show(["operations", tag, operationId], !isShown) | ||||
} | } | ||||
@@ -108,7 +119,7 @@ export default class OperationContainer extends PureComponent { | |||||
render() { | render() { | ||||
let { | let { | ||||
op, | |||||
op: unresolvedOp, | |||||
tag, | tag, | ||||
path, | path, | ||||
method, | method, | ||||
@@ -140,10 +151,14 @@ export default class OperationContainer extends PureComponent { | |||||
const Operation = getComponent( "operation" ) | const Operation = getComponent( "operation" ) | ||||
const resolvedSubtree = specSelectors.specResolvedSubtree(["paths", path, method]) || Map() | |||||
const operationProps = fromJS({ | const operationProps = fromJS({ | ||||
op, | |||||
op: resolvedSubtree || Map(), | |||||
tag, | tag, | ||||
path, | path, | ||||
summary: unresolvedOp.getIn(["operation", "summary"]) || "", | |||||
deprecated: resolvedSubtree.get("deprecated") || unresolvedOp.getIn(["operation", "deprecated"]) || false, | |||||
method, | method, | ||||
security, | security, | ||||
isAuthorized, | isAuthorized, | ||||
@@ -2,6 +2,7 @@ import React, { PureComponent, Component } from "react" | |||||
import PropTypes from "prop-types" | import PropTypes from "prop-types" | ||||
import { List, fromJS } from "immutable" | import { List, fromJS } from "immutable" | ||||
import ImPropTypes from "react-immutable-proptypes" | import ImPropTypes from "react-immutable-proptypes" | ||||
import DebounceInput from "react-debounce-input" | |||||
//import "less/json-schema-form" | //import "less/json-schema-form" | ||||
const noop = ()=> {} | const noop = ()=> {} | ||||
@@ -79,10 +80,13 @@ export class JsonSchema_string extends Component { | |||||
disabled={isDisabled}/>) | disabled={isDisabled}/>) | ||||
} | } | ||||
else { | else { | ||||
return (<Input type={ schema.format === "password" ? "password" : "text" } | |||||
return (<DebounceInput | |||||
type={ schema.format === "password" ? "password" : "text" } | |||||
className={ errors.length ? "invalid" : ""} | className={ errors.length ? "invalid" : ""} | ||||
title={ errors.length ? errors : ""} | title={ errors.length ? errors : ""} | ||||
value={value} | value={value} | ||||
minLength={0} | |||||
debounceTimeout={350} | |||||
placeholder={description} | placeholder={description} | ||||
onChange={ this.onChange } | onChange={ this.onChange } | ||||
disabled={isDisabled}/>) | disabled={isDisabled}/>) | ||||
@@ -4,7 +4,7 @@ import { escapeDeepLinkPath } from "core/utils" | |||||
let hasHashBeenParsed = false //TODO this forces code to only run once which may prevent scrolling if page not refreshed | let hasHashBeenParsed = false //TODO this forces code to only run once which may prevent scrolling if page not refreshed | ||||
export const updateResolved = (ori, { layoutActions, getConfigs }) => (...args) => { | |||||
export const updateJsonSpec = (ori, { layoutActions, getConfigs }) => (...args) => { | |||||
ori(...args) | ori(...args) | ||||
const isDeepLinkingEnabled = getConfigs().deepLinking | const isDeepLinkingEnabled = getConfigs().deepLinking | ||||
@@ -6,6 +6,7 @@ export const NEW_SPEC_ERR = "err_new_spec_err" | |||||
export const NEW_SPEC_ERR_BATCH = "err_new_spec_err_batch" | export const NEW_SPEC_ERR_BATCH = "err_new_spec_err_batch" | ||||
export const NEW_AUTH_ERR = "err_new_auth_err" | export const NEW_AUTH_ERR = "err_new_auth_err" | ||||
export const CLEAR = "err_clear" | export const CLEAR = "err_clear" | ||||
export const CLEAR_BY = "err_clear_by" | |||||
export function newThrownErr(err) { | export function newThrownErr(err) { | ||||
return { | return { | ||||
@@ -49,3 +50,11 @@ export function clear(filter = {}) { | |||||
payload: filter | payload: filter | ||||
} | } | ||||
} | } | ||||
export function clearBy(filter = () => true) { | |||||
// filter is a function | |||||
return { | |||||
type: CLEAR_BY, | |||||
payload: filter | |||||
} | |||||
} |
@@ -4,12 +4,11 @@ import { | |||||
NEW_SPEC_ERR, | NEW_SPEC_ERR, | ||||
NEW_SPEC_ERR_BATCH, | NEW_SPEC_ERR_BATCH, | ||||
NEW_AUTH_ERR, | NEW_AUTH_ERR, | ||||
CLEAR | |||||
CLEAR, | |||||
CLEAR_BY, | |||||
} from "./actions" | } from "./actions" | ||||
import reject from "lodash/reject" | |||||
import Im, { fromJS, List } from "immutable" | |||||
import { fromJS, List } from "immutable" | |||||
import transformErrors from "./error-transformers/hook" | import transformErrors from "./error-transformers/hook" | ||||
@@ -65,11 +64,34 @@ export default function(system) { | |||||
}, | }, | ||||
[CLEAR]: (state, { payload }) => { | [CLEAR]: (state, { payload }) => { | ||||
if(!payload) { | |||||
return | |||||
if(!payload || !state.get("errors")) { | |||||
return state | |||||
} | |||||
let newErrors = state.get("errors") | |||||
.filter(err => { | |||||
return err.keySeq().every(k => { | |||||
const errValue = err.get(k) | |||||
const filterValue = payload[k] | |||||
if(!filterValue) return true | |||||
return errValue !== filterValue | |||||
}) | |||||
}) | |||||
return state.merge({ | |||||
errors: newErrors | |||||
}) | |||||
}, | |||||
[CLEAR_BY]: (state, { payload }) => { | |||||
if(!payload || typeof payload !== "function") { | |||||
return state | |||||
} | } | ||||
// TODO: Rework, to use immutable only, no need for lodash | |||||
let newErrors = Im.fromJS(reject((state.get("errors") || List()).toJS(), payload)) | |||||
let newErrors = state.get("errors") | |||||
.filter(err => { | |||||
return payload(err) | |||||
}) | |||||
return state.merge({ | return state.merge({ | ||||
errors: newErrors | errors: newErrors | ||||
}) | }) | ||||
@@ -20,7 +20,7 @@ const state = state => { | |||||
return state || Map() | return state || Map() | ||||
} | } | ||||
const nullSelector = createSelector(() => null) | |||||
const nullSelector = createSelector(() => null) | |||||
const OAS3NullSelector = onlyOAS3(nullSelector) | const OAS3NullSelector = onlyOAS3(nullSelector) | ||||
@@ -1,6 +1,7 @@ | |||||
import YAML from "js-yaml" | import YAML from "js-yaml" | ||||
import parseUrl from "url-parse" | import parseUrl from "url-parse" | ||||
import serializeError from "serialize-error" | import serializeError from "serialize-error" | ||||
import { Map } from "immutable" | |||||
import isString from "lodash/isString" | import isString from "lodash/isString" | ||||
import { isJSONObject } from "core/utils" | import { isJSONObject } from "core/utils" | ||||
@@ -21,6 +22,7 @@ export const CLEAR_REQUEST = "spec_clear_request" | |||||
export const CLEAR_VALIDATE_PARAMS = "spec_clear_validate_param" | export const CLEAR_VALIDATE_PARAMS = "spec_clear_validate_param" | ||||
export const UPDATE_OPERATION_META_VALUE = "spec_update_operation_meta_value" | export const UPDATE_OPERATION_META_VALUE = "spec_update_operation_meta_value" | ||||
export const UPDATE_RESOLVED = "spec_update_resolved" | export const UPDATE_RESOLVED = "spec_update_resolved" | ||||
export const UPDATE_RESOLVED_SUBTREE = "spec_update_resolved_subtree" | |||||
export const SET_SCHEME = "set_scheme" | export const SET_SCHEME = "set_scheme" | ||||
const toStr = (str) => isString(str) ? str : "" | const toStr = (str) => isString(str) ? str : "" | ||||
@@ -74,7 +76,14 @@ export const parseToJson = (str) => ({specActions, specSelectors, errActions}) = | |||||
return {} | return {} | ||||
} | } | ||||
let hasWarnedAboutResolveSpecDeprecation = false | |||||
export const resolveSpec = (json, url) => ({specActions, specSelectors, errActions, fn: { fetch, resolve, AST }, getConfigs}) => { | export const resolveSpec = (json, url) => ({specActions, specSelectors, errActions, fn: { fetch, resolve, AST }, getConfigs}) => { | ||||
if(!hasWarnedAboutResolveSpecDeprecation) { | |||||
console.warn(`specActions.resolveSpec is deprecated since v3.10.0 and will be removed in v4.0.0; use resolveIn instead!`) | |||||
hasWarnedAboutResolveSpecDeprecation = true | |||||
} | |||||
const { | const { | ||||
modelPropertyMacro, | modelPropertyMacro, | ||||
parameterMacro, | parameterMacro, | ||||
@@ -124,6 +133,55 @@ export const resolveSpec = (json, url) => ({specActions, specSelectors, errActio | |||||
}) | }) | ||||
} | } | ||||
export const requestResolvedSubtree = path => system => { | |||||
const { | |||||
errActions, | |||||
fn: { | |||||
resolveSubtree, | |||||
AST: { getLineNumberForPath } | |||||
}, | |||||
specSelectors, | |||||
specActions, | |||||
} = system | |||||
const specStr = specSelectors.specStr() | |||||
if(!resolveSubtree) { | |||||
console.error("Error: Swagger-Client did not provide a `resolveSubtree` method, doing nothing.") | |||||
return | |||||
} | |||||
const currentValue = specSelectors.specResolvedSubtree(path) | |||||
if(currentValue) { | |||||
return | |||||
} | |||||
return resolveSubtree(specSelectors.specJson().toJS(), path) | |||||
.then(({ spec, errors }) => { | |||||
errActions.clear({ | |||||
type: "thrown" | |||||
}) | |||||
if(Array.isArray(errors) && errors.length > 0) { | |||||
let preparedErrors = errors | |||||
.map(err => { | |||||
console.error(err) | |||||
err.line = err.fullPath ? getLineNumberForPath(specStr, err.fullPath) : null | |||||
err.path = err.fullPath ? err.fullPath.join(".") : null | |||||
err.level = "error" | |||||
err.type = "thrown" | |||||
err.source = "resolver" | |||||
Object.defineProperty(err, "message", { enumerable: true, value: err.message }) | |||||
return err | |||||
}) | |||||
errActions.newThrownErrBatch(preparedErrors) | |||||
} | |||||
return specActions.updateResolvedSubtree(path, spec) | |||||
}) | |||||
.catch(e => console.error(e)) | |||||
} | |||||
export function changeParam( path, paramName, paramIn, value, isXml ){ | export function changeParam( path, paramName, paramIn, value, isXml ){ | ||||
return { | return { | ||||
type: UPDATE_PARAM, | type: UPDATE_PARAM, | ||||
@@ -131,6 +189,23 @@ export function changeParam( path, paramName, paramIn, value, isXml ){ | |||||
} | } | ||||
} | } | ||||
export const updateResolvedSubtree = (path, value) => { | |||||
return { | |||||
type: UPDATE_RESOLVED_SUBTREE, | |||||
payload: { path, value } | |||||
} | |||||
} | |||||
export const invalidateResolvedSubtreeCache = () => { | |||||
return { | |||||
type: UPDATE_RESOLVED_SUBTREE, | |||||
payload: { | |||||
path: [], | |||||
value: Map() | |||||
} | |||||
} | |||||
} | |||||
export const validateParams = ( payload, isOAS3 ) =>{ | export const validateParams = ( payload, isOAS3 ) =>{ | ||||
return { | return { | ||||
type: VALIDATE_PARAMS, | type: VALIDATE_PARAMS, | ||||
@@ -251,6 +326,7 @@ export const executeRequest = (req) => | |||||
// track duration of request | // track duration of request | ||||
const startTime = Date.now() | const startTime = Date.now() | ||||
return fn.execute(req) | return fn.execute(req) | ||||
.then( res => { | .then( res => { | ||||
res.duration = Date.now() - startTime | res.duration = Date.now() - startTime | ||||
@@ -267,13 +343,22 @@ export const executeRequest = (req) => | |||||
// I'm using extras as a way to inject properties into the final, `execute` method - It's not great. Anyone have a better idea? @ponelat | // I'm using extras as a way to inject properties into the final, `execute` method - It's not great. Anyone have a better idea? @ponelat | ||||
export const execute = ( { path, method, ...extras }={} ) => (system) => { | export const execute = ( { path, method, ...extras }={} ) => (system) => { | ||||
let { fn:{fetch}, specSelectors, specActions } = system | let { fn:{fetch}, specSelectors, specActions } = system | ||||
let spec = specSelectors.spec().toJS() | |||||
let spec = specSelectors.specJsonWithResolvedSubtrees().toJS() | |||||
let scheme = specSelectors.operationScheme(path, method) | let scheme = specSelectors.operationScheme(path, method) | ||||
let { requestContentType, responseContentType } = specSelectors.contentTypeValues([path, method]).toJS() | let { requestContentType, responseContentType } = specSelectors.contentTypeValues([path, method]).toJS() | ||||
let isXml = /xml/i.test(requestContentType) | let isXml = /xml/i.test(requestContentType) | ||||
let parameters = specSelectors.parameterValues([path, method], isXml).toJS() | let parameters = specSelectors.parameterValues([path, method], isXml).toJS() | ||||
return specActions.executeRequest({fetch, spec, pathName: path, method, parameters, requestContentType, scheme, responseContentType, ...extras }) | |||||
return specActions.executeRequest({ | |||||
...extras, | |||||
fetch, | |||||
spec, | |||||
pathName: path, | |||||
method, parameters, | |||||
requestContentType, | |||||
scheme, | |||||
responseContentType | |||||
}) | |||||
} | } | ||||
export function clearResponse (path, method) { | export function clearResponse (path, method) { | ||||
@@ -1,7 +1,12 @@ | |||||
import { fromJS } from "immutable" | |||||
import { fromJS, List } from "immutable" | |||||
import { fromJSOrdered, validateParam } from "core/utils" | import { fromJSOrdered, validateParam } from "core/utils" | ||||
import win from "../../window" | import win from "../../window" | ||||
// selector-in-reducer is suboptimal, but `operationWithMeta` is more of a helper | |||||
import { | |||||
operationWithMeta | |||||
} from "./selectors" | |||||
import { | import { | ||||
UPDATE_SPEC, | UPDATE_SPEC, | ||||
UPDATE_URL, | UPDATE_URL, | ||||
@@ -12,6 +17,7 @@ import { | |||||
SET_REQUEST, | SET_REQUEST, | ||||
SET_MUTATED_REQUEST, | SET_MUTATED_REQUEST, | ||||
UPDATE_RESOLVED, | UPDATE_RESOLVED, | ||||
UPDATE_RESOLVED_SUBTREE, | |||||
UPDATE_OPERATION_META_VALUE, | UPDATE_OPERATION_META_VALUE, | ||||
CLEAR_RESPONSE, | CLEAR_RESPONSE, | ||||
CLEAR_REQUEST, | CLEAR_REQUEST, | ||||
@@ -39,38 +45,38 @@ export default { | |||||
return state.setIn(["resolved"], fromJSOrdered(action.payload)) | return state.setIn(["resolved"], fromJSOrdered(action.payload)) | ||||
}, | }, | ||||
[UPDATE_RESOLVED_SUBTREE]: (state, action) => { | |||||
const { value, path } = action.payload | |||||
return state.setIn(["resolvedSubtrees", ...path], fromJSOrdered(value)) | |||||
}, | |||||
[UPDATE_PARAM]: ( state, {payload} ) => { | [UPDATE_PARAM]: ( state, {payload} ) => { | ||||
let { path, paramName, paramIn, value, isXml } = payload | |||||
return state.updateIn( [ "resolved", "paths", ...path, "parameters" ], fromJS([]), parameters => { | |||||
const index = parameters.findIndex(p => p.get( "name" ) === paramName && p.get("in") === paramIn ) | |||||
if (!(value instanceof win.File)) { | |||||
value = fromJSOrdered( value ) | |||||
} | |||||
return parameters.setIn( [ index, isXml ? "value_xml" : "value" ], value) | |||||
}) | |||||
let { path: pathMethod, paramName, paramIn, value, isXml } = payload | |||||
const valueKey = isXml ? "value_xml" : "value" | |||||
return state.setIn( | |||||
["meta", "paths", ...pathMethod, "parameters", `${paramName}.${paramIn}`, valueKey], | |||||
value | |||||
) | |||||
}, | }, | ||||
[VALIDATE_PARAMS]: ( state, { payload: { pathMethod, isOAS3 } } ) => { | [VALIDATE_PARAMS]: ( state, { payload: { pathMethod, isOAS3 } } ) => { | ||||
let meta = state.getIn( [ "meta", "paths", ...pathMethod ], fromJS({}) ) | let meta = state.getIn( [ "meta", "paths", ...pathMethod ], fromJS({}) ) | ||||
let isXml = /xml/i.test(meta.get("consumes_value")) | let isXml = /xml/i.test(meta.get("consumes_value")) | ||||
return state.updateIn( [ "resolved", "paths", ...pathMethod, "parameters" ], fromJS([]), parameters => { | |||||
return parameters.withMutations( parameters => { | |||||
for ( let i = 0, len = parameters.count(); i < len; i++ ) { | |||||
let errors = validateParam(parameters.get(i), isXml, isOAS3) | |||||
parameters.setIn([i, "errors"], fromJS(errors)) | |||||
} | |||||
}) | |||||
const op = operationWithMeta(state, ...pathMethod) | |||||
return state.updateIn(["meta", "paths", ...pathMethod, "parameters"], fromJS({}), paramMeta => { | |||||
return op.get("parameters", List()).reduce((res, param) => { | |||||
const errors = validateParam(param, isXml, isOAS3) | |||||
return res.setIn([`${param.get("name")}.${param.get("in")}`, "errors"], fromJS(errors)) | |||||
}, paramMeta) | |||||
}) | }) | ||||
}, | }, | ||||
[CLEAR_VALIDATE_PARAMS]: ( state, { payload: { pathMethod } } ) => { | [CLEAR_VALIDATE_PARAMS]: ( state, { payload: { pathMethod } } ) => { | ||||
return state.updateIn( [ "resolved", "paths", ...pathMethod, "parameters" ], fromJS([]), parameters => { | |||||
return parameters.withMutations( parameters => { | |||||
for ( let i = 0, len = parameters.count(); i < len; i++ ) { | |||||
parameters.setIn([i, "errors"], fromJS([])) | |||||
} | |||||
}) | |||||
return state.updateIn( [ "meta", "paths", ...pathMethod, "parameters" ], fromJS([]), parameters => { | |||||
return parameters.map(param => param.set("errors", fromJS([]))) | |||||
}) | }) | ||||
}, | }, | ||||
@@ -109,10 +115,10 @@ export default { | |||||
[UPDATE_OPERATION_META_VALUE]: (state, { payload: { path, value, key } }) => { | [UPDATE_OPERATION_META_VALUE]: (state, { payload: { path, value, key } }) => { | ||||
// path is a pathMethod tuple... can't change the name now. | // path is a pathMethod tuple... can't change the name now. | ||||
let operationPath = ["resolved", "paths", ...path] | |||||
let operationPath = ["paths", ...path] | |||||
let metaPath = ["meta", "paths", ...path] | let metaPath = ["meta", "paths", ...path] | ||||
if(!state.getIn(operationPath)) { | |||||
if(!state.getIn(["json", ...operationPath]) && !state.getIn(["resolved", ...operationPath])) { | |||||
// do nothing if the operation does not exist | // do nothing if the operation does not exist | ||||
return state | return state | ||||
} | } | ||||
@@ -42,9 +42,18 @@ export const specResolved = createSelector( | |||||
spec => spec.get("resolved", Map()) | spec => spec.get("resolved", Map()) | ||||
) | ) | ||||
export const specResolvedSubtree = (state, path) => { | |||||
return state.getIn(["resolvedSubtrees", ...path], undefined) | |||||
} | |||||
export const specJsonWithResolvedSubtrees = createSelector( | |||||
state, | |||||
spec => Map().merge(spec.get("json"), spec.get("resolvedSubtrees")) | |||||
) | |||||
// Default Spec ( as an object ) | // Default Spec ( as an object ) | ||||
export const spec = state => { | export const spec = state => { | ||||
let res = specResolved(state) | |||||
let res = specJson(state) | |||||
return res | return res | ||||
} | } | ||||
@@ -137,7 +146,9 @@ export const securityDefinitions = createSelector( | |||||
export const findDefinition = ( state, name ) => { | export const findDefinition = ( state, name ) => { | ||||
return specResolved(state).getIn(["definitions", name], null) | |||||
const resolvedRes = state.getIn(["resolvedSubtrees", "definitions", name], null) | |||||
const unresolvedRes = state.getIn(["json", "definitions", name], null) | |||||
return resolvedRes || unresolvedRes || null | |||||
} | } | ||||
export const definitions = createSelector( | export const definitions = createSelector( | ||||
@@ -261,10 +272,40 @@ export const allowTryItOutFor = () => { | |||||
return true | return true | ||||
} | } | ||||
export const operationWithMeta = (state, path, method) => { | |||||
const op = specJsonWithResolvedSubtrees(state).getIn(["paths", path, method], Map()) | |||||
const meta = state.getIn(["meta", "paths", path, method], Map()) | |||||
const mergedParams = op.get("parameters", List()).map((param) => { | |||||
return Map().merge( | |||||
param, | |||||
meta.getIn(["parameters", `${param.get("name")}.${param.get("in")}`]) | |||||
) | |||||
}) | |||||
return Map() | |||||
.merge(op, meta) | |||||
.set("parameters", mergedParams) | |||||
} | |||||
export const parameterWithMeta = (state, pathMethod, paramName, paramIn) => { | |||||
const opParams = specJsonWithResolvedSubtrees(state).getIn(["paths", ...pathMethod, "parameters"], Map()) | |||||
const metaParams = state.getIn(["meta", "paths", ...pathMethod, "parameters"], Map()) | |||||
const mergedParams = opParams.map((param) => { | |||||
return Map().merge( | |||||
param, | |||||
metaParams.get(`${param.get("name")}.${param.get("in")}`) | |||||
) | |||||
}) | |||||
return mergedParams.find(param => param.get("in") === paramIn && param.get("name") === paramName, Map()) | |||||
} | |||||
// Get the parameter value by parameter name | // Get the parameter value by parameter name | ||||
export function getParameter(state, pathMethod, name, inType) { | export function getParameter(state, pathMethod, name, inType) { | ||||
pathMethod = pathMethod || [] | pathMethod = pathMethod || [] | ||||
let params = spec(state).getIn(["paths", ...pathMethod, "parameters"], fromJS([])) | |||||
let params = state.getIn(["meta", "paths", ...pathMethod, "parameters"], fromJS([])) | |||||
return params.find( (p) => { | return params.find( (p) => { | ||||
return Map.isMap(p) && p.get("name") === name && p.get("in") === inType | return Map.isMap(p) && p.get("name") === name && p.get("in") === inType | ||||
}) || Map() // Always return a map | }) || Map() // Always return a map | ||||
@@ -281,8 +322,9 @@ export const hasHost = createSelector( | |||||
// Get the parameter values, that the user filled out | // Get the parameter values, that the user filled out | ||||
export function parameterValues(state, pathMethod, isXml) { | export function parameterValues(state, pathMethod, isXml) { | ||||
pathMethod = pathMethod || [] | pathMethod = pathMethod || [] | ||||
let params = spec(state).getIn(["paths", ...pathMethod, "parameters"], fromJS([])) | |||||
return params.reduce( (hash, p) => { | |||||
// let paramValues = state.getIn(["meta", "paths", ...pathMethod, "parameters"], fromJS([])) | |||||
let paramValues = operationWithMeta(state, ...pathMethod).get("parameters", List()) | |||||
return paramValues.reduce( (hash, p) => { | |||||
let value = isXml && p.get("in") === "body" ? p.get("value_xml") : p.get("value") | let value = isXml && p.get("in") === "body" ? p.get("value_xml") : p.get("value") | ||||
return hash.set(`${p.get("in")}.${p.get("name")}`, value) | return hash.set(`${p.get("in")}.${p.get("name")}`, value) | ||||
}, fromJS({})) | }, fromJS({})) | ||||
@@ -305,7 +347,7 @@ export function parametersIncludeType(parameters, typeValue="") { | |||||
// Get the consumes/produces value that the user selected | // Get the consumes/produces value that the user selected | ||||
export function contentTypeValues(state, pathMethod) { | export function contentTypeValues(state, pathMethod) { | ||||
pathMethod = pathMethod || [] | pathMethod = pathMethod || [] | ||||
let op = spec(state).getIn(["paths", ...pathMethod], fromJS({})) | |||||
let op = specJsonWithResolvedSubtrees(state).getIn(["paths", ...pathMethod], fromJS({})) | |||||
let meta = state.getIn(["meta", "paths", ...pathMethod], fromJS({})) | let meta = state.getIn(["meta", "paths", ...pathMethod], fromJS({})) | ||||
let producesValue = currentProducesFor(state, pathMethod) | let producesValue = currentProducesFor(state, pathMethod) | ||||
@@ -327,14 +369,14 @@ export function contentTypeValues(state, pathMethod) { | |||||
// Get the consumes/produces by path | // Get the consumes/produces by path | ||||
export function operationConsumes(state, pathMethod) { | export function operationConsumes(state, pathMethod) { | ||||
pathMethod = pathMethod || [] | pathMethod = pathMethod || [] | ||||
return spec(state).getIn(["paths", ...pathMethod, "consumes"], fromJS({})) | |||||
return state.getIn(["meta", ...pathMethod, "consumes"], fromJS({})) | |||||
} | } | ||||
// Get the currently selected produces value for an operation | // Get the currently selected produces value for an operation | ||||
export function currentProducesFor(state, pathMethod) { | export function currentProducesFor(state, pathMethod) { | ||||
pathMethod = pathMethod || [] | pathMethod = pathMethod || [] | ||||
const operation = spec(state).getIn(["paths", ...pathMethod], null) | |||||
const operation = specJsonWithResolvedSubtrees(state).getIn([ "paths", ...pathMethod], null) | |||||
if(operation === null) { | if(operation === null) { | ||||
// return nothing if the operation does not exist | // return nothing if the operation does not exist | ||||
@@ -362,10 +404,10 @@ export const canExecuteScheme = ( state, path, method ) => { | |||||
export const validateBeforeExecute = ( state, pathMethod ) => { | export const validateBeforeExecute = ( state, pathMethod ) => { | ||||
pathMethod = pathMethod || [] | pathMethod = pathMethod || [] | ||||
let params = spec(state).getIn(["paths", ...pathMethod, "parameters"], fromJS([])) | |||||
let paramValues = state.getIn(["meta", "paths", ...pathMethod, "parameters"], fromJS([])) | |||||
let isValid = true | let isValid = true | ||||
params.forEach( (p) => { | |||||
paramValues.forEach( (p) => { | |||||
let errors = p.get("errors") | let errors = p.get("errors") | ||||
if ( errors && errors.count() ) { | if ( errors && errors.count() ) { | ||||
isValid = false | isValid = false | ||||
@@ -5,7 +5,7 @@ export const updateSpec = (ori, {specActions}) => (...args) => { | |||||
export const updateJsonSpec = (ori, {specActions}) => (...args) => { | export const updateJsonSpec = (ori, {specActions}) => (...args) => { | ||||
ori(...args) | ori(...args) | ||||
specActions.resolveSpec(...args) | |||||
specActions.invalidateResolvedSubtreeCache() | |||||
} | } | ||||
// Log the request ( just for debugging, shouldn't affect prod ) | // Log the request ( just for debugging, shouldn't affect prod ) | ||||
@@ -16,4 +16,4 @@ export const executeRequest = (ori, { specActions }) => (req) => { | |||||
export const validateParams = (ori, { specSelectors }) => (req) => { | export const validateParams = (ori, { specSelectors }) => (req) => { | ||||
return ori(req, specSelectors.isOAS3()) | return ori(req, specSelectors.isOAS3()) | ||||
} | |||||
} |
@@ -7,6 +7,7 @@ module.exports = function({ configs }) { | |||||
buildRequest: Swagger.buildRequest, | buildRequest: Swagger.buildRequest, | ||||
execute: Swagger.execute, | execute: Swagger.execute, | ||||
resolve: Swagger.resolve, | resolve: Swagger.resolve, | ||||
resolveSubtree: Swagger.resolveSubtree, | |||||
serializeRes: Swagger.serializeRes, | serializeRes: Swagger.serializeRes, | ||||
opId: Swagger.helpers.opId | opId: Swagger.helpers.opId | ||||
} | } | ||||
@@ -198,6 +198,7 @@ section.models | |||||
.model-box | .model-box | ||||
{ | { | ||||
padding: 10px; | padding: 10px; | ||||
display: inline-block; | |||||
border-radius: 4px; | border-radius: 4px; | ||||
background: rgba($section-models-model-box-background-color,.1); | background: rgba($section-models-model-box-background-color,.1); | ||||
@@ -24,7 +24,8 @@ describe("<Models/>", function(){ | |||||
def1: {}, | def1: {}, | ||||
def2: {} | def2: {} | ||||
}) | }) | ||||
} | |||||
}, | |||||
specResolvedSubtree: () => {} | |||||
}, | }, | ||||
layoutSelectors: { | layoutSelectors: { | ||||
isShown: createSpy() | isShown: createSpy() | ||||
@@ -177,6 +177,10 @@ describe("spec plugin - actions", function(){ | |||||
}) | }) | ||||
}) | }) | ||||
describe("requestResolvedSubtree", () => { | |||||
it("should return a promise ") | |||||
}) | |||||
it.skip("should call errActions.newErr, if the fn.execute rejects", function(){ | it.skip("should call errActions.newErr, if the fn.execute rejects", function(){ | ||||
}) | }) | ||||
@@ -24,7 +24,7 @@ describe("spec plugin - selectors", function(){ | |||||
// Given | // Given | ||||
const spec = fromJS({ | const spec = fromJS({ | ||||
resolved: { | |||||
json: { | |||||
paths: { | paths: { | ||||
"/one": { | "/one": { | ||||
get: { | get: { | ||||
@@ -55,7 +55,7 @@ describe("spec plugin - selectors", function(){ | |||||
it("should return { requestContentType, responseContentType } from an operation", function(){ | it("should return { requestContentType, responseContentType } from an operation", function(){ | ||||
// Given | // Given | ||||
let state = fromJS({ | let state = fromJS({ | ||||
resolved: { | |||||
json: { | |||||
paths: { | paths: { | ||||
"/one": { | "/one": { | ||||
get: {} | get: {} | ||||
@@ -86,7 +86,7 @@ describe("spec plugin - selectors", function(){ | |||||
it("should default to the first `produces` array value if current is not set", function(){ | it("should default to the first `produces` array value if current is not set", function(){ | ||||
// Given | // Given | ||||
let state = fromJS({ | let state = fromJS({ | ||||
resolved: { | |||||
json: { | |||||
paths: { | paths: { | ||||
"/one": { | "/one": { | ||||
get: { | get: { | ||||
@@ -121,7 +121,7 @@ describe("spec plugin - selectors", function(){ | |||||
it("should default to `application/json` if a default produces value is not available", function(){ | it("should default to `application/json` if a default produces value is not available", function(){ | ||||
// Given | // Given | ||||
let state = fromJS({ | let state = fromJS({ | ||||
resolved: { | |||||
json: { | |||||
paths: { | paths: { | ||||
"/one": { | "/one": { | ||||
get: {} | get: {} | ||||
@@ -151,7 +151,7 @@ describe("spec plugin - selectors", function(){ | |||||
it("should prioritize consumes value first from an operation", function(){ | it("should prioritize consumes value first from an operation", function(){ | ||||
// Given | // Given | ||||
let state = fromJS({ | let state = fromJS({ | ||||
resolved: { | |||||
json: { | |||||
paths: { | paths: { | ||||
"/one": { | "/one": { | ||||
get: { | get: { | ||||
@@ -182,7 +182,7 @@ describe("spec plugin - selectors", function(){ | |||||
it("should fallback to multipart/form-data if there is no consumes value but there is a file parameter", function(){ | it("should fallback to multipart/form-data if there is no consumes value but there is a file parameter", function(){ | ||||
// Given | // Given | ||||
let state = fromJS({ | let state = fromJS({ | ||||
resolved: { | |||||
json: { | |||||
paths: { | paths: { | ||||
"/one": { | "/one": { | ||||
get: { | get: { | ||||
@@ -204,7 +204,7 @@ describe("spec plugin - selectors", function(){ | |||||
it("should fallback to application/x-www-form-urlencoded if there is no consumes value, no file parameter, but there is a formData parameter", function(){ | it("should fallback to application/x-www-form-urlencoded if there is no consumes value, no file parameter, but there is a formData parameter", function(){ | ||||
// Given | // Given | ||||
let state = fromJS({ | let state = fromJS({ | ||||
resolved: { | |||||
json: { | |||||
paths: { | paths: { | ||||
"/one": { | "/one": { | ||||
get: { | get: { | ||||
@@ -244,7 +244,7 @@ describe("spec plugin - selectors", function(){ | |||||
// Given | // Given | ||||
let state = fromJS({ | let state = fromJS({ | ||||
url: "https://generator.swagger.io/api/swagger.json", | url: "https://generator.swagger.io/api/swagger.json", | ||||
resolved: { | |||||
json: { | |||||
paths: { | paths: { | ||||
"/one": { | "/one": { | ||||
get: { | get: { | ||||