@@ -151,6 +151,8 @@ domNode | The HTML DOM element inside which SwaggerUi will put the user interfac | |||
oauth2RedirectUrl | OAuth redirect URL | |||
tagsSorter | Apply a sort to the tag list of each API. It can be 'alpha' (sort by paths alphanumerically) or a function (see [Array.prototype.sort()](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/sort) to learn how to write a sort function). Two tag name strings are passed to the sorter for each pass. Default is the order determined by Swagger-UI. | |||
operationsSorter | Apply a sort to the operation list of each API. It can be 'alpha' (sort by paths alphanumerically), 'method' (sort by HTTP method) or a function (see Array.prototype.sort() to know how sort function works). Default is the order returned by the server unchanged. | |||
defaultModelRendering | Controls how models are shown when the API is first rendered. (The user can always switch the rendering for a given model by clicking the 'Model' and 'Example Value' links.) It can be set to 'model' or 'example', and the default is 'example'. | |||
defaultModelExpandDepth | The default expansion depth for models. The default value is 1. | |||
configUrl | Configs URL | |||
parameterMacro | MUST be a function. Function to set default value to parameters. Accepts two arguments parameterMacro(operation, parameter). Operation and parameter are objects passed for context, both remain immutable | |||
modelPropertyMacro | MUST be a function. Function to set default values to each property in model. Accepts one argument modelPropertyMacro(property), property is immutable | |||
@@ -7,14 +7,19 @@ export default class ModelExample extends React.Component { | |||
specSelectors: PropTypes.object.isRequired, | |||
schema: PropTypes.object.isRequired, | |||
example: PropTypes.any.isRequired, | |||
isExecute: PropTypes.bool | |||
isExecute: PropTypes.bool, | |||
getConfigs: PropTypes.func.isRequired | |||
} | |||
constructor(props, context) { | |||
super(props, context) | |||
let { getConfigs } = this.props | |||
let { defaultModelRendering } = getConfigs() | |||
if (defaultModelRendering !== "example" && defaultModelRendering !== "model") { | |||
defaultModelRendering = "example" | |||
} | |||
this.state = { | |||
activeTab: "example" | |||
activeTab: defaultModelRendering | |||
} | |||
} | |||
@@ -27,7 +32,8 @@ export default class ModelExample extends React.Component { | |||
} | |||
render() { | |||
let { getComponent, specSelectors, schema, example, isExecute } = this.props | |||
let { getComponent, specSelectors, schema, example, isExecute, getConfigs } = this.props | |||
let { defaultModelExpandDepth } = getConfigs() | |||
const ModelWrapper = getComponent("ModelWrapper") | |||
return <div> | |||
@@ -47,7 +53,7 @@ export default class ModelExample extends React.Component { | |||
!isExecute && this.state.activeTab === "model" && <ModelWrapper schema={ schema } | |||
getComponent={ getComponent } | |||
specSelectors={ specSelectors } | |||
expandDepth={ 1 } /> | |||
expandDepth={ defaultModelExpandDepth } /> | |||
} | |||
@@ -13,7 +13,7 @@ export default class Models extends Component { | |||
render(){ | |||
let { specSelectors, getComponent, layoutSelectors, layoutActions, getConfigs } = this.props | |||
let definitions = specSelectors.definitions() | |||
let { docExpansion } = getConfigs() | |||
let { docExpansion, defaultModelExpandDepth } = getConfigs() | |||
let showModels = layoutSelectors.isShown("models", docExpansion === "full" || docExpansion === "list" ) | |||
const ModelWrapper = getComponent("ModelWrapper") | |||
@@ -33,6 +33,7 @@ export default class Models extends Component { | |||
definitions.entrySeq().map( ( [ name, model ])=>{ | |||
return <div className="model-container" key={ `models-section-${name}` }> | |||
<ModelWrapper name={ name } | |||
expandDepth={ defaultModelExpandDepth } | |||
schema={ model } | |||
isRef={ true } | |||
getComponent={ getComponent } | |||
@@ -222,6 +222,7 @@ export default class Operation extends PureComponent { | |||
specActions={ specActions } | |||
specSelectors={ specSelectors } | |||
pathMethod={ [path, method] } | |||
getConfigs={ getConfigs } | |||
/> | |||
{!tryItOutEnabled || !allowTryItOut ? null : schemes && schemes.size ? <div className="opblock-schemes"> | |||
@@ -11,7 +11,8 @@ export default class ParameterRow extends Component { | |||
isExecute: PropTypes.bool, | |||
onChangeConsumes: PropTypes.func.isRequired, | |||
specSelectors: PropTypes.object.isRequired, | |||
pathMethod: PropTypes.array.isRequired | |||
pathMethod: PropTypes.array.isRequired, | |||
getConfigs: PropTypes.func.isRequired | |||
} | |||
constructor(props, context) { | |||
@@ -56,7 +57,7 @@ export default class ParameterRow extends Component { | |||
} | |||
render() { | |||
let {param, onChange, getComponent, isExecute, fn, onChangeConsumes, specSelectors, pathMethod} = this.props | |||
let {param, onChange, getComponent, getConfigs, isExecute, fn, onChangeConsumes, specSelectors, pathMethod} = this.props | |||
let { isOAS3 } = specSelectors | |||
@@ -121,6 +122,7 @@ export default class ParameterRow extends Component { | |||
{ | |||
bodyParam && schema ? <ModelExample getComponent={ getComponent } | |||
getConfigs={ getConfigs } | |||
isExecute={ isExecute } | |||
specSelectors={ specSelectors } | |||
schema={ schema } | |||
@@ -19,7 +19,8 @@ export default class Parameters extends Component { | |||
onTryoutClick: PropTypes.func, | |||
onCancelClick: PropTypes.func, | |||
onChangeKey: PropTypes.array, | |||
pathMethod: PropTypes.array.isRequired | |||
pathMethod: PropTypes.array.isRequired, | |||
getConfigs: PropTypes.func.isRequired | |||
} | |||
@@ -60,6 +61,7 @@ export default class Parameters extends Component { | |||
fn, | |||
getComponent, | |||
getConfigs, | |||
specSelectors, | |||
pathMethod | |||
} = this.props | |||
@@ -93,6 +95,7 @@ export default class Parameters extends Component { | |||
eachMap(parameters, (parameter) => ( | |||
<ParameterRow fn={ fn } | |||
getComponent={ getComponent } | |||
getConfigs={ getConfigs } | |||
param={ parameter } | |||
key={ parameter.get( "name" ) } | |||
onChange={ this.onChange } | |||
@@ -44,6 +44,7 @@ export default class Response extends React.Component { | |||
response: PropTypes.object, | |||
className: PropTypes.string, | |||
getComponent: PropTypes.func.isRequired, | |||
getConfigs: PropTypes.func.isRequired, | |||
specSelectors: PropTypes.object.isRequired, | |||
fn: PropTypes.object.isRequired, | |||
contentType: PropTypes.string | |||
@@ -61,6 +62,7 @@ export default class Response extends React.Component { | |||
fn, | |||
getComponent, | |||
getConfigs, | |||
specSelectors, | |||
contentType | |||
} = this.props | |||
@@ -116,6 +118,7 @@ export default class Response extends React.Component { | |||
{ example ? ( | |||
<ModelExample | |||
getComponent={ getComponent } | |||
getConfigs={ getConfigs } | |||
specSelectors={ specSelectors } | |||
schema={ fromJS(schema) } | |||
example={ example }/> | |||
@@ -12,12 +12,12 @@ export default class Responses extends React.Component { | |||
produces: PropTypes.object, | |||
producesValue: PropTypes.any, | |||
getComponent: PropTypes.func.isRequired, | |||
getConfigs: PropTypes.func.isRequired, | |||
specSelectors: PropTypes.object.isRequired, | |||
specActions: PropTypes.object.isRequired, | |||
pathMethod: PropTypes.array.isRequired, | |||
displayRequestDuration: PropTypes.bool.isRequired, | |||
fn: PropTypes.object.isRequired, | |||
getConfigs: PropTypes.func.isRequired | |||
fn: PropTypes.object.isRequired | |||
} | |||
static defaultProps = { | |||
@@ -89,6 +89,7 @@ export default class Responses extends React.Component { | |||
response={ response } | |||
specSelectors={ specSelectors } | |||
contentType={ producesValue } | |||
getConfigs={ getConfigs } | |||
getComponent={ getComponent }/> | |||
) | |||
}).toArray() | |||
@@ -45,6 +45,8 @@ module.exports = function SwaggerUI(opts) { | |||
requestInterceptor: (a => a), | |||
responseInterceptor: (a => a), | |||
showMutatedRequest: true, | |||
defaultModelRendering: "example", | |||
defaultModelExpandDepth: 1, | |||
// Initial set of plugins ( TODO rename this, or refactor - we don't need presets _and_ plugins. Its just there for performance. | |||
// Instead, we can compile the first plugin ( it can be a collection of plugins ), then batch the rest. | |||
@@ -0,0 +1,116 @@ | |||
/* eslint-env mocha */ | |||
import React from "react" | |||
import expect, { createSpy } from "expect" | |||
import { shallow } from "enzyme" | |||
import ModelExample from "components/model-example" | |||
import ModelComponent from "components/model-wrapper" | |||
describe("<ModelExample/>", function(){ | |||
// Given | |||
let components = { | |||
ModelWrapper: ModelComponent | |||
} | |||
let props = { | |||
getComponent: (c) => { | |||
return components[c] | |||
}, | |||
specSelectors: {}, | |||
schema: {}, | |||
example: "{\"example\": \"value\"}", | |||
isExecute: false, | |||
getConfigs: () => ({ | |||
defaultModelRendering: "model", | |||
defaultModelExpandDepth: 1 | |||
}) | |||
} | |||
let exampleSelectedTestInputs = [ | |||
{ defaultModelRendering: "model", isExecute: true }, | |||
{ defaultModelRendering: "example", isExecute: true }, | |||
{ defaultModelRendering: "example", isExecute: false }, | |||
{ defaultModelRendering: "othervalue", isExecute: true }, | |||
{ defaultModelRendering: "othervalue", isExecute: false } | |||
] | |||
let modelSelectedTestInputs = [ | |||
{ defaultModelRendering: "model", isExecute: false } | |||
] | |||
it("renders model and example tabs", function(){ | |||
// When | |||
let wrapper = shallow(<ModelExample {...props}/>) | |||
// Then should render tabs | |||
expect(wrapper.find("div > ul.tab").length).toEqual(1) | |||
let tabs = wrapper.find("div > ul.tab").children() | |||
expect(tabs.length).toEqual(2) | |||
tabs.forEach((node) => { | |||
expect(node.length).toEqual(1) | |||
expect(node.name()).toEqual("li") | |||
expect(node.hasClass("tabitem")).toEqual(true) | |||
}) | |||
expect(tabs.at(0).text()).toEqual("Example Value") | |||
expect(tabs.at(1).text()).toEqual("Model") | |||
}) | |||
exampleSelectedTestInputs.forEach(function(testInputs) { | |||
it("example tab is selected if isExecute = " + testInputs.isExecute + " and defaultModelRendering = " + testInputs.defaultModelRendering, function(){ | |||
// When | |||
props.isExecute = testInputs.isExecute | |||
props.getConfigs = () => ({ | |||
defaultModelRendering: testInputs.defaultModelRendering, | |||
defaultModelExpandDepth: 1 | |||
}) | |||
let wrapper = shallow(<ModelExample {...props}/>) | |||
// Then | |||
let tabs = wrapper.find("div > ul.tab").children() | |||
let exampleTab = tabs.at(0) | |||
expect(exampleTab.hasClass("active")).toEqual(true) | |||
let modelTab = tabs.at(1) | |||
expect(modelTab.hasClass("active")).toEqual(false) | |||
expect(wrapper.find("div > div").length).toEqual(1) | |||
expect(wrapper.find("div > div").text()).toEqual(props.example) | |||
}) | |||
}) | |||
modelSelectedTestInputs.forEach(function(testInputs) { | |||
it("model tab is selected if isExecute = " + testInputs.isExecute + " and defaultModelRendering = " + testInputs.defaultModelRendering, function(){ | |||
// When | |||
props.isExecute = testInputs.isExecute | |||
props.getConfigs = () => ({ | |||
defaultModelRendering: testInputs.defaultModelRendering, | |||
defaultModelExpandDepth: 1 | |||
}) | |||
let wrapper = shallow(<ModelExample {...props}/>) | |||
// Then | |||
let tabs = wrapper.find("div > ul.tab").children() | |||
let exampleTab = tabs.at(0) | |||
expect(exampleTab.hasClass("active")).toEqual(false) | |||
let modelTab = tabs.at(1) | |||
expect(modelTab.hasClass("active")).toEqual(true) | |||
expect(wrapper.find("div > div").length).toEqual(1) | |||
expect(wrapper.find("div > div").find(ModelComponent).props().expandDepth).toBe(1) | |||
}) | |||
}) | |||
it("passes defaultModelExpandDepth to ModelComponent", function(){ | |||
// When | |||
let expandDepth = 0 | |||
props.isExecute = false | |||
props.getConfigs = () => ({ | |||
defaultModelRendering: "model", | |||
defaultModelExpandDepth: expandDepth | |||
}) | |||
let wrapper = shallow(<ModelExample {...props}/>) | |||
// Then | |||
expect(wrapper.find("div > div").find(ModelComponent).props().expandDepth).toBe(expandDepth) | |||
}) | |||
}) |
@@ -0,0 +1,51 @@ | |||
/* eslint-env mocha */ | |||
import React from "react" | |||
import expect, { createSpy } from "expect" | |||
import { shallow } from "enzyme" | |||
import { fromJS } from "immutable" | |||
import Models from "components/models" | |||
import ModelCollpase from "components/model-collapse" | |||
import ModelComponent from "components/model-wrapper" | |||
describe("<Models/>", function(){ | |||
// Given | |||
let components = { | |||
Collapse: ModelCollpase, | |||
ModelWrapper: ModelComponent | |||
} | |||
let props = { | |||
getComponent: (c) => { | |||
return components[c] | |||
}, | |||
specSelectors: { | |||
definitions: function() { | |||
return fromJS({ | |||
def1: {}, | |||
def2: {} | |||
}) | |||
} | |||
}, | |||
layoutSelectors: { | |||
isShown: createSpy() | |||
}, | |||
layoutActions: {}, | |||
getConfigs: () => ({ | |||
docExpansion: "list", | |||
defaultModelExpandDepth: 0 | |||
}) | |||
} | |||
it("passes defaultModelExpandDepth to ModelWrapper", function(){ | |||
// When | |||
let wrapper = shallow(<Models {...props}/>) | |||
// Then should render tabs | |||
expect(wrapper.find("ModelCollapse").length).toEqual(1) | |||
expect(wrapper.find("ModelComponent").length).toBeGreaterThan(0) | |||
wrapper.find("ModelComponent").forEach((modelWrapper) => { | |||
expect(modelWrapper.props().expandDepth).toBe(0) | |||
}) | |||
}) | |||
}) |