Added Swagger
This commit is contained in:
@@ -0,0 +1,94 @@
|
||||
import expect from "expect"
|
||||
|
||||
import validateHelper, { expectNoErrors } from "../validate-helper.js"
|
||||
|
||||
describe("validation plugin - semantic - 2and3 operations", () => {
|
||||
describe("Operations must have unique operationIds", () => {
|
||||
describe("OpenAPI 3.0", () => {
|
||||
it("should return an error when operationId collisions exist", () => {
|
||||
const spec = {
|
||||
openapi: "3.0.0",
|
||||
paths: {
|
||||
"/": {
|
||||
get: {
|
||||
operationId: "myId"
|
||||
},
|
||||
post: {
|
||||
operationId: "myId"
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return validateHelper(spec)
|
||||
.then(system => {
|
||||
const allErrors = system.errSelectors.allErrors().toJS()
|
||||
const firstError = allErrors[0]
|
||||
expect(allErrors.length).toEqual(1)
|
||||
expect(firstError.message).toEqual(`Operations must have unique operationIds.`)
|
||||
expect(firstError.path).toEqual(["paths", "/", "post", "operationId"])
|
||||
})
|
||||
})
|
||||
it("should not return an error when operationId collisions don't exist", () => {
|
||||
const spec = {
|
||||
openapi: "3.0.0",
|
||||
paths: {
|
||||
"/": {
|
||||
get: {
|
||||
operationId: "myId1"
|
||||
},
|
||||
post: {
|
||||
operationId: "myId2"
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return expectNoErrors(spec)
|
||||
})
|
||||
})
|
||||
describe("Swagger 2.0", () => {
|
||||
it("should return an error when operationId collisions exist", () => {
|
||||
const spec = {
|
||||
swagger: "2.0",
|
||||
paths: {
|
||||
"/": {
|
||||
get: {
|
||||
operationId: "myId"
|
||||
},
|
||||
post: {
|
||||
operationId: "myId"
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return validateHelper(spec)
|
||||
.then(system => {
|
||||
const allErrors = system.errSelectors.allErrors().toJS()
|
||||
const firstError = allErrors[0]
|
||||
expect(allErrors.length).toEqual(1)
|
||||
expect(firstError.message).toEqual(`Operations must have unique operationIds.`)
|
||||
expect(firstError.path).toEqual(["paths", "/", "post", "operationId"])
|
||||
})
|
||||
})
|
||||
it("should not return an error when operationId collisions don't exist", () => {
|
||||
const spec = {
|
||||
swagger: "2.0",
|
||||
paths: {
|
||||
"/": {
|
||||
get: {
|
||||
operationId: "myId1"
|
||||
},
|
||||
post: {
|
||||
operationId: "myId2"
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return expectNoErrors(spec)
|
||||
})
|
||||
})
|
||||
})
|
||||
})
|
||||
@@ -0,0 +1,997 @@
|
||||
import expect from "expect"
|
||||
import validateHelper from "../validate-helper.js"
|
||||
|
||||
describe(`validation plugin - semantic - 2and3 parameters`, () => {
|
||||
describe(`parameters must have unique name + in values`, () => {
|
||||
describe(`direct siblings`, () => {
|
||||
it("should return an error for an invalid Swagger 2 definition", () => {
|
||||
const spec = {
|
||||
swagger: "2.0",
|
||||
"paths": {
|
||||
"/pets": {
|
||||
"parameters": [
|
||||
{
|
||||
"name": "pathLevel",
|
||||
"in": "query",
|
||||
"description": "tags to filter by",
|
||||
"type": "string"
|
||||
},
|
||||
{
|
||||
"name": "pathLevel",
|
||||
"in": "query",
|
||||
"description": "tags to filter by",
|
||||
"type": "string"
|
||||
},
|
||||
],
|
||||
"get": {
|
||||
"parameters": [
|
||||
{
|
||||
"name": "opLevel",
|
||||
"in": "query",
|
||||
"description": "tags to filter by",
|
||||
"type": "string"
|
||||
},
|
||||
{
|
||||
"name": "opLevel",
|
||||
"in": "query",
|
||||
"description": "tags to filter by",
|
||||
"type": "string"
|
||||
},
|
||||
]
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return validateHelper(spec)
|
||||
.then(system => {
|
||||
const allErrors = system.errSelectors.allErrors().toJS()
|
||||
const firstError = allErrors[0]
|
||||
const secondError = allErrors[1]
|
||||
expect(allErrors.length).toEqual(2)
|
||||
expect(firstError.path).toEqual(["paths", "/pets", "parameters", "1"])
|
||||
expect(firstError.message).toEqual("Sibling parameters must have unique name + in values")
|
||||
expect(secondError.path).toEqual(["paths", "/pets", "get", "parameters", "1"])
|
||||
expect(secondError.message).toEqual("Sibling parameters must have unique name + in values")
|
||||
})
|
||||
})
|
||||
it("should return an error for an invalid OpenAPI 3 definition", () => {
|
||||
const spec = {
|
||||
openapi: "3.0.0",
|
||||
"paths": {
|
||||
"/pets": {
|
||||
"parameters": [
|
||||
{
|
||||
"name": "pathLevel",
|
||||
"in": "query",
|
||||
"description": "tags to filter by",
|
||||
"schema": {
|
||||
"type": "string"
|
||||
}
|
||||
},
|
||||
{
|
||||
"name": "pathLevel",
|
||||
"in": "query",
|
||||
"description": "tags to filter by",
|
||||
"schema": {
|
||||
"type": "string"
|
||||
}
|
||||
},
|
||||
],
|
||||
"get": {
|
||||
"parameters": [
|
||||
{
|
||||
"name": "opLevel",
|
||||
"in": "query",
|
||||
"description": "tags to filter by",
|
||||
"schema": {
|
||||
"type": "string"
|
||||
}
|
||||
},
|
||||
{
|
||||
"name": "opLevel",
|
||||
"in": "query",
|
||||
"description": "tags to filter by",
|
||||
"schema": {
|
||||
"type": "string"
|
||||
}
|
||||
},
|
||||
]
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return validateHelper(spec)
|
||||
.then(system => {
|
||||
const allErrors = system.errSelectors.allErrors().toJS()
|
||||
const firstError = allErrors[0]
|
||||
const secondError = allErrors[1]
|
||||
expect(allErrors.length).toEqual(2)
|
||||
expect(firstError.path).toEqual(["paths", "/pets", "parameters", "1"])
|
||||
expect(firstError.message).toEqual("Sibling parameters must have unique name + in values")
|
||||
expect(secondError.path).toEqual(["paths", "/pets", "get", "parameters", "1"])
|
||||
expect(secondError.message).toEqual("Sibling parameters must have unique name + in values")
|
||||
})
|
||||
})
|
||||
it("should return no errors for a valid Swagger 2 definition", () => {
|
||||
const spec = {
|
||||
swagger: "2.0",
|
||||
"paths": {
|
||||
"/pets": {
|
||||
"get": {
|
||||
"parameters": [
|
||||
{
|
||||
"name": "wags",
|
||||
"in": "query",
|
||||
"description": "wags to filter by",
|
||||
"type": "string"
|
||||
},
|
||||
{
|
||||
"name": "tags",
|
||||
"in": "query",
|
||||
"description": "tags to filter by",
|
||||
"type": "string"
|
||||
},
|
||||
]
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return validateHelper(spec)
|
||||
.then(system => {
|
||||
const allErrors = system.errSelectors.allErrors().toJS()
|
||||
expect(allErrors.length).toEqual(0)
|
||||
})
|
||||
})
|
||||
it("should return no errors for a valid OpenAPI 3 definition", () => {
|
||||
const spec = {
|
||||
openapi: "3.0.0",
|
||||
"paths": {
|
||||
"/pets": {
|
||||
"get": {
|
||||
"parameters": [
|
||||
{
|
||||
"name": "wags",
|
||||
"in": "query",
|
||||
"description": "wags to filter by",
|
||||
"type": "string"
|
||||
},
|
||||
{
|
||||
"name": "tags",
|
||||
"in": "query",
|
||||
"description": "tags to filter by",
|
||||
"type": "string"
|
||||
},
|
||||
]
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return validateHelper(spec)
|
||||
.then(system => {
|
||||
const allErrors = system.errSelectors.allErrors().toJS()
|
||||
expect(allErrors.length).toEqual(0)
|
||||
})
|
||||
})
|
||||
})
|
||||
describe(`inherited siblings`, () => {
|
||||
it("should return no errors for a valid Swagger 2 definition due to inheritance", () => {
|
||||
const spec = {
|
||||
swagger: "2.0",
|
||||
parameters: {
|
||||
MyParam: {
|
||||
name: "one",
|
||||
in: "query"
|
||||
}
|
||||
},
|
||||
"paths": {
|
||||
"/pets": {
|
||||
"parameters": [
|
||||
{
|
||||
name: "one",
|
||||
in: "query"
|
||||
},
|
||||
{
|
||||
name: "two",
|
||||
in: "query"
|
||||
}
|
||||
],
|
||||
"get": {
|
||||
"parameters": [
|
||||
{
|
||||
name: "two",
|
||||
in: "query"
|
||||
},
|
||||
{
|
||||
name: "three",
|
||||
in: "query"
|
||||
}
|
||||
]
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return validateHelper(spec)
|
||||
.then(system => {
|
||||
const allErrors = system.errSelectors.allErrors().toJS()
|
||||
expect(allErrors.length).toEqual(0)
|
||||
})
|
||||
})
|
||||
it("should return no errors for a valid OpenAPI 3 definition due to inheritance", () => {
|
||||
const spec = {
|
||||
openapi: "3.0.0",
|
||||
parameters: {
|
||||
MyParam: {
|
||||
name: "one",
|
||||
in: "query"
|
||||
}
|
||||
},
|
||||
"paths": {
|
||||
"/pets": {
|
||||
"parameters": [
|
||||
{
|
||||
name: "one",
|
||||
in: "query"
|
||||
},
|
||||
{
|
||||
name: "two",
|
||||
in: "query"
|
||||
}
|
||||
],
|
||||
"get": {
|
||||
"parameters": [
|
||||
{
|
||||
name: "two",
|
||||
in: "query"
|
||||
},
|
||||
{
|
||||
name: "three",
|
||||
in: "query"
|
||||
}
|
||||
]
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return validateHelper(spec)
|
||||
.then(system => {
|
||||
const allErrors = system.errSelectors.allErrors().toJS()
|
||||
expect(allErrors.length).toEqual(0)
|
||||
})
|
||||
})
|
||||
it("should not return an error for root parameters in Swagger 2", () => {
|
||||
const spec = {
|
||||
swagger: "2.0",
|
||||
parameters: {
|
||||
MyParam: {
|
||||
name: "one",
|
||||
in: "query"
|
||||
}
|
||||
},
|
||||
"paths": {
|
||||
"/pets": {
|
||||
"parameters": [
|
||||
{
|
||||
name: "otherParam",
|
||||
in: "query"
|
||||
}
|
||||
],
|
||||
"get": {
|
||||
"parameters": [
|
||||
{
|
||||
name: "one",
|
||||
in: "query"
|
||||
}
|
||||
]
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return validateHelper(spec)
|
||||
.then(system => {
|
||||
const allErrors = system.errSelectors.allErrors().toJS()
|
||||
expect(allErrors.length).toEqual(0)
|
||||
})
|
||||
})
|
||||
it("should not return an error for root parameters in OpenAPI 3", () => {
|
||||
const spec = {
|
||||
openapi: "3.0.0",
|
||||
parameters: {
|
||||
MyParam: {
|
||||
name: "one",
|
||||
in: "query"
|
||||
}
|
||||
},
|
||||
"paths": {
|
||||
"/pets": {
|
||||
"parameters": [
|
||||
{
|
||||
name: "otherParam",
|
||||
in: "query"
|
||||
}
|
||||
],
|
||||
"get": {
|
||||
"parameters": [
|
||||
{
|
||||
name: "one",
|
||||
in: "query"
|
||||
}
|
||||
]
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return validateHelper(spec)
|
||||
.then(system => {
|
||||
const allErrors = system.errSelectors.allErrors().toJS()
|
||||
expect(allErrors.length).toEqual(0)
|
||||
})
|
||||
})
|
||||
it("should return no errors for a valid Swagger 2 definition", () => {
|
||||
const spec = {
|
||||
swagger: "2.0",
|
||||
parameters: {
|
||||
MyParamOne: {
|
||||
name: "one",
|
||||
in: "query"
|
||||
},
|
||||
MyParamTwo: {
|
||||
name: "anotherParam1",
|
||||
in: "query"
|
||||
},
|
||||
},
|
||||
"paths": {
|
||||
"/pets/{one}/{two}": {
|
||||
"parameters": [
|
||||
{
|
||||
name: "one",
|
||||
in: "path",
|
||||
required: true
|
||||
},
|
||||
{
|
||||
name: "two",
|
||||
in: "query"
|
||||
},
|
||||
{
|
||||
name: "anotherParam2",
|
||||
in: "query"
|
||||
},
|
||||
],
|
||||
"get": {
|
||||
"parameters": [
|
||||
{
|
||||
name: "two",
|
||||
in: "path",
|
||||
required: true
|
||||
},
|
||||
{
|
||||
name: "three",
|
||||
in: "query"
|
||||
},
|
||||
{
|
||||
name: "anotherParam3",
|
||||
in: "query"
|
||||
},
|
||||
]
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return validateHelper(spec)
|
||||
.then(system => {
|
||||
const allErrors = system.errSelectors.allErrors().toJS()
|
||||
expect(allErrors).toEqual([])
|
||||
})
|
||||
})
|
||||
it("should return no errors for a valid OpenAPI 3 definition", () => {
|
||||
const spec = {
|
||||
openapi: "3.0.0",
|
||||
parameters: {
|
||||
MyParamOne: {
|
||||
name: "one",
|
||||
in: "query"
|
||||
},
|
||||
MyParamTwo: {
|
||||
name: "anotherParam1",
|
||||
in: "query"
|
||||
},
|
||||
},
|
||||
"paths": {
|
||||
"/pets/{one}/{two}": {
|
||||
"parameters": [
|
||||
{
|
||||
name: "one",
|
||||
in: "path",
|
||||
required: true
|
||||
},
|
||||
{
|
||||
name: "two",
|
||||
in: "query"
|
||||
},
|
||||
{
|
||||
name: "anotherParam2",
|
||||
in: "query"
|
||||
},
|
||||
],
|
||||
"get": {
|
||||
"parameters": [
|
||||
{
|
||||
name: "two",
|
||||
in: "path",
|
||||
required: true
|
||||
},
|
||||
{
|
||||
name: "three",
|
||||
in: "query"
|
||||
},
|
||||
{
|
||||
name: "anotherParam3",
|
||||
in: "query"
|
||||
},
|
||||
]
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return validateHelper(spec)
|
||||
.then(system => {
|
||||
const allErrors = system.errSelectors.allErrors().toJS()
|
||||
expect(allErrors.length).toEqual(0)
|
||||
})
|
||||
})
|
||||
})
|
||||
|
||||
})
|
||||
describe(`parameter defaults must be present in enums`, () => {
|
||||
it("should return an error for an invalid Swagger 2 definition", () => {
|
||||
const spec = {
|
||||
swagger: "2.0",
|
||||
"paths": {
|
||||
"/pets": {
|
||||
"get": {
|
||||
"parameters": [
|
||||
{
|
||||
"name": "num",
|
||||
"in": "query",
|
||||
"type": "number",
|
||||
enum: [1, 2, 3],
|
||||
default: 0
|
||||
},
|
||||
]
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return validateHelper(spec)
|
||||
.then(system => {
|
||||
const allErrors = system.errSelectors.allErrors().toJS()
|
||||
const firstError = allErrors[0]
|
||||
expect(allErrors.length).toEqual(1)
|
||||
expect(firstError.path).toEqual(["paths", "/pets", "get", "parameters", "0", "default"])
|
||||
expect(firstError.message).toEqual("Default values must be present in `enum`")
|
||||
})
|
||||
})
|
||||
it("should return an error for an invalid OpenAPI 3 definition", () => {
|
||||
const spec = {
|
||||
openapi: "3.0.0",
|
||||
"paths": {
|
||||
"/pets": {
|
||||
"get": {
|
||||
"parameters": [
|
||||
{
|
||||
"name": "num",
|
||||
"in": "query",
|
||||
"type": "number",
|
||||
schema: {
|
||||
enum: [1, 2, 3],
|
||||
default: 0
|
||||
}
|
||||
},
|
||||
]
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return validateHelper(spec)
|
||||
.then(system => {
|
||||
const allErrors = system.errSelectors.allErrors().toJS()
|
||||
const firstError = allErrors[0]
|
||||
expect(allErrors.length).toEqual(1)
|
||||
expect(firstError.path).toEqual(["paths", "/pets", "get", "parameters", "0", "schema", "default"])
|
||||
expect(firstError.message).toEqual("Default values must be present in `enum`")
|
||||
})
|
||||
})
|
||||
it("should return an error for an invalid OpenAPI 3 definition", () => {
|
||||
const spec = {
|
||||
openapi: "3.0.0",
|
||||
components: {
|
||||
parameters: {
|
||||
MyParam: {
|
||||
"name": "num",
|
||||
"in": "query",
|
||||
"type": "number",
|
||||
schema: {
|
||||
enum: [1, 2, 3],
|
||||
default: 0
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return validateHelper(spec)
|
||||
.then(system => {
|
||||
const allErrors = system.errSelectors.allErrors().toJS()
|
||||
const firstError = allErrors[0]
|
||||
expect(allErrors.length).toEqual(1)
|
||||
expect(firstError.path).toEqual(["components", "parameters", "MyParam", "schema", "default"])
|
||||
expect(firstError.message).toEqual("Default values must be present in `enum`")
|
||||
})
|
||||
})
|
||||
it("should return no errors for a Swagger 2 definition without default set", () => {
|
||||
const spec = {
|
||||
swagger: "2.0",
|
||||
"paths": {
|
||||
"/pets": {
|
||||
"get": {
|
||||
"parameters": [
|
||||
{
|
||||
"name": "num",
|
||||
"in": "query",
|
||||
"type": "number",
|
||||
enum: [1, 2, 3]
|
||||
},
|
||||
]
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return validateHelper(spec)
|
||||
.then(system => {
|
||||
const allErrors = system.errSelectors.allErrors().toJS()
|
||||
expect(allErrors.length).toEqual(0)
|
||||
})
|
||||
})
|
||||
it("should return no errors for an OpenAPI 3 definition without default set", () => {
|
||||
const spec = {
|
||||
openapi: "3.0.0",
|
||||
"paths": {
|
||||
"/pets": {
|
||||
"get": {
|
||||
"parameters": [
|
||||
{
|
||||
"name": "num",
|
||||
"in": "query",
|
||||
"type": "number",
|
||||
schema: {
|
||||
enum: [1, 2, 3]
|
||||
}
|
||||
},
|
||||
]
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return validateHelper(spec)
|
||||
.then(system => {
|
||||
const allErrors = system.errSelectors.allErrors().toJS()
|
||||
expect(allErrors.length).toEqual(0)
|
||||
})
|
||||
})
|
||||
it("should return no errors for a Swagger 2 definition without enum set", () => {
|
||||
const spec = {
|
||||
swagger: "2.0",
|
||||
"paths": {
|
||||
"/pets": {
|
||||
"get": {
|
||||
"parameters": [
|
||||
{
|
||||
"name": "num",
|
||||
"in": "query",
|
||||
"type": "number",
|
||||
default: 0
|
||||
},
|
||||
]
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return validateHelper(spec)
|
||||
.then(system => {
|
||||
const allErrors = system.errSelectors.allErrors().toJS()
|
||||
expect(allErrors.length).toEqual(0)
|
||||
})
|
||||
})
|
||||
it("should return no errors for an OpenAPI 3 definition without enum set", () => {
|
||||
const spec = {
|
||||
openapi: "3.0.0",
|
||||
"paths": {
|
||||
"/pets": {
|
||||
"get": {
|
||||
"parameters": [
|
||||
{
|
||||
"name": "num",
|
||||
"in": "query",
|
||||
"type": "number",
|
||||
schema: {
|
||||
default: 0
|
||||
}
|
||||
},
|
||||
]
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return validateHelper(spec)
|
||||
.then(system => {
|
||||
const allErrors = system.errSelectors.allErrors().toJS()
|
||||
expect(allErrors.length).toEqual(0)
|
||||
})
|
||||
})
|
||||
})
|
||||
|
||||
describe(`path parameters must be in path definition`, () => {
|
||||
it("should return no errors for a valid Swagger 2 definition", () => {
|
||||
const spec = {
|
||||
swagger: "2.0",
|
||||
info: {
|
||||
"title": "Correct path parameters in path",
|
||||
"version": "1.0.0"
|
||||
},
|
||||
"paths": {
|
||||
"/foo/{param1}/{param2}/{param3}": {
|
||||
"parameters": [
|
||||
{
|
||||
name: "param1",
|
||||
in: "path",
|
||||
required: true,
|
||||
type: "string"
|
||||
},
|
||||
{
|
||||
$ref: "#/parameters/param3"
|
||||
}
|
||||
],
|
||||
"get": {
|
||||
"parameters": [
|
||||
{
|
||||
name: "param2",
|
||||
in: "path",
|
||||
required: true,
|
||||
type: "string"
|
||||
}
|
||||
],
|
||||
responses: {
|
||||
"200": {
|
||||
"description": "ok"
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
parameters: {
|
||||
param3: {
|
||||
name: "param3",
|
||||
in: "path",
|
||||
required: true,
|
||||
type: "string"
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return validateHelper(spec)
|
||||
.then(system => {
|
||||
const allErrors = system.errSelectors.allErrors().toJS()
|
||||
expect(allErrors.length).toEqual(0)
|
||||
})
|
||||
})
|
||||
|
||||
it("should return 2 errors for each path parameter that isn't in the path in spec 2", () => {
|
||||
const spec = {
|
||||
swagger: "2.0",
|
||||
info: {
|
||||
"title": "Unused path parameters in path",
|
||||
"version": "1.0.0"
|
||||
},
|
||||
"paths": {
|
||||
"/foo": {
|
||||
"parameters": [
|
||||
{
|
||||
name: "param1",
|
||||
in: "path",
|
||||
required: true,
|
||||
type: "string"
|
||||
}
|
||||
],
|
||||
"get": {
|
||||
"parameters": [
|
||||
{
|
||||
name: "param2",
|
||||
in: "path",
|
||||
required: true,
|
||||
type: "string"
|
||||
}
|
||||
],
|
||||
responses: {
|
||||
"200": {
|
||||
"description": "ok"
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return validateHelper(spec)
|
||||
.then(system => {
|
||||
const allErrors = system.errSelectors.allErrors().toJS()
|
||||
expect(allErrors.length).toEqual(2)
|
||||
const firstError = allErrors[0]
|
||||
expect(firstError.path).toEqual(["paths", "/foo", "parameters", "0","name"])
|
||||
expect(firstError.message).toEqual(`Path parameter "param1" must have the corresponding {param1} segment in the "/foo" path`)
|
||||
const secondError = allErrors[1]
|
||||
expect(secondError.path).toEqual(["paths", "/foo", "get", "parameters", "0","name"])
|
||||
expect(secondError.message).toEqual(`Path parameter "param2" must have the corresponding {param2} segment in the "/foo" path`)
|
||||
})
|
||||
})
|
||||
|
||||
it("should return 2 errors for each referenced path parameter that isn't in the path for 2 spec", () => {
|
||||
const spec = {
|
||||
swagger: "2.0",
|
||||
info: {
|
||||
"title": "Unused path parameters in path",
|
||||
"version": "1.0.0"
|
||||
},
|
||||
"paths": {
|
||||
"/foo/{param1}/{param2}": {
|
||||
"parameters": [
|
||||
{
|
||||
name: "param1",
|
||||
in: "path",
|
||||
required: true,
|
||||
type: "string"
|
||||
},
|
||||
{
|
||||
$ref: "#/parameters/param3"
|
||||
}
|
||||
],
|
||||
"get": {
|
||||
"parameters": [
|
||||
{
|
||||
name: "param2",
|
||||
in: "path",
|
||||
required: true,
|
||||
type: "string"
|
||||
},
|
||||
{
|
||||
$ref: "#/parameters/param4"
|
||||
}
|
||||
],
|
||||
responses: {
|
||||
"200": {
|
||||
"description": "ok"
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
parameters: {
|
||||
param3: {
|
||||
name: "param3",
|
||||
in: "path",
|
||||
required: true,
|
||||
type: "string"
|
||||
},
|
||||
param4: {
|
||||
name: "param4",
|
||||
in: "path",
|
||||
required: true,
|
||||
type: "string"
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return validateHelper(spec)
|
||||
.then(system => {
|
||||
const allErrors = system.errSelectors.allErrors().toJS()
|
||||
expect(allErrors.length).toEqual(2)
|
||||
const firstError = allErrors[0]
|
||||
expect(firstError.path).toEqual(["paths", "/foo/{param1}/{param2}", "parameters", "1","name"])
|
||||
expect(firstError.message).toEqual(`Path parameter "param3" must have the corresponding {param3} segment in the "/foo/{param1}/{param2}" path`)
|
||||
const secondError = allErrors[1]
|
||||
expect(secondError.path).toEqual(["paths", "/foo/{param1}/{param2}","get", "parameters", "1","name"])
|
||||
expect(secondError.message).toEqual(`Path parameter "param4" must have the corresponding {param4} segment in the "/foo/{param1}/{param2}" path`)
|
||||
})
|
||||
})
|
||||
|
||||
it("should return no errors for a valid Swagger 3 definition", () => {
|
||||
const spec = {
|
||||
swagger: "3.0",
|
||||
info: {
|
||||
"title": "Correct path parameters in path",
|
||||
"version": "1.0.0"
|
||||
},
|
||||
"paths": {
|
||||
"/foo/{param1}/{param2}/{param3}": {
|
||||
"parameters": [
|
||||
{
|
||||
name: "param1",
|
||||
in: "path",
|
||||
required: true,
|
||||
type: "string"
|
||||
},
|
||||
{
|
||||
$ref: "#/parameters/param3"
|
||||
}
|
||||
],
|
||||
"get": {
|
||||
"parameters": [
|
||||
{
|
||||
name: "param2",
|
||||
in: "path",
|
||||
required: true,
|
||||
type: "string"
|
||||
}
|
||||
],
|
||||
responses: {
|
||||
"200": {
|
||||
"description": "ok"
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
components: {
|
||||
parameters: {
|
||||
param3: {
|
||||
name: "param3",
|
||||
in: "path",
|
||||
required: true,
|
||||
type: "string"
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return validateHelper(spec)
|
||||
.then(system => {
|
||||
const allErrors = system.errSelectors.allErrors().toJS()
|
||||
expect(allErrors.length).toEqual(0)
|
||||
})
|
||||
})
|
||||
|
||||
it("should return 2 errors for each path parameter that isn't in the path in spec 3", () => {
|
||||
const spec = {
|
||||
openapi: "3.0.2",
|
||||
info: {
|
||||
"title": "Unused path parameters in path",
|
||||
"version": "1.0.0"
|
||||
},
|
||||
"paths": {
|
||||
"/foo": {
|
||||
"parameters": [
|
||||
{
|
||||
name: "param1",
|
||||
in: "path",
|
||||
required: true,
|
||||
type: "string"
|
||||
}
|
||||
],
|
||||
"get": {
|
||||
"parameters": [
|
||||
{
|
||||
name: "param2",
|
||||
in: "path",
|
||||
required: true,
|
||||
type: "string"
|
||||
}
|
||||
],
|
||||
responses: {
|
||||
"200": {
|
||||
"description": "ok"
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return validateHelper(spec)
|
||||
.then(system => {
|
||||
const allErrors = system.errSelectors.allErrors().toJS()
|
||||
expect(allErrors.length).toEqual(2)
|
||||
const firstError = allErrors[0]
|
||||
expect(firstError.path).toEqual(["paths", "/foo", "parameters", "0","name"])
|
||||
expect(firstError.message).toEqual(`Path parameter "param1" must have the corresponding {param1} segment in the "/foo" path`)
|
||||
const secondError = allErrors[1]
|
||||
expect(secondError.path).toEqual(["paths", "/foo", "get", "parameters", "0","name"])
|
||||
expect(secondError.message).toEqual(`Path parameter "param2" must have the corresponding {param2} segment in the "/foo" path`)
|
||||
})
|
||||
})
|
||||
|
||||
it("should return 2 errors for each referenced path parameter that isn't in the path for 3 spec", () => {
|
||||
const spec = {
|
||||
openapi: "3.0.2",
|
||||
info: {
|
||||
"title": "Unused path parameters in path",
|
||||
"version": "1.0.0"
|
||||
},
|
||||
"paths": {
|
||||
"/foo/{param1}/{param2}": {
|
||||
"parameters": [
|
||||
{
|
||||
name: "param1",
|
||||
in: "path",
|
||||
required: true,
|
||||
type: "string"
|
||||
},
|
||||
{
|
||||
$ref: "#/components/parameters/param3"
|
||||
}
|
||||
],
|
||||
"get": {
|
||||
"parameters": [
|
||||
{
|
||||
name: "param2",
|
||||
in: "path",
|
||||
required: true,
|
||||
type: "string"
|
||||
},
|
||||
{
|
||||
$ref: "#/components/parameters/param4"
|
||||
}
|
||||
],
|
||||
responses: {
|
||||
"200": {
|
||||
"description": "ok"
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
components: {
|
||||
parameters: {
|
||||
param3: {
|
||||
name: "param3",
|
||||
in: "path",
|
||||
required: true,
|
||||
type: "string"
|
||||
},
|
||||
param4: {
|
||||
name: "param4",
|
||||
in: "path",
|
||||
required: true,
|
||||
type: "string"
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return validateHelper(spec)
|
||||
.then(system => {
|
||||
const allErrors = system.errSelectors.allErrors().toJS()
|
||||
expect(allErrors.length).toEqual(2)
|
||||
const firstError = allErrors[0]
|
||||
expect(firstError.path).toEqual(["paths", "/foo/{param1}/{param2}", "parameters", "1","name"])
|
||||
expect(firstError.message).toEqual(`Path parameter "param3" must have the corresponding {param3} segment in the "/foo/{param1}/{param2}" path`)
|
||||
const secondError = allErrors[1]
|
||||
expect(secondError.path).toEqual(["paths", "/foo/{param1}/{param2}","get", "parameters", "1","name"])
|
||||
expect(secondError.message).toEqual(`Path parameter "param4" must have the corresponding {param4} segment in the "/foo/{param1}/{param2}" path`)
|
||||
})
|
||||
})
|
||||
})
|
||||
})
|
||||
@@ -0,0 +1,484 @@
|
||||
/* eslint-env mocha */
|
||||
import expect from "expect"
|
||||
import validateHelper, { expectNoErrors } from "../validate-helper.js"
|
||||
|
||||
describe("validation plugin - semantic - 2and3 paths", () => {
|
||||
describe("Paths cannot have query strings in them", () => {
|
||||
it("should return one problem for an stray '?' in a Swagger 2 path string", function(){
|
||||
const spec = {
|
||||
swagger: "2.0",
|
||||
paths: {
|
||||
"/report?asdf=123": {
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return validateHelper(spec)
|
||||
.then( system => {
|
||||
const allErrors = system.errSelectors.allErrors().toJS()
|
||||
expect(allErrors.length).toEqual(1)
|
||||
const firstError = allErrors[0]
|
||||
expect(firstError.message).toEqual("Query strings in paths are not allowed.")
|
||||
expect(firstError.path).toEqual(["paths", "/report?asdf=123"])
|
||||
})
|
||||
})
|
||||
it("should return one problem for an stray '?' in an OpenAPI 3 path string", function(){
|
||||
const spec = {
|
||||
openapi: "3.0.0",
|
||||
paths: {
|
||||
"/report?asdf=123": {
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return validateHelper(spec)
|
||||
.then( system => {
|
||||
const allErrors = system.errSelectors.allErrors().toJS()
|
||||
expect(allErrors.length).toEqual(1)
|
||||
const firstError = allErrors[0]
|
||||
expect(firstError.message).toEqual("Query strings in paths are not allowed.")
|
||||
expect(firstError.path).toEqual(["paths", "/report?asdf=123"])
|
||||
})
|
||||
})
|
||||
it("should return no problems for a correct Swagger 2 path template", function(){
|
||||
const spec = {
|
||||
swagger: "2.0",
|
||||
paths: {
|
||||
"/CoolPath/{id}": {
|
||||
parameters: [{
|
||||
name: "id",
|
||||
in: "path",
|
||||
required: true
|
||||
}]
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return expectNoErrors(spec)
|
||||
})
|
||||
it("should return no problems for a correct OpenAPI 3 path template", function(){
|
||||
const spec = {
|
||||
openapi: "3.0.0",
|
||||
paths: {
|
||||
"/CoolPath/{id}": {
|
||||
parameters: [{
|
||||
name: "id",
|
||||
in: "path",
|
||||
required: true
|
||||
}]
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return expectNoErrors(spec)
|
||||
})
|
||||
})
|
||||
|
||||
describe("Path parameter definitions need matching paramater declarations", function(){
|
||||
describe("OpenAPI 3", () => {
|
||||
it("should not return problems for a valid path-level definiton/declaration pair", function(){
|
||||
const spec = {
|
||||
openapi: "3.0.0",
|
||||
paths: {
|
||||
"/CoolPath/{id}": {
|
||||
parameters: [{
|
||||
name: "id",
|
||||
in: "path",
|
||||
description: "An id",
|
||||
required: true
|
||||
}]
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return expectNoErrors(spec)
|
||||
})
|
||||
|
||||
it("should not return problems for a valid path-level definiton/declaration pair using a $ref", function(){
|
||||
const spec = {
|
||||
openapi: "3.0.0",
|
||||
paths: {
|
||||
"/CoolPath/{id}": {
|
||||
parameters: [
|
||||
{ $ref: "#/parameters/id" }
|
||||
]
|
||||
}
|
||||
},
|
||||
parameters: {
|
||||
id: {
|
||||
name: "id",
|
||||
in: "path",
|
||||
description: "An id",
|
||||
required: true
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return expectNoErrors(spec)
|
||||
})
|
||||
|
||||
it("should not return problems for a valid operation-level definiton/declaration pair", function(){
|
||||
const spec = {
|
||||
openapi: "3.0.0",
|
||||
paths: {
|
||||
"/CoolPath/{id}": {
|
||||
get: {
|
||||
parameters: [{
|
||||
name: "id",
|
||||
in: "path",
|
||||
description: "An id",
|
||||
required: true
|
||||
}]
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return expectNoErrors(spec)
|
||||
})
|
||||
|
||||
it("should return one problem for a path parameter defined at the operation level that is not present within every operation on the path", function(){
|
||||
const spec = {
|
||||
openapi: "3.0.0",
|
||||
paths: {
|
||||
"/CoolPath/{id}": {
|
||||
get: {
|
||||
parameters: [{
|
||||
name: "id",
|
||||
in: "path",
|
||||
description: "An id",
|
||||
required: true
|
||||
}]
|
||||
},
|
||||
post: {
|
||||
description: "the path parameter definition is missing here"
|
||||
},
|
||||
delete: {
|
||||
description: "the path parameter definition is missing here"
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return validateHelper(spec)
|
||||
.then(system => {
|
||||
const allErrors = system.errSelectors.allErrors().toJS()
|
||||
const firstError = allErrors[0]
|
||||
expect(allErrors.length).toEqual(1)
|
||||
expect(firstError.message).toEqual( `Declared path parameter \"id\" needs to be defined within every operation in the path (missing in "post", "delete"), or moved to the path-level parameters object`)
|
||||
expect(firstError.path).toEqual(["paths", "/CoolPath/{id}"])
|
||||
})
|
||||
})
|
||||
|
||||
it("should return one problem when the definition is completely absent", function(){
|
||||
const spec = {
|
||||
openapi: "3.0.0",
|
||||
paths: {
|
||||
"/CoolPath/{id}": {
|
||||
parameters: []
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return validateHelper(spec)
|
||||
.then(system => {
|
||||
const allErrors = system.errSelectors.allErrors().toJS()
|
||||
const firstError = allErrors[0]
|
||||
expect(allErrors.length).toEqual(1)
|
||||
expect(firstError.message).toEqual( "Declared path parameter \"id\" needs to be defined as a path parameter at either the path or operation level")
|
||||
expect(firstError.path).toEqual(["paths", "/CoolPath/{id}"])
|
||||
})
|
||||
|
||||
})
|
||||
|
||||
it("should return one error when no parameters are defined", function(){
|
||||
const spec = {
|
||||
openapi: "3.0.0",
|
||||
paths: {
|
||||
"/CoolPath/{id}": {}
|
||||
}
|
||||
}
|
||||
|
||||
return validateHelper(spec)
|
||||
.then(system => {
|
||||
const allErrors = system.errSelectors.allErrors().toJS()
|
||||
const firstError = allErrors[0]
|
||||
expect(allErrors.length).toEqual(1)
|
||||
expect(firstError.message).toEqual( "Declared path parameter \"id\" needs to be defined as a path parameter at either the path or operation level")
|
||||
expect(firstError.path).toEqual(["paths", "/CoolPath/{id}"])
|
||||
})
|
||||
|
||||
})
|
||||
|
||||
it("should return one problem for a missed 'in' value", function(){
|
||||
const spec = {
|
||||
openapi: "3.0.0",
|
||||
paths: {
|
||||
"/CoolPath/{id}": {
|
||||
parameters: [{
|
||||
name: "id",
|
||||
// in: "path",
|
||||
description: "An id"
|
||||
}]
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return validateHelper(spec)
|
||||
.then(system => {
|
||||
const allErrors = system.errSelectors.allErrors().toJS()
|
||||
const firstError = allErrors[0]
|
||||
expect(allErrors.length).toEqual(1)
|
||||
expect(firstError.message).toEqual( "Declared path parameter \"id\" needs to be defined as a path parameter at either the path or operation level")
|
||||
expect(firstError.path).toEqual(["paths", "/CoolPath/{id}"])
|
||||
})
|
||||
})
|
||||
})
|
||||
|
||||
describe("Swagger 2", () => {
|
||||
it("should not return problems for a valid path-level definiton/declaration pair", function(){
|
||||
const spec = {
|
||||
swagger: "2.0",
|
||||
paths: {
|
||||
"/CoolPath/{id}": {
|
||||
parameters: [{
|
||||
name: "id",
|
||||
in: "path",
|
||||
description: "An id",
|
||||
required: true
|
||||
}]
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return expectNoErrors(spec)
|
||||
})
|
||||
|
||||
it("should not return problems for a valid path-level definiton/declaration pair using a $ref", function(){
|
||||
const spec = {
|
||||
swagger: "2.0",
|
||||
paths: {
|
||||
"/CoolPath/{id}": {
|
||||
parameters: [
|
||||
{ $ref: "#/parameters/id" }
|
||||
]
|
||||
}
|
||||
},
|
||||
parameters: {
|
||||
id: {
|
||||
name: "id",
|
||||
in: "path",
|
||||
description: "An id",
|
||||
required: true
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return expectNoErrors(spec)
|
||||
})
|
||||
|
||||
it("should not return problems for a valid operation-level definiton/declaration pair", function(){
|
||||
const spec = {
|
||||
swagger: "2.0",
|
||||
paths: {
|
||||
"/CoolPath/{id}": {
|
||||
get: {
|
||||
parameters: [{
|
||||
name: "id",
|
||||
in: "path",
|
||||
description: "An id",
|
||||
required: true
|
||||
}]
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return expectNoErrors(spec)
|
||||
})
|
||||
|
||||
it("should return one problem for a path parameter defined at the operation level that is not present within every operation on the path", function(){
|
||||
const spec = {
|
||||
swagger: "2.0",
|
||||
paths: {
|
||||
"/CoolPath/{id}": {
|
||||
get: {
|
||||
parameters: [{
|
||||
name: "id",
|
||||
in: "path",
|
||||
description: "An id",
|
||||
required: true
|
||||
}]
|
||||
},
|
||||
post: {
|
||||
description: "the path parameter definition is missing here"
|
||||
},
|
||||
delete: {
|
||||
description: "the path parameter definition is missing here"
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return validateHelper(spec)
|
||||
.then(system => {
|
||||
const allErrors = system.errSelectors.allErrors().toJS()
|
||||
const firstError = allErrors[0]
|
||||
expect(allErrors.length).toEqual(1)
|
||||
expect(firstError.message).toEqual( `Declared path parameter \"id\" needs to be defined within every operation in the path (missing in "post", "delete"), or moved to the path-level parameters object`)
|
||||
expect(firstError.path).toEqual(["paths", "/CoolPath/{id}"])
|
||||
})
|
||||
})
|
||||
|
||||
it("should return one problem when the definition is completely absent", function(){
|
||||
const spec = {
|
||||
swagger: "2.0",
|
||||
paths: {
|
||||
"/CoolPath/{id}": {
|
||||
parameters: []
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return validateHelper(spec)
|
||||
.then(system => {
|
||||
const allErrors = system.errSelectors.allErrors().toJS()
|
||||
const firstError = allErrors[0]
|
||||
expect(allErrors.length).toEqual(1)
|
||||
expect(firstError.message).toEqual( "Declared path parameter \"id\" needs to be defined as a path parameter at either the path or operation level")
|
||||
expect(firstError.path).toEqual(["paths", "/CoolPath/{id}"])
|
||||
})
|
||||
|
||||
})
|
||||
|
||||
it("should return one error when no parameters are defined", function(){
|
||||
const spec = {
|
||||
swagger: "2.0",
|
||||
info: {
|
||||
title: "test",
|
||||
version: "1.0.0"
|
||||
},
|
||||
paths: {
|
||||
"/{12345instanceABCDE_instance_12345}": {
|
||||
get: {
|
||||
responses: {
|
||||
"200": {
|
||||
description: "ok"
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return validateHelper(spec)
|
||||
.then(system => {
|
||||
const allErrors = system.errSelectors.allErrors().toJS()
|
||||
const firstError = allErrors[0]
|
||||
expect(allErrors.length).toEqual(1)
|
||||
expect(firstError.message).toEqual( "Declared path parameter \"12345instanceABCDE_instance_12345\" needs to be defined as a path parameter at either the path or operation level")
|
||||
expect(firstError.path).toEqual(["paths", "/{12345instanceABCDE_instance_12345}"])
|
||||
})
|
||||
|
||||
})
|
||||
|
||||
it("should return a well-formed error when ", function(){
|
||||
const spec = {
|
||||
swagger: "2.0",
|
||||
paths: {
|
||||
"/CoolPath/{id}": {}
|
||||
}
|
||||
}
|
||||
|
||||
return validateHelper(spec)
|
||||
.then(system => {
|
||||
const allErrors = system.errSelectors.allErrors().toJS()
|
||||
const firstError = allErrors[0]
|
||||
expect(allErrors.length).toEqual(1)
|
||||
expect(firstError.message).toEqual( "Declared path parameter \"id\" needs to be defined as a path parameter at either the path or operation level")
|
||||
expect(firstError.path).toEqual(["paths", "/CoolPath/{id}"])
|
||||
})
|
||||
|
||||
})
|
||||
|
||||
it.skip("should return one problem for a missed 'in' value", function(){
|
||||
const spec = {
|
||||
swagger: "2.0",
|
||||
paths: {
|
||||
"/CoolPath/{id}": {
|
||||
parameters: [{
|
||||
name: "id",
|
||||
// in: "path",
|
||||
description: "An id"
|
||||
}]
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return validateHelper(spec)
|
||||
.then(system => {
|
||||
const allErrors = system.errSelectors.allErrors().toJS()
|
||||
const firstError = allErrors[0]
|
||||
expect(allErrors.length).toEqual(1)
|
||||
expect(firstError.message).toEqual( "Declared path parameter \"id\" needs to be defined as a path parameter at either the path or operation level")
|
||||
expect(firstError.path).toEqual(["paths", "/CoolPath/{id}"])
|
||||
})
|
||||
})
|
||||
|
||||
it("should return a specific error for parameters with different casing characters OpenAPI 3 definition", () => {
|
||||
const spec = {
|
||||
openapi: "3.0.1",
|
||||
"paths": {
|
||||
"/{myParam}": {
|
||||
"get": {
|
||||
"parameters": [
|
||||
{
|
||||
"name": "myparam",
|
||||
"in": "path",
|
||||
"required": true,
|
||||
"schema": {
|
||||
"type": "string"
|
||||
}
|
||||
},
|
||||
]
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return validateHelper(spec)
|
||||
.then(system => {
|
||||
const allErrors = system.errSelectors.allErrors().toJS()
|
||||
const firstError = allErrors[0]
|
||||
expect(allErrors.length).toEqual(1)
|
||||
expect(firstError.message).toEqual("Parameter names are case-sensitive. The parameter named \"myparam\" does not match the case used in the path \"/{myParam}\".")
|
||||
})
|
||||
})
|
||||
})
|
||||
|
||||
it("should return no errors for parameters with same characters in path and parameters definition", () => {
|
||||
const spec = {
|
||||
openapi: "3.0.1",
|
||||
"paths": {
|
||||
"/{myParam}": {
|
||||
"get": {
|
||||
"parameters": [
|
||||
{
|
||||
"name": "myParam",
|
||||
"in": "path",
|
||||
"required": true,
|
||||
"schema": {
|
||||
"type": "string"
|
||||
}
|
||||
},
|
||||
]
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
return expectNoErrors(spec)
|
||||
})
|
||||
})
|
||||
})
|
||||
@@ -0,0 +1,698 @@
|
||||
import expect from "expect"
|
||||
import validateHelper, { expectNoErrorsOrWarnings } from "../validate-helper.js"
|
||||
|
||||
describe("validation plugin - semantic - 2and3 refs", function() {
|
||||
this.timeout(10 * 1000)
|
||||
describe("Ref siblings", () => {
|
||||
|
||||
it("should return a warning when another property is a sibling of a $ref in OpenAPI 3", () => {
|
||||
const spec = {
|
||||
openapi: "3.0.0",
|
||||
paths: {
|
||||
"/CoolPath": {
|
||||
get: {
|
||||
$ref: "#/components/schemas/abc",
|
||||
description: "My very cool get"
|
||||
}
|
||||
}
|
||||
},
|
||||
components: {
|
||||
schemas: {
|
||||
abc: {}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return validateHelper(spec)
|
||||
.then(system => {
|
||||
const allErrors = system.errSelectors.allErrors().toJS()
|
||||
expect(allErrors.length).toEqual(1)
|
||||
const firstError = allErrors[0]
|
||||
expect(firstError.message).toMatch("Sibling values alongside $refs are ignored.\nTo add properties to a $ref, wrap the $ref into allOf, or move the extra properties into the referenced definition (if applicable).")
|
||||
expect(firstError.level).toEqual("warning")
|
||||
expect(firstError.path).toEqual(["paths", "/CoolPath", "get", "description"])
|
||||
})
|
||||
})
|
||||
it("should return a warning when another property is a sibling of a $ref in Swagger 2", () => {
|
||||
const spec = {
|
||||
swagger: "2.0",
|
||||
paths: {
|
||||
"/CoolPath": {
|
||||
get: {
|
||||
$ref: "#/definitions/abc",
|
||||
description: "My very cool get"
|
||||
}
|
||||
}
|
||||
},
|
||||
definitions: {
|
||||
abc: {}
|
||||
}
|
||||
}
|
||||
|
||||
return validateHelper(spec)
|
||||
.then(system => {
|
||||
const allErrors = system.errSelectors.allErrors().toJS()
|
||||
expect(allErrors.length).toEqual(1)
|
||||
const firstError = allErrors[0]
|
||||
expect(firstError.message).toMatch("Sibling values alongside $refs are ignored.\nTo add properties to a $ref, wrap the $ref into allOf, or move the extra properties into the referenced definition (if applicable).")
|
||||
expect(firstError.level).toEqual("warning")
|
||||
expect(firstError.path).toEqual(["paths", "/CoolPath", "get", "description"])
|
||||
})
|
||||
})
|
||||
|
||||
it("should return no warnings when a $ref has no siblings in OpenAPI 3", () => {
|
||||
const spec = {
|
||||
openapi: "3.0.0",
|
||||
paths: {
|
||||
"/CoolPath": {
|
||||
get: {
|
||||
$ref: "#/components/schemas/abc"
|
||||
}
|
||||
}
|
||||
},
|
||||
components: {
|
||||
schemas: {
|
||||
abc: {}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return expectNoErrorsOrWarnings(spec)
|
||||
})
|
||||
it("should return no warnings when a $ref has no siblings in Swagger 2", () => {
|
||||
const spec = {
|
||||
swagger: "2.0",
|
||||
paths: {
|
||||
"/CoolPath": {
|
||||
get: {
|
||||
$ref: "#/definitions/abc"
|
||||
}
|
||||
}
|
||||
},
|
||||
definitions: {
|
||||
abc: {}
|
||||
}
|
||||
}
|
||||
|
||||
return expectNoErrorsOrWarnings(spec)
|
||||
})
|
||||
|
||||
it("should return no warnings when a path item $ref has siblings in OpenAPI 3", () => {
|
||||
const spec = {
|
||||
openapi: "3.0.0",
|
||||
paths: {
|
||||
$ref: "#/components/schemas/abc",
|
||||
"/CoolPath": {
|
||||
get: {
|
||||
$ref: "#/components/schemas/abc"
|
||||
}
|
||||
}
|
||||
},
|
||||
components: {
|
||||
schemas: {
|
||||
abc: {}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return expectNoErrorsOrWarnings(spec)
|
||||
})
|
||||
it("should return no warnings when a path item $ref has siblings in Swagger 2", () => {
|
||||
const spec = {
|
||||
swagger: "2.0",
|
||||
paths: {
|
||||
$ref: "#/definitions/abc",
|
||||
"/CoolPath": {
|
||||
get: {
|
||||
$ref: "#/definitions/abc"
|
||||
}
|
||||
}
|
||||
},
|
||||
definitions: {
|
||||
abc: {}
|
||||
}
|
||||
}
|
||||
|
||||
return expectNoErrorsOrWarnings(spec)
|
||||
})
|
||||
|
||||
})
|
||||
describe("Unused definitions", () => {
|
||||
it("should return a warning when a definition is declared but not used in OpenAPI 3", () => {
|
||||
const spec = {
|
||||
openapi: "3.0.0",
|
||||
components: {
|
||||
schemas: {
|
||||
"x-Foo": {
|
||||
type: "object"
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return validateHelper(spec)
|
||||
.then(system => {
|
||||
const allErrors = system.errSelectors.allErrors().toJS()
|
||||
expect(allErrors.length).toEqual(1)
|
||||
const firstError = allErrors[0]
|
||||
expect(firstError.message).toMatch("Definition was declared but never used in document")
|
||||
expect(firstError.level).toEqual("warning")
|
||||
expect(firstError.path).toEqual(["components", "schemas", "x-Foo"])
|
||||
})
|
||||
})
|
||||
|
||||
it("should not return a warning when a definition with special characters is properly referenced in OpenAPI 3", () => {
|
||||
const spec = {
|
||||
openapi: "3.0.0",
|
||||
paths: {
|
||||
"/CoolPath": {
|
||||
get: {
|
||||
responses: {
|
||||
200: {
|
||||
content: {
|
||||
"application/json": {
|
||||
schema: {
|
||||
$ref: "#/components/schemas/x~1Foo"
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
400: {
|
||||
content: {
|
||||
"application/json": {
|
||||
schema: {
|
||||
$ref: "#/components/schemas/x~0Bar"
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
components: {
|
||||
schemas: {
|
||||
"x/Foo": {
|
||||
type: "object"
|
||||
},
|
||||
"x~Bar": {
|
||||
type: "object"
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return validateHelper(spec)
|
||||
.then(system => {
|
||||
// We want warnings only, without errors about invalid component names
|
||||
const allWarnings = system.errSelectors.allErrors().toJS()
|
||||
.filter(err => err.level === "warning")
|
||||
expect(allWarnings.length).toEqual(0)
|
||||
})
|
||||
})
|
||||
|
||||
it("should return a warning when a definition is declared but not used in Swagger 2", () => {
|
||||
const spec = {
|
||||
swagger: "2.0",
|
||||
paths: {
|
||||
"/CoolPath": {}
|
||||
},
|
||||
definitions: {
|
||||
abc: {
|
||||
type: "string"
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return validateHelper(spec)
|
||||
.then(system => {
|
||||
const allErrors = system.errSelectors.allErrors().toJS()
|
||||
expect(allErrors.length).toEqual(1)
|
||||
const firstError = allErrors[0]
|
||||
expect(firstError.message).toMatch("Definition was declared but never used in document")
|
||||
expect(firstError.level).toEqual("warning")
|
||||
expect(firstError.path).toEqual(["definitions", "abc"])
|
||||
})
|
||||
})
|
||||
|
||||
it("should not return a warning when a definition with special character is declared and used in Swagger 2", () => {
|
||||
const spec = {
|
||||
swagger: "2.0",
|
||||
paths: {
|
||||
"/CoolPath": {
|
||||
get: {
|
||||
responses: {
|
||||
200: {
|
||||
schema: {
|
||||
$ref: "#/definitions/x~1Foo"
|
||||
}
|
||||
},
|
||||
400: {
|
||||
schema: {
|
||||
$ref: "#/definitions/x~0Bar"
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
definitions: {
|
||||
"x/Foo": {
|
||||
type: "object"
|
||||
},
|
||||
"x~Bar": {
|
||||
type: "object"
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return validateHelper(spec)
|
||||
.then(system => {
|
||||
const allErrors = system.errSelectors.allErrors().toJS()
|
||||
expect(allErrors.length).toEqual(0)
|
||||
})
|
||||
})
|
||||
|
||||
})
|
||||
describe("Malformed $ref values", () => {
|
||||
it("should return an error when a JSON pointer lacks a leading `#/` in Swagger 2", () => {
|
||||
const spec = {
|
||||
swagger: "2.0",
|
||||
paths: {
|
||||
"/CoolPath": {
|
||||
$ref: "#myObj/abc"
|
||||
}
|
||||
},
|
||||
myObj: {
|
||||
abc: {
|
||||
type: "string"
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return validateHelper(spec)
|
||||
.then(system => {
|
||||
const allErrors = system.errSelectors.allErrors().toJS()
|
||||
expect(allErrors.length).toEqual(1)
|
||||
const firstError = allErrors[0]
|
||||
expect(firstError.message).toMatch("$ref paths must begin with `#/`")
|
||||
expect(firstError.level).toEqual("error")
|
||||
expect(firstError.path).toEqual(["paths", "/CoolPath", "$ref"])
|
||||
})
|
||||
})
|
||||
it("should return an error when a JSON pointer lacks a leading `#/` in OpenAPI 3", () => {
|
||||
const spec = {
|
||||
openapi: "3.0.0",
|
||||
paths: {
|
||||
"/CoolPath": {
|
||||
$ref: "#myObj/abc"
|
||||
}
|
||||
},
|
||||
myObj: {
|
||||
abc: {
|
||||
type: "string"
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return validateHelper(spec)
|
||||
.then(system => {
|
||||
const allErrors = system.errSelectors.allErrors().toJS()
|
||||
expect(allErrors.length).toEqual(1)
|
||||
const firstError = allErrors[0]
|
||||
expect(firstError.message).toMatch("$ref paths must begin with `#/`")
|
||||
expect(firstError.level).toEqual("error")
|
||||
expect(firstError.path).toEqual(["paths", "/CoolPath", "$ref"])
|
||||
})
|
||||
})
|
||||
it("should return no errors when a JSON pointer is a well-formed remote reference in Swagger 2", () => {
|
||||
const spec = {
|
||||
swagger: "2.0",
|
||||
paths: {
|
||||
"/CoolPath": {
|
||||
$ref: "http://google.com#/myObj/abc"
|
||||
},
|
||||
},
|
||||
myObj: {
|
||||
abc: {
|
||||
type: "string",
|
||||
properties: {
|
||||
$ref: "http://google.com/MyRegularURLReference"
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return validateHelper(spec)
|
||||
.then(system => {
|
||||
const allSemanticErrors = system.errSelectors.allErrors().toJS()
|
||||
.filter(err => err.source !== "resolver")
|
||||
expect(allSemanticErrors).toEqual([])
|
||||
})
|
||||
})
|
||||
it("should return no errors when a JSON pointer is a well-formed remote reference in OpenAPI 3", () => {
|
||||
const spec = {
|
||||
openapi: "3.0.0",
|
||||
paths: {
|
||||
"/CoolPath": {
|
||||
$ref: "http://google.com#/myObj/abc"
|
||||
},
|
||||
},
|
||||
myObj: {
|
||||
abc: {
|
||||
type: "string",
|
||||
properties: {
|
||||
$ref: "http://google.com/MyRegularURLReference"
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return validateHelper(spec)
|
||||
.then(system => {
|
||||
const allSemanticErrors = system.errSelectors.allErrors().toJS()
|
||||
.filter(err => err.source !== "resolver")
|
||||
expect(allSemanticErrors).toEqual([])
|
||||
})
|
||||
})
|
||||
it("should return an error when a JSON pointer uses incorrect percent-encoding in Swagger 2", () => {
|
||||
const spec = {
|
||||
"swagger": "2.0",
|
||||
"paths": {
|
||||
"/foo": {
|
||||
"get": {
|
||||
"responses": {
|
||||
"200": {
|
||||
"description": "Success",
|
||||
"schema": {
|
||||
"$ref": "#/definitions/foo bar"
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"definitions": {
|
||||
"foo bar": {
|
||||
"type": "string"
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return validateHelper(spec)
|
||||
.then(system => {
|
||||
const allSemanticErrors = system.errSelectors.allErrors().toJS()
|
||||
.filter(err => err.source !== "resolver")
|
||||
expect(allSemanticErrors[0]).toInclude({
|
||||
level: "warning",
|
||||
message: "Definition was declared but never used in document",
|
||||
path: ["definitions", "foo bar"]
|
||||
})
|
||||
expect(allSemanticErrors.length).toEqual(2)
|
||||
expect(allSemanticErrors[1]).toInclude({
|
||||
level: "error",
|
||||
message: "$ref values must be RFC3986-compliant percent-encoded URIs",
|
||||
path: ["paths", "/foo", "get", "responses", "200", "schema", "$ref"]
|
||||
})
|
||||
})
|
||||
})
|
||||
it("should return an error when a JSON pointer uses incorrect percent-encoding in OpenAPI 3", () => {
|
||||
const spec = {
|
||||
"openapi": "3.0.0",
|
||||
"paths": {
|
||||
"/foo": {
|
||||
"get": {
|
||||
"responses": {
|
||||
"200": {
|
||||
"description": "Success",
|
||||
"content": {
|
||||
"application/json": {
|
||||
"schema": {
|
||||
"$ref": "#/components/schemas/foo bar"
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
components: {
|
||||
schemas: {
|
||||
"foo bar": {
|
||||
"type": "string"
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return validateHelper(spec)
|
||||
.then(system => {
|
||||
const allSemanticErrors = system.errSelectors.allErrors().toJS()
|
||||
.filter(err => err.source !== "resolver")
|
||||
expect(allSemanticErrors.length).toEqual(3)
|
||||
expect(allSemanticErrors[0]).toInclude({
|
||||
level: "warning",
|
||||
message: "Definition was declared but never used in document",
|
||||
path: ["components", "schemas", "foo bar"]
|
||||
})
|
||||
expect(allSemanticErrors[1]).toInclude({
|
||||
level: "error",
|
||||
message: "$ref values must be RFC3986-compliant percent-encoded URIs",
|
||||
path: ["paths", "/foo", "get", "responses", "200", "content", "application/json", "schema", "$ref"]
|
||||
}),
|
||||
expect(allSemanticErrors[2]).toInclude({
|
||||
level: "error",
|
||||
message: "Component names can only contain the characters A-Z a-z 0-9 - . _",
|
||||
path: ["components", "schemas", "foo bar"]
|
||||
})
|
||||
})
|
||||
})
|
||||
it("should return no errors when a JSON pointer uses correct percent-encoding in Swagger 2", () => {
|
||||
const spec = {
|
||||
"swagger": "2.0",
|
||||
"paths": {
|
||||
"/foo": {
|
||||
"get": {
|
||||
"responses": {
|
||||
"200": {
|
||||
"description": "Success",
|
||||
"schema": {
|
||||
"$ref": "#/definitions/foo%20bar"
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"definitions": {
|
||||
"foo bar": {
|
||||
"type": "string"
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return validateHelper(spec)
|
||||
.then(system => {
|
||||
const allSemanticErrors = system.errSelectors.allErrors().toJS()
|
||||
.filter(err => err.source !== "resolver")
|
||||
expect(allSemanticErrors).toEqual([])
|
||||
})
|
||||
})
|
||||
it("should return no errors when a JSON pointer uses correct percent-encoding in OpenAPI 3", () => {
|
||||
const spec = {
|
||||
"openapi": "3.0.0",
|
||||
"paths": {
|
||||
"/foo": {
|
||||
"get": {
|
||||
"responses": {
|
||||
"200": {
|
||||
"description": "Success",
|
||||
"content": {
|
||||
"application/json": {
|
||||
"schema": {
|
||||
"$ref": "#/components/schemas/foo%20bar"
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
components: {
|
||||
schemas: {
|
||||
"foo bar": {
|
||||
"type": "string"
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return validateHelper(spec)
|
||||
.then(system => {
|
||||
const allSemanticErrors = system.errSelectors.allErrors().toJS()
|
||||
.filter(err => err.source !== "resolver")
|
||||
expect(allSemanticErrors.length).toEqual(1)
|
||||
expect(allSemanticErrors[0]).toInclude({
|
||||
level: "error",
|
||||
message: "Component names can only contain the characters A-Z a-z 0-9 - . _",
|
||||
path: ["components", "schemas", "foo bar"]
|
||||
})
|
||||
})
|
||||
})
|
||||
|
||||
})
|
||||
describe("Nonexistent $ref pointers", () => {
|
||||
it("should return an error when a local JSON pointer does not exist in Swagger 2", () => {
|
||||
const spec = {
|
||||
swagger: "2.0",
|
||||
paths: {
|
||||
"/CoolPath": {
|
||||
$ref: "#/myObj/DoesNotExist"
|
||||
}
|
||||
},
|
||||
myObj: {
|
||||
abc: {
|
||||
type: "string",
|
||||
properties: {
|
||||
$ref: "http://google.com/MyRegularURLReference"
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return validateHelper(spec)
|
||||
.then(system => {
|
||||
const allErrors = system.errSelectors.allErrors().toJS()
|
||||
.filter(err => err.source !== "resolver")
|
||||
expect(allErrors.length).toEqual(1)
|
||||
const firstError = allErrors[0]
|
||||
expect(firstError.message).toMatch("$refs must reference a valid location in the document")
|
||||
expect(firstError.level).toEqual("error")
|
||||
expect(firstError.path).toEqual(["paths", "/CoolPath", "$ref"])
|
||||
})
|
||||
})
|
||||
it("should return an error when a local JSON pointer does not exist in OpenAPI 3", () => {
|
||||
const spec = {
|
||||
openapi: "3.0.0",
|
||||
paths: {
|
||||
"/CoolPath": {
|
||||
$ref: "#/myObj/DoesNotExist"
|
||||
}
|
||||
},
|
||||
myObj: {
|
||||
abc: {
|
||||
type: "string",
|
||||
properties: {
|
||||
$ref: "http://google.com/MyRegularURLReference"
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return validateHelper(spec)
|
||||
.then(system => {
|
||||
const allErrors = system.errSelectors.allErrors().toJS()
|
||||
.filter(err => err.source !== "resolver")
|
||||
.filter((el, i, arr) => arr.indexOf(el) === i)
|
||||
expect(allErrors.length).toEqual(1)
|
||||
const firstError = allErrors[0]
|
||||
expect(firstError.message).toMatch("$refs must reference a valid location in the document")
|
||||
expect(firstError.level).toEqual("error")
|
||||
expect(firstError.path).toEqual(["paths", "/CoolPath", "$ref"])
|
||||
})
|
||||
})
|
||||
it("should return no errors when a JSON pointer exists in Swagger 2", () => {
|
||||
const spec = {
|
||||
swagger: "2.0",
|
||||
paths: {
|
||||
"/CoolPath": {
|
||||
$ref: "#/myObj/abc"
|
||||
},
|
||||
},
|
||||
myObj: {
|
||||
abc: {
|
||||
type: "string"
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return validateHelper(spec)
|
||||
.then(system => {
|
||||
const allSemanticErrors = system.errSelectors.allErrors().toJS()
|
||||
.filter(err => err.source !== "resolver")
|
||||
expect(allSemanticErrors).toEqual([])
|
||||
})
|
||||
})
|
||||
it("should return no errors when a JSON pointer exists in OpenAPI 3", () => {
|
||||
const spec = {
|
||||
openapi: "3.0.0",
|
||||
paths: {
|
||||
"/CoolPath": {
|
||||
$ref: "#/myObj/abc"
|
||||
},
|
||||
},
|
||||
myObj: {
|
||||
abc: {
|
||||
type: "string",
|
||||
properties: {
|
||||
$ref: "http://google.com/MyRegularURLReference"
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return validateHelper(spec)
|
||||
.then(system => {
|
||||
const allSemanticErrors = system.errSelectors.allErrors().toJS()
|
||||
.filter(err => err.source !== "resolver")
|
||||
expect(allSemanticErrors).toEqual([])
|
||||
})
|
||||
})
|
||||
it("should return no errors when a JSON pointer is a remote reference in Swagger 2", () => {
|
||||
const spec = {
|
||||
swagger: "2.0",
|
||||
paths: {
|
||||
"/CoolPath": {
|
||||
$ref: "http://google.com#/myObj/abc"
|
||||
},
|
||||
},
|
||||
myObj: {
|
||||
abc: {
|
||||
type: "string"
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return validateHelper(spec)
|
||||
.then(system => {
|
||||
const allSemanticErrors = system.errSelectors.allErrors().toJS()
|
||||
.filter(err => err.source !== "resolver")
|
||||
expect(allSemanticErrors).toEqual([])
|
||||
})
|
||||
})
|
||||
it("should return no errors when a JSON pointer is a remote reference in OpenAPI 3", () => {
|
||||
const spec = {
|
||||
openapi: "3.0.0",
|
||||
paths: {
|
||||
"/CoolPath": {
|
||||
$ref: "http://google.com#/myObj/abc"
|
||||
},
|
||||
},
|
||||
myObj: {
|
||||
abc: {
|
||||
type: "string"
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return validateHelper(spec)
|
||||
.then(system => {
|
||||
const allSemanticErrors = system.errSelectors.allErrors().toJS()
|
||||
.filter(err => err.source !== "resolver")
|
||||
expect(allSemanticErrors).toEqual([])
|
||||
})
|
||||
})
|
||||
})
|
||||
})
|
||||
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,217 @@
|
||||
import expect from "expect"
|
||||
import validateHelper, { expectNoErrorsOrWarnings } from "../validate-helper.js"
|
||||
|
||||
describe("validation plugin - semantic - 2and3 security", () => {
|
||||
it("should return an error when top-level security references a non-existing security scheme", () => {
|
||||
const spec = {
|
||||
swagger: "2.0",
|
||||
security: [
|
||||
{
|
||||
fictional_security_definition: [
|
||||
"write:pets"
|
||||
]
|
||||
}
|
||||
]
|
||||
}
|
||||
|
||||
return validateHelper(spec)
|
||||
.then(system => {
|
||||
const allErrors = system.errSelectors.allErrors().toJS()
|
||||
expect(allErrors.length).toEqual(1)
|
||||
const firstError = allErrors[0]
|
||||
expect(firstError.path).toEqual(["security", "0"])
|
||||
expect(firstError.message).toMatch("Security requirements must match a security definition")
|
||||
})
|
||||
})
|
||||
|
||||
it("should return an error when an operation references a non-existing security scheme", () => {
|
||||
const spec = {
|
||||
swagger: "2.0",
|
||||
paths: {
|
||||
"/": {
|
||||
get: {
|
||||
security: [
|
||||
{
|
||||
fictional_security_definition: [
|
||||
"write:pets"
|
||||
]
|
||||
}
|
||||
]
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return validateHelper(spec)
|
||||
.then(system => {
|
||||
const allErrors = system.errSelectors.allErrors().toJS()
|
||||
expect(allErrors.length).toEqual(1)
|
||||
const firstError = allErrors[0]
|
||||
expect(firstError.path).toEqual(["paths", "/", "get", "security", "0"])
|
||||
expect(firstError.message).toMatch("Security requirements must match a security definition")
|
||||
})
|
||||
})
|
||||
|
||||
it("should return a warning when a security scheme is defined but not used in OpenAPI 2.0", () => {
|
||||
const spec = {
|
||||
swagger: "2.0",
|
||||
securityDefinitions: {
|
||||
auth: {
|
||||
type: "basic"
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return validateHelper(spec)
|
||||
.then(system => {
|
||||
const allErrors = system.errSelectors.allErrors().toJS()
|
||||
const firstError = allErrors[0]
|
||||
expect(allErrors.length).toEqual(1)
|
||||
expect(firstError.level).toEqual("warning")
|
||||
expect(firstError.message).toMatch("Security scheme was defined but never used.")
|
||||
expect(firstError.path).toEqual(["securityDefinitions", "auth"])
|
||||
})
|
||||
})
|
||||
|
||||
it("should return a warning when a security scheme is defined but not used in OpenAPI 3.0", () => {
|
||||
const spec = {
|
||||
openapi: "3.0.0",
|
||||
components: {
|
||||
securitySchemes: {
|
||||
auth: {
|
||||
type: "http"
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return validateHelper(spec)
|
||||
.then(system => {
|
||||
const allErrors = system.errSelectors.allErrors().toJS()
|
||||
const firstError = allErrors[0]
|
||||
expect(allErrors.length).toEqual(1)
|
||||
expect(firstError.level).toEqual("warning")
|
||||
expect(firstError.message).toMatch("Security scheme was defined but never used.")
|
||||
expect(firstError.path).toEqual(["components", "securitySchemes", "auth"])
|
||||
})
|
||||
})
|
||||
|
||||
it("should return no errors when a security scheme is defined and referenced globally in OpenAPI 2.0", () => {
|
||||
const spec = {
|
||||
swagger: "2.0",
|
||||
security: [
|
||||
{ auth: [] }
|
||||
],
|
||||
securityDefinitions: {
|
||||
auth: {
|
||||
type: "basic"
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return expectNoErrorsOrWarnings(spec)
|
||||
})
|
||||
|
||||
it("should return no errors when a security scheme is defined and used in an operation in OpenAPI 2.0", () => {
|
||||
const spec = {
|
||||
swagger: "2.0",
|
||||
paths: {
|
||||
"/": {
|
||||
get: {
|
||||
security: [
|
||||
{ auth: [] }
|
||||
]
|
||||
}
|
||||
}
|
||||
},
|
||||
securityDefinitions: {
|
||||
auth: {
|
||||
type: "basic"
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return expectNoErrorsOrWarnings(spec)
|
||||
})
|
||||
|
||||
it("should return no errors when a security scheme is defined and referenced globally in OpenAPI 3.0", () => {
|
||||
const spec = {
|
||||
openapi: "3.0.0",
|
||||
security: [
|
||||
{ auth: [] }
|
||||
],
|
||||
components: {
|
||||
securitySchemes: {
|
||||
auth: {
|
||||
type: "http"
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return expectNoErrorsOrWarnings(spec)
|
||||
})
|
||||
|
||||
it("should return no errors when a security scheme is defined and used in an operation in OpenAPI 3.0", () => {
|
||||
const spec = {
|
||||
openapi: "3.0.0",
|
||||
paths: {
|
||||
"/": {
|
||||
get: {
|
||||
security: [
|
||||
{ auth: [] }
|
||||
]
|
||||
}
|
||||
}
|
||||
},
|
||||
components: {
|
||||
securitySchemes: {
|
||||
auth: {
|
||||
type: "http"
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return expectNoErrorsOrWarnings(spec)
|
||||
})
|
||||
|
||||
it("should return no errrors when `security` contains multiple requirements combined using logical OR", () => {
|
||||
const spec = {
|
||||
swagger: "2.0",
|
||||
security: [
|
||||
{},
|
||||
{ auth: [] }
|
||||
],
|
||||
securityDefinitions: {
|
||||
auth: {
|
||||
type: "basic"
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return expectNoErrorsOrWarnings(spec)
|
||||
})
|
||||
|
||||
it("should return no errors when security schemes are combined using logical AND", () => {
|
||||
const spec = {
|
||||
swagger: "2.0",
|
||||
security: [
|
||||
{
|
||||
auth1: [],
|
||||
auth2: []
|
||||
}
|
||||
],
|
||||
securityDefinitions: {
|
||||
auth1: {
|
||||
type: "apiKey"
|
||||
},
|
||||
auth2: {
|
||||
type: "apiKey"
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return expectNoErrorsOrWarnings(spec)
|
||||
})
|
||||
})
|
||||
@@ -0,0 +1,132 @@
|
||||
/**
|
||||
* @prettier
|
||||
*/
|
||||
|
||||
import expect from "expect"
|
||||
|
||||
import validateHelper, { expectNoErrors } from "../validate-helper.js"
|
||||
|
||||
describe("validation plugin - semantic - 2and3 tags", () => {
|
||||
describe("global `tags` array", () => {
|
||||
describe("OpenAPI 3.0", () => {
|
||||
it("should return an error when two tag objects are equivalent", () => {
|
||||
const spec = {
|
||||
openapi: "3.0.0",
|
||||
tags: [
|
||||
{
|
||||
name: "pet",
|
||||
},
|
||||
{
|
||||
name: "pet",
|
||||
},
|
||||
],
|
||||
}
|
||||
|
||||
return validateHelper(spec).then(system => {
|
||||
const allErrors = system.errSelectors.allErrors().toJS()
|
||||
const firstError = allErrors[0]
|
||||
expect(allErrors.length).toEqual(1)
|
||||
expect(firstError.message).toEqual("Tag Objects must have unique `name` field values.")
|
||||
expect(firstError.path).toEqual(["tags", "1"])
|
||||
})
|
||||
})
|
||||
it("should return an error when two tag objects have the same name", () => {
|
||||
const spec = {
|
||||
openapi: "3.0.0",
|
||||
tags: [
|
||||
{
|
||||
name: "pet",
|
||||
},
|
||||
{
|
||||
name: "pet",
|
||||
description: "Everything about your pets",
|
||||
},
|
||||
],
|
||||
}
|
||||
|
||||
return validateHelper(spec).then(system => {
|
||||
const allErrors = system.errSelectors.allErrors().toJS()
|
||||
const firstError = allErrors[0]
|
||||
expect(allErrors.length).toEqual(1)
|
||||
expect(firstError.message).toEqual("Tag Objects must have unique `name` field values.")
|
||||
expect(firstError.path).toEqual(["tags", "1"])
|
||||
})
|
||||
})
|
||||
it("should not return an error when two tags have unique names", () => {
|
||||
const spec = {
|
||||
openapi: "3.0.0",
|
||||
tags: [
|
||||
{
|
||||
name: "pet",
|
||||
},
|
||||
{
|
||||
name: "store",
|
||||
},
|
||||
],
|
||||
}
|
||||
|
||||
return expectNoErrors(spec)
|
||||
})
|
||||
})
|
||||
describe("Swagger 2.0", () => {
|
||||
it("should return an error when two tag objects are equivalent", () => {
|
||||
const spec = {
|
||||
swagger: "2.0",
|
||||
tags: [
|
||||
{
|
||||
name: "pet",
|
||||
},
|
||||
{
|
||||
name: "pet",
|
||||
},
|
||||
],
|
||||
}
|
||||
|
||||
return validateHelper(spec).then(system => {
|
||||
const allErrors = system.errSelectors.allErrors().toJS()
|
||||
const firstError = allErrors[0]
|
||||
expect(allErrors.length).toEqual(1)
|
||||
expect(firstError.message).toEqual("Tag Objects must have unique `name` field values.")
|
||||
expect(firstError.path).toEqual(["tags", "1"])
|
||||
})
|
||||
})
|
||||
it("should return an error when two tag objects have the same name", () => {
|
||||
const spec = {
|
||||
swagger: "2.0",
|
||||
tags: [
|
||||
{
|
||||
name: "pet",
|
||||
},
|
||||
{
|
||||
name: "pet",
|
||||
description: "Everything about your pets",
|
||||
},
|
||||
],
|
||||
}
|
||||
|
||||
return validateHelper(spec).then(system => {
|
||||
const allErrors = system.errSelectors.allErrors().toJS()
|
||||
const firstError = allErrors[0]
|
||||
expect(allErrors.length).toEqual(1)
|
||||
expect(firstError.message).toEqual("Tag Objects must have unique `name` field values.")
|
||||
expect(firstError.path).toEqual(["tags", "1"])
|
||||
})
|
||||
})
|
||||
it("should not return an error when two tags have unique names", () => {
|
||||
const spec = {
|
||||
swagger: "2.0",
|
||||
tags: [
|
||||
{
|
||||
name: "pet",
|
||||
},
|
||||
{
|
||||
name: "store",
|
||||
},
|
||||
],
|
||||
}
|
||||
|
||||
return expectNoErrors(spec)
|
||||
})
|
||||
})
|
||||
})
|
||||
})
|
||||
Reference in New Issue
Block a user