Ekapp/swagger/test/unit/plugins/validate-semantic/oas3/refs.js

706 lines
19 KiB
JavaScript

import expect from "expect"
import validateHelper, { expectNoErrorsOrWarnings } from "../validate-helper.js"
describe("validation plugin - semantic - oas3 refs", () => {
describe("$refs for request bodies must reference a request body by position", () => {
it("should return an error when a requestBody incorrectly references a local component schema", () => {
const spec = {
openapi: "3.0.0",
paths: {
"/": {
post: {
operationId: "myId",
requestBody: {
$ref: "#/components/schemas/MySchema"
}
}
}
},
components: {
schemas: {
MySchema: {
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(`requestBody $refs cannot point to '#/components/schemas/…', they must point to '#/components/requestBodies/…'`)
expect(firstError.path).toEqual(["paths", "/", "post", "requestBody", "$ref"])
})
})
it("should not return an error when a requestBody references a remote component schema", () => {
const spec = {
openapi: "3.0.0",
paths: {
"/": {
post: {
operationId: "myId",
requestBody: {
$ref: "http://google.com/#/components/schemas/MySchema"
}
}
}
}
}
return expectNoErrorsOrWarnings(spec)
})
it("should return an error when a requestBody in a callback incorrectly references a local component schema", () => {
const spec = {
openapi: "3.0.0",
info: null,
version: "1.0.0-oas3",
title: "example",
paths: {
"/api/callbacks": {
post: {
responses: {
"200": {
description: "OK"
}
},
callbacks: {
callback: {
"/callback": {
post: {
requestBody: {
$ref: "#/components/schemas/callbackRequest"
},
responses: {
"200": {
description: "OK"
}
}
}
}
}
}
}
}
},
components: {
schemas: {
callbackRequest: {
type: "object",
properties: {
property1: {
type: "integer",
example: 10000
}
}
}
}
}
}
return validateHelper(spec)
.then(system => {
const allErrors = system.errSelectors.allErrors().toJS()
const firstError = allErrors[0]
expect(allErrors.length).toEqual(1)
expect(firstError.message).toEqual(`requestBody $refs cannot point to '#/components/schemas/…', they must point to '#/components/requestBodies/…'`)
expect(firstError.path).toEqual(["paths", "/api/callbacks", "post", "callbacks",
"callback", "/callback", "post", "requestBody", "$ref"])
})
})
it("should return no errors when a requestBody correctly references a local component request body", () => {
const spec = {
openapi: "3.0.0",
paths: {
"/": {
post: {
operationId: "myId",
requestBody: {
$ref: "#/components/requestBodies/MyBody"
}
}
}
},
components: {
requestBodies: {
MyBody: {
content: {
"application/json": {
schema: {
type: "string"
}
}
}
}
}
}
}
return expectNoErrorsOrWarnings(spec)
})
it("should return no errors when a requestBody correctly references a local operation request body", () => {
const spec = {
openapi: "3.0.0",
paths: {
"/": {
post: {
operationId: "myId",
requestBody: {
$ref: "#/paths/~1/put/requestBody"
}
},
put: {
requestBody: {
content: {
"application/json": {
schema: {
type: "string"
}
}
}
}
}
}
}
}
return expectNoErrorsOrWarnings(spec)
})
it("should return no errors when a requestBody correctly references a remote component request body", () => {
const spec = {
openapi: "3.0.0",
paths: {
"/": {
post: {
operationId: "myId",
requestBody: {
$ref: "http://google.com/#/components/requestBodies/MyBody"
}
}
}
},
components: {
requestBodies: {
MyBody: {
content: {
"application/json": {
schema: {
type: "string"
}
}
}
}
}
}
}
return expectNoErrorsOrWarnings(spec)
})
it("should return no errors when a requestBody correctly references a remote https component request body", () => {
const spec = {
openapi: "3.0.0",
paths: {
"/": {
post: {
operationId: "myId",
requestBody: {
$ref: "https://example.com/file.yaml#/components/requestBodies/group1/addPetBody"
}
}
}
},
components: {
requestBodies: {
MyBody: {
content: {
"application/json": {
schema: {
type: "string"
}
}
}
}
}
}
}
return expectNoErrorsOrWarnings(spec)
})
it("should return no errors when a requestBody correctly references an external yaml file", () => {
const spec = {
openapi: "3.0.0",
paths: {
"/": {
post: {
operationId: "myId",
requestBody: {
$ref: "addPetBody.yaml"
}
}
}
},
components: {
requestBodies: {
MyBody: {
content: {
"application/json": {
schema: {
type: "string"
}
}
}
}
}
}
}
return expectNoErrorsOrWarnings(spec)
})
it("should return no errors when a requestBody correctly references an external yaml pointing some node", () => {
const spec = {
openapi: "3.0.0",
paths: {
"/": {
post: {
operationId: "myId",
requestBody: {
$ref: "./components.yaml#/path/to/some/node"
}
}
}
},
components: {
requestBodies: {
MyBody: {
content: {
"application/json": {
schema: {
type: "string"
}
}
}
}
}
}
}
return expectNoErrorsOrWarnings(spec)
})
})
describe("$refs for requestbody schemas must reference a schema by position", () => {
it("should return an error when a requestBody schema incorrectly references a local component requestBody", () => {
const spec = {
openapi: "3.0.0",
paths: {
"/foo": {
post: {
requestBody: {
content: {
"application/json": {
schema: {
$ref: "#/components/requestBodies/Foo"
}
}
}
}
}
}
},
components: {
requestBodies: {
Foo: {
type: "string"
}
}
}
}
return validateHelper(spec)
.then(system => {
const allErrors = system.errSelectors.allErrors().toJS()
const allSemanticErrors = allErrors.filter(err => err.source === "semantic")
expect(allSemanticErrors.length).toEqual(1)
const firstError = allSemanticErrors[0]
expect(firstError.message).toEqual(`requestBody schema $refs must point to a position where a Schema Object can be legally placed`)
expect(firstError.path).toEqual(["paths", "/foo", "post", "requestBody", "content", "application/json", "schema", "$ref"])
})
})
it("should not return an error when a requestBody schema references a local component schema", () => {
const spec = {
openapi: "3.0.0",
paths: {
"/foo": {
post: {
requestBody: {
content: {
"application/json": {
schema: {
$ref: "#/components/schemas/Foo"
}
}
}
}
}
}
},
components: {
schemas: {
Foo: {
type: "string"
}
}
}
}
return validateHelper(spec)
.then(system => {
const allErrors = system.errSelectors.allErrors().toJS()
expect(allErrors.length).toEqual(0)
})
})
it("should not return an error when a requestBody schema references remote document paths", () => {
const spec = {
openapi: "3.0.0",
paths: {
"/foo": {
post: {
requestBody: {
content: {
"application/json": {
schema: {
$ref: "http://google.com#/Foo"
}
}
}
}
}
}
}
}
return validateHelper(spec)
.then(system => {
const allErrors = system.errSelectors.allErrors().toJS()
expect(allErrors.length).toEqual(0)
})
})
it("should not return an error when a requestBody schema references entire remote documents", () => {
const spec = {
openapi: "3.0.0",
paths: {
"/foo": {
post: {
requestBody: {
content: {
"application/json": {
schema: {
$ref: "addPetBody.yaml"
}
}
}
}
}
}
}
}
return validateHelper(spec)
.then(system => {
const allErrors = system.errSelectors.allErrors().toJS()
expect(allErrors.length).toEqual(0)
})
})
it("should not return an error when a requestBody schema references local operation requestBody schemas", () => {
const spec = {
openapi: "3.0.0",
paths: {
"/foo": {
post: {
responses: {
"200": {
description: "OK"
}
},
requestBody: {
content: {
"application/json": {
schema: {
type: "string"
}
}
}
}
},
put: {
requestBody: {
responses: {
"200": {
description: "OK"
}
},
content: {
"application/json": {
schema: {
$ref: "#/paths/~1foo/post/requestBody/content/application~1json/schema"
}
}
}
}
}
}
}
}
return validateHelper(spec)
.then(system => {
const allErrors = system.errSelectors.allErrors().toJS()
expect(allErrors.length).toEqual(0)
})
})
})
describe("response header $refs should not point to parameters", () => {
it("should return an error when a response header incorrectly references a local parameter component", () => {
const spec = {
openapi: "3.0.0",
paths: {
"/foo": {
get: {
responses: {
"200": {
description: "OK",
headers: {
"X-MyHeader": {
$ref: "#/components/parameters/MyHeader"
}
}
}
}
}
}
},
components: {
headers: {
MyHeader: {
$ref: "#/components/parameters/MyHeader"
}
},
parameters: {
MyHeader: {}
}
}
}
return validateHelper(spec)
.then(system => {
const allErrors = system.errSelectors.allErrors().toJS()
const firstError = allErrors[0]
expect(allErrors.length).toEqual(1)
expect(firstError.message).toEqual(`OAS3 header $refs should point to #/components/headers/... and not #/components/parameters/...`)
expect(firstError.path).toEqual(["paths", "/foo", "get","responses","200", "headers", "X-MyHeader", "$ref"])
})
})
it("should return no errors when a response header correctly references a local header component", () => {
const spec = {
openapi: "3.0.0",
paths: {
"/foo": {
get: {
responses: {
"200": {
description: "OK",
headers: {
"X-MyHeader": {
$ref: "#/components/headers/MyHeader"
}
}
}
}
}
}
},
components: {
headers: {
MyHeader: {
$ref: "#/components/headers/MyHeader"
}
}
}
}
return expectNoErrorsOrWarnings(spec)
})
it("should return no errors for external $refs in response headers", () => {
const spec = {
openapi: "3.0.0",
paths: {
"/foo": {
get: {
responses: {
"200": {
description: "OK",
headers: {
"X-MyHeader": {
$ref: "https://www.google.com/#/components/parameter/MyHeader"
}
}
}
}
}
}
},
components: {
headers: {
MyHeader: {
$ref: "#/components/headers/MyHeader"
}
}
}
}
return expectNoErrorsOrWarnings(spec)
})
})
describe("parameter $refs should not point to header components", () => {
it("should return an error when a parameter incorrectly references a response header component", () => {
const spec = {
openapi: "3.0.0",
paths: {
"/foo": {
parameters: [
{
$ref: "#/components/headers/foo"
}
],
get: {
parameters: [
{
$ref: "#/components/headers/foo"
}
],
responses: {
"200": {
description: "OK"
}
}
}
}
},
components: {
parameters: {
myParam: {
$ref: "#/components/headers/foo"
}
},
headers: {
foo: {}
}
}
}
return validateHelper(spec)
.then(system => {
const allErrors = system.errSelectors.allErrors().toJS()
expect(allErrors.length).toEqual(3)
const firstError = allErrors[0]
expect(firstError.message).toEqual(`OAS3 parameter $refs should point to #/components/parameters/... and not #/components/headers/...`)
expect(firstError.path).toEqual(["paths","/foo","parameters", "0", "$ref"])
const secondError = allErrors[1]
expect(secondError.message).toEqual(`OAS3 parameter $refs should point to #/components/parameters/... and not #/components/headers/...`)
expect(secondError.path).toEqual(["paths","/foo","get","parameters", "0", "$ref"])
const thirdError = allErrors[2]
expect(thirdError.message).toEqual(`OAS3 parameter $refs should point to #/components/parameters/... and not #/components/headers/...`)
expect(thirdError.path).toEqual(["components","parameters", "myParam", "$ref"])
})
})
it("should return no errors when a parameter correctly references a parameter component", () => {
const spec = {
openapi: "3.0.0",
paths: {
"/foo": {
parameters: [
{
$ref: "#/components/parameters/foo"
}
],
get: {
parameters: [
{
$ref: "#/components/parameters/foo"
}
],
responses: {
"200": {
description: "OK"
}
}
}
}
},
components: {
parameters: {
foo: {
$ref: "#/components/parameters/foo"
}
}
}
}
return expectNoErrorsOrWarnings(spec)
})
it("should return no errors for external parameter $refs", () => {
const spec = {
openapi: "3.0.0",
paths: {
"/foo": {
parameters: [
{
$ref: "http://www.google.com/#/components/parameters/foo"
}
],
get: {
parameters: [
{
$ref: "http://www.google.com/#/components/parameters/foo"
}
],
responses: {
"200": {
description: "OK"
}
}
}
}
},
components: {
parameters: {
foo: {
$ref: "http://www.google.com/#/components/parameters/foo"
}
}
}
}
return expectNoErrorsOrWarnings(spec)
})
})
})