Parcourir la source

Merge branch 'master' into bug/2903-wrong-font-for-error

bubble
shockey il y a 7 ans
committed by GitHub
Parent
révision
4f1772f654
37 fichiers modifiés avec 580 ajouts et 603 suppressions
  1. +5
    -0
      README.md
  2. +1
    -0
      dist/index.html
  3. +0
    -1
      make-webpack-config.js
  4. +0
    -1
      package.json
  5. +1
    -1
      src/core/components/info.jsx
  6. +4
    -3
      src/core/components/layout-utils.jsx
  7. +2
    -2
      src/core/components/models.jsx
  8. +3
    -2
      src/core/components/schemes.jsx
  9. +13
    -11
      src/core/json-schema-components.js
  10. +0
    -67
      src/core/path-translator.js
  11. +1
    -1
      src/core/plugins/auth/actions.js
  12. +0
    -1
      src/core/plugins/split-pane-mode/components/split-pane-mode.jsx
  13. +0
    -5
      src/core/plugins/split-pane-mode/components/split-pane-mode.less
  14. +1
    -2
      src/core/plugins/util/index.js
  15. +71
    -45
      src/core/utils.js
  16. +1
    -1
      src/plugins/add-plugin.md
  17. +1
    -1
      src/plugins/topbar/topbar.jsx
  18. +0
    -52
      src/plugins/topbar/topbar.less
  19. +0
    -2
      src/standalone/index.js
  20. +9
    -1
      src/style/_buttons.scss
  21. +6
    -6
      src/style/_form.scss
  22. +9
    -0
      src/style/_layout.scss
  23. +6
    -0
      src/style/_mixins.scss
  24. +3
    -0
      src/style/_split-pane-mode.scss
  25. +4
    -0
      src/style/_table.scss
  26. +1
    -1
      src/style/main.scss
  27. +41
    -0
      test/components/schemes.js
  28. +0
    -183
      test/core/path-translator.js
  29. +301
    -36
      test/core/utils.js
  30. +12
    -44
      webpack-dist-bundle.config.js
  31. +11
    -44
      webpack-dist-standalone.config.js
  32. +9
    -50
      webpack-dist.config.js
  33. +24
    -33
      webpack-hot-dev-server.config.js
  34. +1
    -1
      webpack-watch.config.js
  35. +4
    -5
      webpack.check.js
  36. +1
    -1
      webpack.config.js
  37. +34
    -0
      webpack.dist-style.config.js

+ 5
- 0
README.md Voir le fichier

@@ -146,6 +146,7 @@ displayOperationId | Controls the display of operationId in operations list. The
displayRequestDuration | Controls the display of the request duration (in milliseconds) for `Try it out` requests. The default is `false`.
maxDisplayedTags | If set, limits the number of tagged operations displayed to at most this many. The default is to show all operations.
filter | If set, enables filtering. The top bar will show an edit box that you can use to filter the tagged operations that are shown. Can be true/false to enable or disable, or an explicit filter string in which case filtering will be enabled using that string as the filter expression. Filtering is case sensitive matching the filter expression anywhere inside the tag.
deepLinking | If set to `true`, enables dynamic deep linking for tags and operations. [Docs](https://github.com/swagger-api/swagger-ui/blob/master/docs/deep-linking.md)

### Plugins

@@ -235,6 +236,10 @@ Access-Control-Allow-Headers: Content-Type, api_key, Authorization

Only headers with these names will be allowed to be sent by Swagger-UI.

## Security contact

Please disclose any security-related issues or vulnerabilities by emailing [security@swagger.io](mailto:security@swagger.io), instead of using the public issue tracker.

## License

Copyright 2017 SmartBear Software


+ 1
- 0
dist/index.html Voir le fichier

@@ -76,6 +76,7 @@ window.onload = function() {
const ui = SwaggerUIBundle({
url: "http://petstore.swagger.io/v2/swagger.json",
dom_id: '#swagger-ui',
deepLinking: true,
presets: [
SwaggerUIBundle.presets.apis,
SwaggerUIStandalonePreset


+ 0
- 1
make-webpack-config.js Voir le fichier

@@ -61,7 +61,6 @@ module.exports = function(rules, options) {
}

if( specialOptions.minimize ) {

plugins.push(
new webpack.optimize.UglifyJsPlugin({
sourceMap: true,


+ 0
- 1
package.json Voir le fichier

@@ -109,7 +109,6 @@
"karma-sourcemap-loader": "^0.3.7",
"karma-webpack": "2.0.3",
"less": "2.7.2",
"less-loader": "4.0.4",
"license-checker": "^11.0.0",
"mocha": "^3.4.2",
"node-sass": "^4.5.0",


+ 1
- 1
src/core/components/info.jsx Voir le fichier

@@ -15,7 +15,7 @@ class Path extends React.Component {

return (
<pre className="base-url">
[ Base url: {host}{basePath}]
[ Base URL: {host}{basePath} ]
</pre>
)
}


+ 4
- 3
src/core/components/layout-utils.jsx Voir le fichier

@@ -129,7 +129,8 @@ export class Select extends React.Component {
value: PropTypes.any,
onChange: PropTypes.func,
multiple: PropTypes.bool,
allowEmptyValue: PropTypes.bool
allowEmptyValue: PropTypes.bool,
className: PropTypes.string
}

static defaultProps = {
@@ -142,7 +143,7 @@ export class Select extends React.Component {

let value

if (props.value !== undefined) {
if (props.value) {
value = props.value
} else {
value = props.multiple ? [""] : ""
@@ -178,7 +179,7 @@ export class Select extends React.Component {
let value = this.state.value.toJS ? this.state.value.toJS() : this.state.value

return (
<select multiple={ multiple } value={ value } onChange={ this.onChange } >
<select className={this.props.className} multiple={ multiple } value={ value } onChange={ this.onChange } >
{ allowEmptyValue ? <option value="">--</option> : null }
{
allowedValues.map(function (item, key) {


+ 2
- 2
src/core/components/models.jsx Voir le fichier

@@ -24,8 +24,8 @@ export default class Models extends Component {
return <section className={ showModels ? "models is-open" : "models"}>
<h4 onClick={() => layoutActions.show("models", !showModels)}>
<span>Models</span>
<svg width="20" height="20">
<use xlinkHref="#large-arrow" />
<svg className="arrow" width="20" height="20">
<use xlinkHref={showModels ? "#large-arrow-down" : "#large-arrow"} />
</svg>
</h4>
<Collapse isOpened={showModels}>


+ 3
- 2
src/core/components/schemes.jsx Voir le fichier

@@ -19,8 +19,9 @@ export default class Schemes extends React.Component {
}

componentWillReceiveProps(nextProps) {
if ( this.props.operationScheme && !nextProps.schemes.has(this.props.operationScheme) ) {
//fire 'change' event if our selected scheme is no longer an option
if ( !this.props.operationScheme || !nextProps.schemes.has(this.props.operationScheme) ) {
// if we don't have a selected operationScheme or if our selected scheme is no longer an option,
// then fire 'change' event and select the first scheme in the list of options
this.setScheme(nextProps.schemes.first())
}
}


+ 13
- 11
src/core/json-schema-components.js Voir le fichier

@@ -57,7 +57,8 @@ export class JsonSchema_string extends Component {

if ( enumValue ) {
const Select = getComponent("Select")
return (<Select allowedValues={ enumValue }
return (<Select className={ errors.length ? "invalid" : ""}
allowedValues={ enumValue }
value={ value }
allowEmptyValue={ !required }
onChange={ this.onEnumChange }/>)
@@ -121,6 +122,7 @@ export class JsonSchema_array extends PureComponent {
render() {
let { getComponent, required, schema, fn } = this.props

let errors = schema.errors || []
let itemSchema = fn.inferSchema(schema.items)

const JsonSchemaForm = getComponent("JsonSchemaForm")
@@ -131,19 +133,17 @@ export class JsonSchema_array extends PureComponent {

if ( enumValue ) {
const Select = getComponent("Select")
return (<Select multiple={ true }
return (<Select className={ errors.length ? "invalid" : ""}
multiple={ true }
value={ value }
allowedValues={ enumValue }
allowEmptyValue={ !required }
onChange={ this.onEnumChange }/>)
}

let errors = schema.errors || []

return (
<div>
{ !value || value.count() < 1 ?
(errors.length ? <span style={{ color: "red", fortWeight: "bold" }}>{ errors[0] }</span> : null) :
{ !value || value.count() < 1 ? null :
value.map( (item,i) => {
let schema = Object.assign({}, itemSchema)
if ( errors.length ) {
@@ -153,12 +153,12 @@ export class JsonSchema_array extends PureComponent {
return (
<div key={i} className="json-schema-form-item">
<JsonSchemaForm fn={fn} getComponent={getComponent} value={item} onChange={(val) => this.onItemChange(val, i)} schema={schema} />
<Button className="json-schema-form-item-remove" onClick={()=> this.removeItem(i)} > - </Button>
<Button className="btn btn-sm json-schema-form-item-remove" onClick={()=> this.removeItem(i)} > - </Button>
</div>
)
}).toArray()
}
<Button className="json-schema-form-item-add" onClick={this.addItem}> Add item </Button>
<Button className={`btn btn-sm json-schema-form-item-add ${errors.length ? "invalid" : null}`} onClick={this.addItem}> Add item </Button>
</div>
)
}
@@ -170,12 +170,14 @@ export class JsonSchema_boolean extends Component {

onEnumChange = (val) => this.props.onChange(val)
render() {
let { getComponent, required, value } = this.props
let { getComponent, value, schema } = this.props
let errors = schema.errors || []
const Select = getComponent("Select")

return (<Select value={ String(value) }
return (<Select className={ errors.length ? "invalid" : ""}
value={ String(value) }
allowedValues={ fromJS(["true", "false"]) }
allowEmptyValue={ !required }
allowEmptyValue={true}
onChange={ this.onEnumChange }/>)
}
}

+ 0
- 67
src/core/path-translator.js Voir le fichier

@@ -1,67 +0,0 @@
import get from "lodash/get"

export function transformPathToArray(property, jsSpec) {
if(property.slice(0,9) === "instance.") {
var str = property.slice(9)
} else { // eslint-disable-next-line no-redeclare
var str = property
}

var pathArr = []

str
.split(".")
.map(item => {
// "key[0]" becomes ["key", "0"]
if(item.includes("[")) {
let index = parseInt(item.match(/\[(.*)\]/)[1])
let keyName = item.slice(0, item.indexOf("["))
return [keyName, index.toString()]
} else {
return item
}
})
.reduce(function(a, b) {
// flatten!
return a.concat(b)
}, [])
.concat([""]) // add an empty item into the array, so we don't get stuck with something in our buffer below
.reduce((buffer, curr) => {
let obj = pathArr.length ? get(jsSpec, pathArr) : jsSpec

if(get(obj, makeAccessArray(buffer, curr))) {
if(buffer.length) {
pathArr.push(buffer)
}
if(curr.length) {
pathArr.push(curr)
}
return ""
} else {
// attach key to buffer
return `${buffer}${buffer.length ? "." : ""}${curr}`
}
}, "")

if(typeof get(jsSpec, pathArr) !== "undefined") {
return pathArr
} else {
// if our path is not correct (there is no value at the path),
// return null
return null
}
}

function makeAccessArray(buffer, curr) {
let arr = []

if(buffer.length) {
arr.push(buffer)
}

if(curr.length) {
arr.push(curr)
}

return arr
}

+ 1
- 1
src/core/plugins/auth/actions.js Voir le fichier

@@ -73,7 +73,7 @@ export const authorizePassword = ( auth ) => ( { authActions } ) => {
let { schema, name, username, password, passwordType, clientId, clientSecret } = auth
let form = {
grant_type: "password",
scopes: encodeURIComponent(auth.scopes.join(scopeSeparator))
scope: encodeURIComponent(auth.scopes.join(scopeSeparator))
}
let query = {}
let headers = {}


+ 0
- 1
src/core/plugins/split-pane-mode/components/split-pane-mode.jsx Voir le fichier

@@ -1,7 +1,6 @@
import React from "react"
import PropTypes from "prop-types"
import SplitPane from "react-split-pane"
import "./split-pane-mode.less"

const MODE_KEY = ["split-pane-mode"]
const MODE_LEFT = "left"


+ 0
- 5
src/core/plugins/split-pane-mode/components/split-pane-mode.less Voir le fichier

@@ -1,5 +0,0 @@
.swagger-ui {
.Resizer.vertical.disabled {
display: none;
}
}

+ 1
- 2
src/core/plugins/util/index.js Voir le fichier

@@ -1,8 +1,7 @@
import { shallowEqualKeys } from "core/utils"
import { transformPathToArray } from "core/path-translator"

export default function() {
return {
fn: { shallowEqualKeys, transformPathToArray }
fn: { shallowEqualKeys }
}
}

+ 71
- 45
src/core/utils.js Voir le fichier

@@ -41,7 +41,7 @@ export function fromJSOrdered (js) {
return !isObject(js) ? js :
Array.isArray(js) ?
Im.Seq(js).map(fromJSOrdered).toList() :
Im.Seq(js).map(fromJSOrdered).toOrderedMap()
Im.OrderedMap(js).map(fromJSOrdered)
}

export function bindToState(obj, state) {
@@ -468,6 +468,18 @@ export const validateFile = ( val ) => {
}
}

export const validateBoolean = ( val ) => {
if ( !(val === "true" || val === "false" || val === true || val === false) ) {
return "Value must be a boolean"
}
}

export const validateString = ( val ) => {
if ( val && typeof val !== "string" ) {
return "Value must be a string"
}
}

// validation of parameters before execute
export const validateParam = (param, isXml) => {
let errors = []
@@ -475,52 +487,66 @@ export const validateParam = (param, isXml) => {
let required = param.get("required")
let type = param.get("type")

let stringCheck = type === "string" && !value
let arrayCheck = type === "array" && Array.isArray(value) && !value.length
let listCheck = type === "array" && Im.List.isList(value) && !value.count()
let fileCheck = type === "file" && !(value instanceof win.File)

if ( required && (stringCheck || arrayCheck || listCheck || fileCheck) ) {
errors.push("Required field is not provided")
return errors
}

if ( value === null || value === undefined ) {
return errors
}

if ( type === "number" ) {
let err = validateNumber(value)
if (!err) return errors
errors.push(err)
} else if ( type === "integer" ) {
let err = validateInteger(value)
if (!err) return errors
errors.push(err)
} else if ( type === "array" ) {
let itemType

if ( !value.count() ) { return errors }

itemType = param.getIn(["items", "type"])

value.forEach((item, index) => {
let err
// If the parameter is required OR the parameter has a value (meaning optional, but filled in)
// then we should do our validation routine
if ( required || value ) {
// These checks should evaluate to true if the parameter's value is valid
let stringCheck = type === "string" && value && !validateString(value)
let arrayCheck = type === "array" && Array.isArray(value) && value.length
let listCheck = type === "array" && Im.List.isList(value) && value.count()
let fileCheck = type === "file" && value instanceof win.File
let booleanCheck = type === "boolean" && !validateBoolean(value)
let numberCheck = type === "number" && !validateNumber(value) // validateNumber returns undefined if the value is a number
let integerCheck = type === "integer" && !validateInteger(value) // validateInteger returns undefined if the value is an integer

if ( required && !(stringCheck || arrayCheck || listCheck || fileCheck || booleanCheck || numberCheck || integerCheck) ) {
errors.push("Required field is not provided")
return errors
}

if (itemType === "number") {
err = validateNumber(item)
} else if (itemType === "integer") {
err = validateInteger(item)
}
if ( type === "string" ) {
let err = validateString(value)
if (!err) return errors
errors.push(err)
} else if ( type === "boolean" ) {
let err = validateBoolean(value)
if (!err) return errors
errors.push(err)
} else if ( type === "number" ) {
let err = validateNumber(value)
if (!err) return errors
errors.push(err)
} else if ( type === "integer" ) {
let err = validateInteger(value)
if (!err) return errors
errors.push(err)
} else if ( type === "array" ) {
let itemType

if ( !value.count() ) { return errors }

itemType = param.getIn(["items", "type"])

value.forEach((item, index) => {
let err

if (itemType === "number") {
err = validateNumber(item)
} else if (itemType === "integer") {
err = validateInteger(item)
} else if (itemType === "string") {
err = validateString(item)
}

if ( err ) {
errors.push({ index: index, error: err})
}
})
} else if ( type === "file" ) {
let err = validateFile(value)
if (!err) return errors
errors.push(err)
if ( err ) {
errors.push({ index: index, error: err})
}
})
} else if ( type === "file" ) {
let err = validateFile(value)
if (!err) return errors
errors.push(err)
}
}

return errors


+ 1
- 1
src/plugins/add-plugin.md Voir le fichier

@@ -20,7 +20,7 @@ SwaggerUI({
})
```

Or if you're updating the core plugins.. you'll add it to [src/js/bootstrap-plugin](https://github.com/SmartBear/swagger-ux/blob/master/src/js/bootstrap-plugin.js)
Or if you're updating the core plugins.. you'll add it to the base preset: [src/core/presets/base.js](https://github.com/swagger-api/swagger-ui/blob/master/src/core/presets/base.js)

Each Plugin is a function that returns an object. That object will get merged with the `system` and later bound to the state.
Here is an example of each `type`


+ 1
- 1
src/plugins/topbar/topbar.jsx Voir le fichier

@@ -130,7 +130,7 @@ export default class Topbar extends React.Component {
<div className="wrapper">
<div className="topbar-wrapper">
<Link href="#" title="Swagger UX">
<img height="30" width="30" src={ Logo } alt="Swagger UX"/>
<img height="30" width="30" src={ Logo } alt="Swagger UI"/>
<span>swagger</span>
</Link>
<form className="download-url-wrapper" onSubmit={formOnSubmit}>


+ 0
- 52
src/plugins/topbar/topbar.less Voir le fichier

@@ -1,52 +0,0 @@
.swagger-ui {
.topbar {
background-color: #89bf04;
}

.topbar-wrapper {
padding: 0.7em;
}

.topbar-logo__img {
float: left;
}

.topbar-logo__title {
display: inline-block;
color: #fff;
font-size: 1.5em;
font-weight: bold;
margin: 0.15em 0 0 0.5em;
}

.download-url-wrapper {
text-align: right;
float: right;
}

.topbar .download-url__text {
width: 28em;
height: 2em;
margin-right: 0.5em;
}

.download-url__btn {
background-color: #547f00;
border-color: #547f00;
text-decoration: none;
font-weight: bold;
padding: 0.2em 0.3em;
color: white;
border-radius: 0.1em;

&:hover {
&:extend(.download-url__btn);
}
}

.center-700 {
display: block;
margin: 0 auto;
width: 45em;
}
}

+ 0
- 2
src/standalone/index.js Voir le fichier

@@ -1,6 +1,4 @@
import StandaloneLayout from "./layout"
import "../style/main.scss"

import TopbarPlugin from "plugins/topbar"
import ConfigsPlugin from "plugins/configs"



+ 9
- 1
src/style/_buttons.scss Voir le fichier

@@ -14,6 +14,11 @@

@include text_headline();

&.btn-sm {
font-size: 12px;
padding: 4px 23px;
}

&[disabled]
{
cursor: not-allowed;
@@ -165,6 +170,9 @@
button
{
cursor: pointer;

outline: none;

&.invalid {
@include invalidFormElement();
}
}

+ 6
- 6
src/style/_form.scss Voir le fichier

@@ -21,6 +21,10 @@ select

background: #f7f7f7;
}

&.invalid {
@include invalidFormElement();
}
}

.opblock-body select
@@ -53,12 +57,8 @@ input[type=file]
border-radius: 4px;
background: #fff;

&.invalid
{
animation: shake .4s 1;

border-color: $_color-delete;
background: lighten($_color-delete, 35%);
&.invalid {
@include invalidFormElement();
}
}



+ 9
- 0
src/style/_layout.scss Voir le fichier

@@ -490,6 +490,15 @@
{
margin: 0;
}

a
{
@include text_code(#89bf04);
text-decoration: underline;
&:hover {
color: #81b10c;
}
}
}
}



+ 6
- 0
src/style/_mixins.scss Voir le fichier

@@ -166,3 +166,9 @@ $browser-context: 16;
@warn 'Breakpoint mixin supports: tablet, mobile, desktop';
}
}

@mixin invalidFormElement() {
animation: shake .4s 1;
border-color: $_color-delete;
background: lighten($_color-delete, 35%);
}

+ 3
- 0
src/style/_split-pane-mode.scss Voir le fichier

@@ -0,0 +1,3 @@
.Resizer.vertical.disabled {
display: none;
}

+ 4
- 0
src/style/_table.scss Voir le fichier

@@ -97,6 +97,10 @@ table
width: 100%;
max-width: 340px;
}

select {
border-width: 1px;
}
}

.parameter__name


+ 1
- 1
src/style/main.scss Voir le fichier

@@ -14,6 +14,6 @@
@import 'information';
@import 'authorize';
@import 'errors';

@include text_body();
@import 'split-pane-mode';
}

+ 41
- 0
test/components/schemes.js Voir le fichier

@@ -0,0 +1,41 @@

/* eslint-env mocha */
import React from "react"
import expect, { createSpy } from "expect"
import { shallow } from "enzyme"
import { fromJS } from "immutable"
import Schemes from "components/schemes"

describe("<Schemes/>", function(){
it("calls props.specActions.setScheme() when no operationScheme is selected", function(){

// Given
let props = {
specActions: {
setScheme: createSpy()
},
schemes: fromJS([
"http",
"https"
]),
operationScheme: undefined,
path: "/test",
method: "get"
}
// When
let wrapper = shallow(<Schemes {...props}/>)

// Then operationScheme should default to first scheme in options list
expect(props.specActions.setScheme).toHaveBeenCalledWith("http", "/test" , "get")

// When the operationScheme is no longer in the list of options
props.schemes = fromJS([
"https"
])
wrapper.setProps(props)

// Then operationScheme should default to first scheme in options list
expect(props.specActions.setScheme).toHaveBeenCalledWith("https", "/test", "get")
})
})

+ 0
- 183
test/core/path-translator.js Voir le fichier

@@ -1,183 +0,0 @@
/* eslint-env mocha */
import expect from "expect"
import { transformPathToArray } from "core/path-translator"

describe("validation plugin - path translator", function(){

describe("string paths", function(){

it("should translate a simple string path to an array", function(){
// Given
let jsSpec = {
one: {
a: "a thing",
b: "another thing",
c: "one more thing"
},
two: 2
}

let path = "instance.one.a"

// Then
expect(transformPathToArray(path, jsSpec)).toEqual(["one", "a"])

})

it("should translate an ambiguous string path to an array", function(){
// Since JSONSchema uses periods to mark different properties,
// a key with a period in it is ambiguous, because it can mean at least two things.
// In our case, the path can mean:
// ["google", "com", "a"] or ["google.com", "a"]

// Given
let jsSpec = {
"google.com": {
a: "a thing",
b: "another thing",
c: "one more thing"
},
"gmail.com": {
d: "more stuff",
e: "even more stuff"
}
}

let path = "instance.google.com.a"

// Then
expect(transformPathToArray(path, jsSpec)).toEqual(["google.com", "a"])

})

it("should translate an doubly ambiguous string path to an array", function(){
// Since JSONSchema uses periods to mark different properties,
// a key with two periods in it (like "www.google.com") is doubly ambiguous,
// because it can mean at least three things.


// Given
let jsSpec = {
"www.google.com": {
a: "a thing",
b: "another thing",
c: "one more thing"
},
"gmail.com": {
d: "more stuff",
e: "even more stuff"
}
}

let path = "instance.www.google.com.a"

// Then
expect(transformPathToArray(path, jsSpec)).toEqual(["www.google.com", "a"])

})

it("should return null for an invalid path", function(){

// Given
let jsSpec = {
"google.com": {
a: "a thing",
b: "another thing",
c: "one more thing"
},
"gmail.com": {
d: "more stuff",
e: "even more stuff"
}
}

let path = "instance.google.net.a"

// Then
expect(transformPathToArray(path, jsSpec)).toEqual(null)

})

it("should return inline array indices in their own value", function(){
// "a[1]" => ["a", "1"]

// Given
let jsSpec = {
"google.com": {
a: [
"hello",
"here is the target"
],
b: "another thing",
c: "one more thing"
},
"gmail.com": {
d: "more stuff",
e: "even more stuff"
}
}

let path = "instance.google.com.a[1]"

// Then
expect(transformPathToArray(path, jsSpec)).toEqual(["google.com", "a", "1"])

})

it("should return the correct path when the last part is ambiguous", function(){

// Given
let jsSpec = {
"google.com": {
a: [
"hello",
{
"gmail.com": 1234
}
],
b: "another thing",
c: "one more thing"
},
"gmail.com": {
d: "more stuff",
e: "even more stuff"
}
}

let path = "instance.google.com.a[1].gmail.com"

// Then
expect(transformPathToArray(path, jsSpec)).toEqual(["google.com", "a", "1", "gmail.com"])

})

it("should return the correct path when the last part is doubly ambiguous", function(){

// Given
let jsSpec = {
"google.com": {
a: [
"hello",
{
"www.gmail.com": 1234
}
],
b: "another thing",
c: "one more thing"
},
"gmail.com": {
d: "more stuff",
e: "even more stuff"
}
}

let path = "instance.google.com.a[1].www.gmail.com"

// Then
expect(transformPathToArray(path, jsSpec)).toEqual(["google.com", "a", "1", "www.gmail.com"])

})

})

})

+ 301
- 36
test/core/utils.js Voir le fichier

@@ -1,10 +1,10 @@
/* eslint-env mocha */
import expect from "expect"
import { fromJS } from "immutable"
import { mapToList, validateNumber, validateInteger, validateParam, validateFile } from "core/utils"
import { mapToList, validateNumber, validateInteger, validateParam, validateFile, fromJSOrdered } from "core/utils"
import win from "core/window"

describe("utils", function(){
describe("utils", function() {

describe("mapToList", function(){

@@ -176,6 +176,7 @@ describe("utils", function(){
let result = null

it("validates required strings", function() {
// invalid string
param = fromJS({
required: true,
type: "string",
@@ -183,9 +184,39 @@ describe("utils", function(){
})
result = validateParam( param, false )
expect( result ).toEqual( ["Required field is not provided"] )

// valid string
param = fromJS({
required: true,
type: "string",
value: "test string"
})
result = validateParam( param, false )
expect( result ).toEqual( [] )
})

it("validates optional strings", function() {
// valid (empty) string
param = fromJS({
required: false,
type: "string",
value: ""
})
result = validateParam( param, false )
expect( result ).toEqual( [] )

// valid string
param = fromJS({
required: false,
type: "string",
value: "test"
})
result = validateParam( param, false )
expect( result ).toEqual( [] )
})

it("validates required files", function() {
// invalid file
param = fromJS({
required: true,
type: "file",
@@ -193,9 +224,48 @@ describe("utils", function(){
})
result = validateParam( param, false )
expect( result ).toEqual( ["Required field is not provided"] )

// valid file
param = fromJS({
required: true,
type: "file",
value: new win.File()
})
result = validateParam( param, false )
expect( result ).toEqual( [] )
})

it("validates optional files", function() {
// invalid file
param = fromJS({
required: false,
type: "file",
value: "not a file"
})
result = validateParam( param, false )
expect( result ).toEqual( ["Value must be a file"] )

// valid (empty) file
param = fromJS({
required: false,
type: "file",
value: undefined
})
result = validateParam( param, false )
expect( result ).toEqual( [] )

// valid file
param = fromJS({
required: false,
type: "file",
value: new win.File()
})
result = validateParam( param, false )
expect( result ).toEqual( [] )
})

it("validates required arrays", function() {
// invalid (empty) array
param = fromJS({
required: true,
type: "array",
@@ -204,17 +274,191 @@ describe("utils", function(){
result = validateParam( param, false )
expect( result ).toEqual( ["Required field is not provided"] )

// invalid (not an array)
param = fromJS({
required: true,
type: "array",
value: undefined
})
result = validateParam( param, false )
expect( result ).toEqual( ["Required field is not provided"] )

// invalid array, items do not match correct type
param = fromJS({
required: true,
type: "array",
value: [1],
items: {
type: "string"
}
})
result = validateParam( param, false )
expect( result ).toEqual( [{index: 0, error: "Value must be a string"}] )

// valid array, with no 'type' for items
param = fromJS({
required: true,
type: "array",
value: ["1"]
})
result = validateParam( param, false )
expect( result ).toEqual( [] )

// valid array, items match type
param = fromJS({
required: true,
type: "array",
value: ["1"],
items: {
type: "string"
}
})
result = validateParam( param, false )
expect( result ).toEqual( [] )
})

it("validates optional arrays", function() {
// valid, empty array
param = fromJS({
required: false,
type: "array",
value: []
})
result = validateParam( param, false )
expect( result ).toEqual( [] )

// invalid, items do not match correct type
param = fromJS({
required: false,
type: "array",
value: ["number"],
items: {
type: "number"
}
})
result = validateParam( param, false )
expect( result ).toEqual( [{index: 0, error: "Value must be a number"}] )

// valid
param = fromJS({
required: false,
type: "array",
value: ["test"],
items: {
type: "string"
}
})
result = validateParam( param, false )
expect( result ).toEqual( [] )
})

it("validates required booleans", function() {
// invalid boolean value
param = fromJS({
required: true,
type: "boolean",
value: undefined
})
result = validateParam( param, false )
expect( result ).toEqual( ["Required field is not provided"] )

// invalid boolean value (not a boolean)
param = fromJS({
required: true,
type: "boolean",
value: "test string"
})
result = validateParam( param, false )
expect( result ).toEqual( ["Required field is not provided"] )

// valid boolean value
param = fromJS({
required: true,
type: "boolean",
value: "true"
})
result = validateParam( param, false )
expect( result ).toEqual( [] )

// valid boolean value
param = fromJS({
required: true,
type: "boolean",
value: false
})
result = validateParam( param, false )
expect( result ).toEqual( [] )
})

it("validates numbers", function() {
// string instead of a number
it("validates optional booleans", function() {
// valid (empty) boolean value
param = fromJS({
required: false,
type: "boolean",
value: undefined
})
result = validateParam( param, false )
expect( result ).toEqual( [] )

// invalid boolean value (not a boolean)
param = fromJS({
required: false,
type: "boolean",
value: "test string"
})
result = validateParam( param, false )
expect( result ).toEqual( ["Value must be a boolean"] )

// valid boolean value
param = fromJS({
required: false,
type: "boolean",
value: "true"
})
result = validateParam( param, false )
expect( result ).toEqual( [] )

// valid boolean value
param = fromJS({
required: false,
type: "boolean",
value: false
})
result = validateParam( param, false )
expect( result ).toEqual( [] )
})

it("validates required numbers", function() {
// invalid number, string instead of a number
param = fromJS({
required: true,
type: "number",
value: "test"
})
result = validateParam( param, false )
expect( result ).toEqual( ["Required field is not provided"] )

// invalid number, undefined value
param = fromJS({
required: true,
type: "number",
value: undefined
})
result = validateParam( param, false )
expect( result ).toEqual( ["Required field is not provided"] )

// valid number
param = fromJS({
required: true,
type: "number",
value: 10
})
result = validateParam( param, false )
expect( result ).toEqual( [] )
})

it("validates optional numbers", function() {
// invalid number, string instead of a number
param = fromJS({
required: false,
type: "number",
@@ -223,7 +467,7 @@ describe("utils", function(){
result = validateParam( param, false )
expect( result ).toEqual( ["Value must be a number"] )

// undefined value
// valid (empty) number
param = fromJS({
required: false,
type: "number",
@@ -232,78 +476,99 @@ describe("utils", function(){
result = validateParam( param, false )
expect( result ).toEqual( [] )

// null value
// valid number
param = fromJS({
required: false,
type: "number",
value: null
value: 10
})
result = validateParam( param, false )
expect( result ).toEqual( [] )
})

it("validates integers", function() {
// string instead of integer
it("validates required integers", function() {
// invalid integer, string instead of an integer
param = fromJS({
required: false,
required: true,
type: "integer",
value: "test"
})
result = validateParam( param, false )
expect( result ).toEqual( ["Value must be an integer"] )
expect( result ).toEqual( ["Required field is not provided"] )

// undefined value
// invalid integer, undefined value
param = fromJS({
required: false,
required: true,
type: "integer",
value: undefined
})
result = validateParam( param, false )
expect( result ).toEqual( [] )
expect( result ).toEqual( ["Required field is not provided"] )

// null value
// valid integer
param = fromJS({
required: false,
required: true,
type: "integer",
value: null
value: 10
})
result = validateParam( param, false )
expect( result ).toEqual( [] )
})

it("validates arrays", function() {
// empty array
it("validates optional integers", function() {
// invalid integer, string instead of an integer
param = fromJS({
required: false,
type: "array",
value: []
type: "integer",
value: "test"
})
result = validateParam( param, false )
expect( result ).toEqual( [] )
expect( result ).toEqual( ["Value must be an integer"] )

// numbers
// valid (empty) integer
param = fromJS({
required: false,
type: "array",
value: ["number"],
items: {
type: "number"
}
type: "integer",
value: undefined
})
result = validateParam( param, false )
expect( result ).toEqual( [{index: 0, error: "Value must be a number"}] )
expect( result ).toEqual( [] )

// integers
// valid number
param = fromJS({
required: false,
type: "array",
value: ["not", "numbers"],
items: {
type: "integer"
}
type: "integer",
value: 10
})
result = validateParam( param, false )
expect( result ).toEqual( [{index: 0, error: "Value must be an integer"}, {index: 1, error: "Value must be an integer"}] )
expect( result ).toEqual( [] )
})
})

describe("fromJSOrdered", () => {
it("should create an OrderedMap from an object", () => {
const param = {
value: "test"
}

const result = fromJSOrdered(param).toJS()
expect( result ).toEqual( { value: "test" } )
})

it("should not use an object's length property for Map size", () => {
const param = {
length: 5
}

const result = fromJSOrdered(param).toJS()
expect( result ).toEqual( { length: 5 } )
})

it("should create an OrderedMap from an array", () => {
const param = [1, 1, 2, 3, 5, 8]

const result = fromJSOrdered(param).toJS()
expect( result ).toEqual( [1, 1, 2, 3, 5, 8] )
})
})
})

+ 12
- 44
webpack-dist-bundle.config.js Voir le fichier

@@ -1,64 +1,32 @@
var path = require('path')
var rules = [
const path = require("path")
const styleRules = require("./webpack.dist-style.config.js")

let rules = [
{ test: /\.(worker\.js)(\?.*)?$/,
use: [
{
loader: 'worker-loader',
loader: "worker-loader",
options: {
inline: true,
name: '[name].js'
}
},
{ loader: 'babel-loader' }
]
},
{ test: /\.(css)(\?.*)?$/,
use: [
'style-loader',
'css-loader',
'postcss-loader'
]
},
{ test: /\.(scss)(\?.*)?$/,
use: [
'style-loader',
'css-loader',
{
loader: 'postcss-loader',
options: { sourceMap: true }
},
{ loader: 'sass-loader',
options: {
outputStyle: 'expanded',
sourceMap: true,
sourceMapContents: 'true'
name: "[name].js"
}
}
]
},
{ test: /\.(less)(\?.*)?$/,
use: [
'style-loader',
'css-loader',
{
loader: 'postcss-loader',
},
'less-loader'
{ loader: "babel-loader" }
]
}
]

module.exports = require('./make-webpack-config.js')(rules, {
module.exports = require("./make-webpack-config.js")(rules, {
_special: {
separateStylesheets: false,
separateStylesheets: true,
minimize: true,
sourcemaps: true,
},

entry: {
'swagger-ui-bundle': [
'./src/polyfills',
'./src/core/index.js'
"swagger-ui-bundle": [
"./src/polyfills",
"./src/core/index.js"
]
},



+ 11
- 44
webpack-dist-standalone.config.js Voir le fichier

@@ -1,65 +1,32 @@
var path = require('path')
const path = require("path")
const styleRules = require("./webpack.dist-style.config.js")

var rules = [
let rules = [
{ test: /\.(worker\.js)(\?.*)?$/,
use: [
{
loader: 'worker-loader',
loader: "worker-loader",
options: {
inline: true,
name: '[name].js'
name: "[name].js"
}
},
{ loader: 'babel-loader' }
]
},
{ test: /\.(css)(\?.*)?$/,
use: [
'style-loader',
'css-loader',
'postcss-loader'
]
},
{ test: /\.(scss)(\?.*)?$/,
use: [
'style-loader',
'css-loader',
{
loader: 'postcss-loader',
options: { sourceMap: true }
},
{ loader: 'sass-loader',
options: {
outputStyle: 'expanded',
sourceMap: true,
sourceMapContents: 'true'
}
}
]
},
{ test: /\.(less)(\?.*)?$/,
use: [
'style-loader',
'css-loader',
{
loader: 'postcss-loader',
},
'less-loader'
{ loader: "babel-loader" }
]
}
]

module.exports = require('./make-webpack-config.js')(rules, {
module.exports = require("./make-webpack-config.js")(rules, {
_special: {
separateStylesheets: false,
separateStylesheets: true,
minimize: true,
sourcemaps: true,
},

entry: {
'swagger-ui-standalone-preset': [
'./src/polyfills',
'./src/standalone/index.js'
"swagger-ui-standalone-preset": [
"./src/polyfills",
"./src/standalone/index.js"
]
},



+ 9
- 50
webpack-dist.config.js Voir le fichier

@@ -1,66 +1,25 @@
var path = require('path')
var fs = require('fs')
const path = require("path")
const fs = require("fs")
const nodeModules = fs.readdirSync("node_modules").filter(function(x) { return x !== ".bin" })
var ExtractTextPlugin = require('extract-text-webpack-plugin')
const styleRules = require("./webpack.dist-style.config.js")

var rules = [
let rules = [
{ test: /\.(worker\.js)(\?.*)?$/,
use: [
{
loader: 'worker-loader',
loader: "worker-loader",
options: {
inline: true,
name: '[name].js'
name: "[name].js"
}
},
{ loader: 'babel-loader' }
{ loader: "babel-loader" }
]
},
{ test: /\.(css)(\?.*)?$/,
use: ExtractTextPlugin.extract({
fallback: 'style-loader',
use: [
'css-loader',
'postcss-loader'
]
})
},
{ test: /\.(scss)(\?.*)?$/,
use: ExtractTextPlugin.extract({
fallback: 'style-loader',
use: [
{
loader: 'css-loader',
options: { minimize: true }
},
{
loader: 'postcss-loader',
options: { sourceMap: true }
},
{ loader: 'sass-loader',
options: {
outputStyle: 'expanded',
sourceMap: true,
sourceMapContents: 'true'
}
}
]
})
},
{ test: /\.(less)(\?.*)?$/,
use: ExtractTextPlugin.extract({
fallback: 'style-loader',
use: ['css-loader',
{
loader: 'postcss-loader',
},
'less-loader'
]
})
}
]
rules = rules.concat(styleRules)

module.exports = require('./make-webpack-config.js')(rules, {
module.exports = require("./make-webpack-config.js")(rules, {
_special: {
separateStylesheets: true,
minimize: true,


+ 24
- 33
webpack-hot-dev-server.config.js Voir le fichier

@@ -1,56 +1,46 @@
var path = require('path')
const path = require("path")

var rules = [
const rules = [
{ test: /\.(worker\.js)(\?.*)?$/,
use: [
{
loader: 'worker-loader',
loader: "worker-loader",
options: {
inline: true
}
},
{ loader: 'babel-loader' }
{ loader: "babel-loader" }
]
},
{ test: /\.(jsx)(\?.*)?$/,
use: [
{ loader: 'react-hot-loader' },
{ loader: 'babel-loader' }
{ loader: "react-hot-loader" },
{ loader: "babel-loader" }
]
},
{ test: /\.(css)(\?.*)?$/,
use: [
'style-loader',
'css-loader',
'postcss-loader'
"style-loader",
"css-loader",
"postcss-loader"
]
},
{ test: /\.(scss)(\?.*)?$/,
use: [
'style-loader',
'css-loader',
"style-loader",
"css-loader",
{
loader: 'postcss-loader',
loader: "postcss-loader",
options: { sourceMap: true }
},
{ loader: 'sass-loader',
{ loader: "sass-loader",
options: {
outputStyle: 'expanded',
outputStyle: "expanded",
sourceMap: true,
sourceMapContents: 'true'
sourceMapContents: "true"
}
}
]
},
{ test: /\.(less)(\?.*)?$/,
use: [
'style-loader',
'css-loader',
{
loader: 'postcss-loader',
},
'less-loader'
]
}
]

@@ -60,25 +50,26 @@ module.exports = require("./make-webpack-config")(rules, {
},
devtool: "eval",
entry: {
'swagger-ui-bundle': [
'./src/polyfills',
'./src/core/index.js'
"swagger-ui-bundle": [
"./src/polyfills",
"./src/core/index.js"
],
'swagger-ui-standalone-preset': [
'./src/polyfills',
'./src/standalone/index.js',
"swagger-ui-standalone-preset": [
"./src/style/main.scss",
"./src/polyfills",
"./src/standalone/index.js",
]
},
output: {
pathinfo: true,
filename: '[name].js',
filename: "[name].js",
library: "[name]",
libraryTarget: "umd",
chunkFilename: "[id].js"
},
devServer: {
port: 3200,
contentBase: path.join(__dirname, 'dev-helpers'),
contentBase: path.join(__dirname, "dev-helpers"),
publicPath: "/",
noInfo: true,
hot: true,


+ 1
- 1
webpack-watch.config.js Voir le fichier

@@ -1,3 +1,3 @@
var config = require("./webpack-dist.config.js")
const config = require("./webpack-dist.config.js")

module.exports = config

+ 4
- 5
webpack.check.js Voir le fichier

@@ -1,8 +1,7 @@
const webpack = require('webpack')
const path = require('path')
const deepMerge = require('deepmerge')
const webpackConfig = require('./webpack-dist-bundle.config.js')
const DEPS_CHECK_DIR = require('./package.json').config.deps_check_dir
const path = require("path")
const deepMerge = require("deepmerge")
const webpackConfig = require("./webpack-dist-bundle.config.js")
const DEPS_CHECK_DIR = require("./package.json").config.deps_check_dir

module.exports = deepMerge(
webpackConfig, {


+ 1
- 1
webpack.config.js Voir le fichier

@@ -1,3 +1,3 @@
module.exports = require("./make-webpack-config")({

});
})

+ 34
- 0
webpack.dist-style.config.js Voir le fichier

@@ -0,0 +1,34 @@
const ExtractTextPlugin = require("extract-text-webpack-plugin")

module.exports = [{
test: /\.(css)(\?.*)?$/,
use: ExtractTextPlugin.extract({
fallback: "style-loader",
use: [
"css-loader",
"postcss-loader"
]
})
},
{ test: /\.(scss)(\?.*)?$/,
use: ExtractTextPlugin.extract({
fallback: "style-loader",
use: [
{
loader: "css-loader",
options: { minimize: true }
},
{
loader: "postcss-loader",
options: { sourceMap: true }
},
{ loader: "sass-loader",
options: {
outputStyle: "expanded",
sourceMap: true,
sourceMapContents: "true"
}
}
]
})
}]

Chargement…
Annuler
Enregistrer