feat: OpenAPI 3.1 support (#8367)
- New top-level field - `webhooks`. This allows describing out-of-band webhooks that are available as part of the API. - New top-level field - `jsonSchemaDialect`. This allows defining of a default `$schema` value for Schema Objects - The Info Object has a new `summary` field. - The License Object now has a new `identifier` field for SPDX licenses. This `identifier` field is mutually exclusive with the `url` field. Either can be used in OpenAPI 3.1 definitions. - Components Object now has a new entry `pathItems`, to allow for reusable Path Item Objects to be defined within a valid OpenAPI document. - `License` and `Contact` components are now exported and available via `getComponent` - New version predicates and selectors for `isOpenAPI30` and `isOpenAPI31`. This avoids needing to change the usage of `isOAS3` selector. - New OAS3 components: `Webhooks` - New OAS3 wrapped components: `Info`, `License`
This commit is contained in:
@@ -0,0 +1,6 @@
|
||||
swagger: 2.0.0
|
||||
info:
|
||||
title: OpenAPI 2.0 Info Object
|
||||
version: 1.0.0
|
||||
summary: This 3.1.x field should not render in OpenAPI2.x.x
|
||||
description: This is a sample server for a pet store.
|
||||
@@ -0,0 +1,6 @@
|
||||
openapi: 3.1.0
|
||||
info:
|
||||
title: OpenAPI 3.0 Info Object
|
||||
version: 1.0.0
|
||||
summary: This 3.1.x field should not render in OpenAPI3.0.x
|
||||
description: This is a sample server for a pet store.
|
||||
@@ -0,0 +1,7 @@
|
||||
openapi: 3.1.0
|
||||
info:
|
||||
title: OpenAPI 3.1 Info Object
|
||||
version: 1.0.0
|
||||
summary: a new 3.1.x specific field for summary
|
||||
description: This is a sample server for a pet store.
|
||||
|
||||
@@ -0,0 +1,8 @@
|
||||
swagger: 2.0.0
|
||||
info:
|
||||
title: OpenAPI 2.0 License with only url present
|
||||
version: 1.0.0
|
||||
description: This is a sample server for a pet store.
|
||||
license:
|
||||
name: Apache 2.0
|
||||
url: https://www.apache.org/licenses/LICENSE-2.0.html
|
||||
@@ -0,0 +1,8 @@
|
||||
openapi: 3.0.0
|
||||
info:
|
||||
title: OpenAPI 3.0 License with only url present
|
||||
version: 1.0.0
|
||||
description: This is a sample server for a pet store.
|
||||
license:
|
||||
name: Apache 2.0
|
||||
url: https://www.apache.org/licenses/LICENSE-2.0.html
|
||||
@@ -0,0 +1,9 @@
|
||||
openapi: 3.1.0
|
||||
info:
|
||||
title: OpenAPI 3.1 License with only identifier present
|
||||
version: 1.0.0
|
||||
description: This is a sample server for a pet store.
|
||||
license:
|
||||
name: Apache 2.0
|
||||
url: https://www.apache.org/licenses/LICENSE-2.0.html
|
||||
identifier: Apache-2.0 # mutually exclusive of url; separately, for json_schema, consider const, prefix, array items can be of a different type (current assumption is all array items are the same)
|
||||
@@ -0,0 +1,9 @@
|
||||
openapi: 3.1.0
|
||||
info:
|
||||
title: OpenAPI 3.1 License with only identifier present
|
||||
version: 1.0.0
|
||||
description: This is a sample server for a pet store.
|
||||
license:
|
||||
name: Apache 2.0
|
||||
# url: https://www.apache.org/licenses/LICENSE-2.0.html
|
||||
identifier: Apache-2.0 # mutually exclusive of url; separately, for json_schema, consider const, prefix, array items can be of a different type (current assumption is all array items are the same)
|
||||
@@ -0,0 +1,9 @@
|
||||
openapi: 3.1.0
|
||||
info:
|
||||
title: OpenAPI 3.1 License with only url present
|
||||
version: 1.0.0
|
||||
description: This is a sample server for a pet store.
|
||||
license:
|
||||
name: Apache 2.0
|
||||
url: https://www.apache.org/licenses/LICENSE-2.0.html
|
||||
# identifier: Apache-2.0 # mutually exclusive of url; separately, for json_schema, consider const, prefix, array items can be of a different type (current assumption is all array items are the same)
|
||||
@@ -0,0 +1,24 @@
|
||||
openapi: 3.0.0
|
||||
info:
|
||||
title: Webhooks does not exist in OpenAPI 3.0 and should not render
|
||||
version: 1.0.0
|
||||
summary: a new 3.1.x specific field for summary
|
||||
description: This is a sample server for a pet store.
|
||||
termsOfService: https://example.com/terms/
|
||||
webhooks:
|
||||
newPet:
|
||||
post:
|
||||
summary: summary for newPet--post
|
||||
requestBody:
|
||||
description: Information about a new pet in the system
|
||||
content:
|
||||
application/json:
|
||||
schema:
|
||||
$ref: "#/components/schemas/foo"
|
||||
responses:
|
||||
"200":
|
||||
description: Return a 200 status to indicate that the data was received successfully
|
||||
components:
|
||||
schemas:
|
||||
foo:
|
||||
type: string
|
||||
@@ -0,0 +1,50 @@
|
||||
openapi: 3.1.0
|
||||
info:
|
||||
title: OpenAPI 3.1 Webhooks
|
||||
version: 1.0.0
|
||||
summary: a new 3.1.x specific field for summary
|
||||
description: This is a sample server for a pet store.
|
||||
termsOfService: https://example.com/terms/
|
||||
license:
|
||||
name: Apache 2.0
|
||||
identifier: Apache-2.0
|
||||
webhooks:
|
||||
newPet:
|
||||
post:
|
||||
summary: summary for newPet--post
|
||||
requestBody:
|
||||
description: Information about a new pet in the system
|
||||
content:
|
||||
application/json:
|
||||
schema:
|
||||
$ref: "#/components/schemas/foo"
|
||||
responses:
|
||||
"200":
|
||||
description: Return a 200 status to indicate that the data was received successfully
|
||||
put:
|
||||
summary: summary for newPet--put
|
||||
requestBody:
|
||||
description: Information about a new pet in the system
|
||||
content:
|
||||
application/json:
|
||||
schema:
|
||||
$ref: "#/components/schemas/foo"
|
||||
responses:
|
||||
"200":
|
||||
description: Return a 200 status to indicate that the data was received successfully
|
||||
oldPet:
|
||||
post:
|
||||
summary: summary for oldPet--post
|
||||
requestBody:
|
||||
description: Information about a new pet in the system
|
||||
content:
|
||||
application/json:
|
||||
schema:
|
||||
$ref: "#/components/schemas/foo"
|
||||
responses:
|
||||
"200":
|
||||
description: Return a 200 status to indicate that the data was received successfully
|
||||
components:
|
||||
schemas:
|
||||
foo:
|
||||
type: string
|
||||
74
test/e2e-cypress/tests/features/info.js
Normal file
74
test/e2e-cypress/tests/features/info.js
Normal file
@@ -0,0 +1,74 @@
|
||||
describe("Render Info Component", () => {
|
||||
describe("OpenAPI 2.x", () => {
|
||||
const baseUrl = "/?url=/documents/features/info-openAPI2.yaml"
|
||||
it("should render Info Description", () => {
|
||||
cy.visit(baseUrl)
|
||||
.get(".info .description")
|
||||
.should("contains.text", "This is a sample")
|
||||
})
|
||||
it("should render Info Main anchor target xss link with safe `rel` attributes", () => {
|
||||
cy.visit(baseUrl)
|
||||
.get(".info .main > a")
|
||||
.should("have.attr", "rel")
|
||||
.and("include", "noopener")
|
||||
.and("include", "noreferrer")
|
||||
.get(".info .main > a")
|
||||
.should("have.attr", "target")
|
||||
.and("equal", "_blank")
|
||||
})
|
||||
it("should not render Info Summary (an OpenAPI 3.1 field)", () => {
|
||||
cy.visit(baseUrl)
|
||||
.get(".info__summary")
|
||||
.should("not.exist")
|
||||
})
|
||||
})
|
||||
describe("OpenAPI 3.0.x", () => {
|
||||
const baseUrl = "/?url=/documents/features/info-openAPI30.yaml"
|
||||
it("should render Info Description", () => {
|
||||
cy.visit(baseUrl)
|
||||
.get(".info .description")
|
||||
.should("contains.text", "This is a sample")
|
||||
})
|
||||
it("should render Info Main anchor target xss link with safe `rel` attributes", () => {
|
||||
cy.visit(baseUrl)
|
||||
.get(".info .main > a")
|
||||
.should("have.attr", "rel")
|
||||
.and("include", "noopener")
|
||||
.and("include", "noreferrer")
|
||||
.get(".info .main > a")
|
||||
.should("have.attr", "target")
|
||||
.and("equal", "_blank")
|
||||
})
|
||||
it("should not render Info Summary (an OpenAPI 3.1 field)", () => {
|
||||
cy.visit(baseUrl)
|
||||
.get(".info__summary")
|
||||
.should("not.exist")
|
||||
})
|
||||
})
|
||||
describe("OpenAPI 3.1.x", () => {
|
||||
const baseUrl = "/?url=/documents/features/info-openAPI31.yaml"
|
||||
it("should render Info Description", () => {
|
||||
cy.visit(baseUrl)
|
||||
.get(".info .description")
|
||||
.should("contains.text", "This is a sample")
|
||||
})
|
||||
it("should render Info Main anchor target xss link with safe `rel` attributes", () => {
|
||||
cy.visit(baseUrl)
|
||||
.get(".info .main > a")
|
||||
.should("have.attr", "rel")
|
||||
.and("include", "noopener")
|
||||
.and("include", "noreferrer")
|
||||
.get(".info .main > a")
|
||||
.should("have.attr", "target")
|
||||
.and("equal", "_blank")
|
||||
})
|
||||
it("should render Info Summary", () => {
|
||||
cy.visit(baseUrl)
|
||||
.get(".info__summary")
|
||||
.should("exist")
|
||||
.should("contains.text", "new 3.1.x specific field")
|
||||
.get(".info .description")
|
||||
.should("contains.text", "This is a sample")
|
||||
})
|
||||
})
|
||||
})
|
||||
105
test/e2e-cypress/tests/features/license.js
Normal file
105
test/e2e-cypress/tests/features/license.js
Normal file
@@ -0,0 +1,105 @@
|
||||
describe("Render License Component", () => {
|
||||
describe("OpenAPI 2", () =>{
|
||||
const baseUrl = "/?url=/documents/features/license-openAPI2.yaml"
|
||||
it("should render License URL", () => {
|
||||
cy.visit(baseUrl)
|
||||
.get(".info__license")
|
||||
.should("exist")
|
||||
.should("contains.text", "Apache 2.0")
|
||||
.should("not.contains.text", "SPDX License")
|
||||
.get(".info__license__identifier")
|
||||
.should("not.exist")
|
||||
})
|
||||
it("should render License URL anchor target xss link with safe `rel` attributes ", () => {
|
||||
cy.visit(baseUrl)
|
||||
.get(".info__license > .link")
|
||||
.should("have.attr", "rel")
|
||||
.and("include", "noopener")
|
||||
.and("include", "noreferrer")
|
||||
.get(".info .main > a")
|
||||
.should("have.attr", "target")
|
||||
.and("equal", "_blank")
|
||||
})
|
||||
})
|
||||
describe("OpenAPI 3.0.x", () => {
|
||||
const baseUrl = "/?url=/documents/features/license-openAPI30.yaml"
|
||||
it("should render License URL", () => {
|
||||
cy.visit(baseUrl)
|
||||
.get(".info__license__url")
|
||||
.should("exist")
|
||||
.should("contains.text", "Apache 2.0")
|
||||
.should("not.contains.text", "SPDX License")
|
||||
.get(".info__license__identifier")
|
||||
.should("not.exist")
|
||||
})
|
||||
it("should render URL anchor target xss link with safe `rel` attributes ", () => {
|
||||
cy.visit(baseUrl)
|
||||
.get(".info__license__url > a")
|
||||
.should("have.attr", "rel")
|
||||
.and("include", "noopener")
|
||||
.and("include", "noreferrer")
|
||||
.get(".info .main > a")
|
||||
.should("have.attr", "target")
|
||||
.and("equal", "_blank")
|
||||
})
|
||||
})
|
||||
describe("OpenAPI 3.1.x", () => {
|
||||
describe("only URL", () => {
|
||||
const baseUrl = "/?url=/documents/features/license-openAPI31-url.yaml"
|
||||
it("should render URL", () => {
|
||||
cy.visit(baseUrl)
|
||||
.get(".info__license__url")
|
||||
.should("exist")
|
||||
.should("contains.text", "Apache 2.0")
|
||||
.should("not.contains.text", "SPDX License")
|
||||
.get(".info__license__identifier")
|
||||
.should("not.exist")
|
||||
})
|
||||
it("should render URL anchor target xss link with safe `rel` attributes ", () => {
|
||||
cy.visit(baseUrl)
|
||||
.get(".info__license__url > a")
|
||||
.should("have.attr", "rel")
|
||||
.and("include", "noopener")
|
||||
.and("include", "noreferrer")
|
||||
.get(".info .main > a")
|
||||
.should("have.attr", "target")
|
||||
.and("equal", "_blank")
|
||||
})
|
||||
})
|
||||
describe("only SPDX Identifier", () => {
|
||||
const baseUrl = "/?url=/documents/features/license-openAPI31-identifier.yaml"
|
||||
it("should render SPDX Identifier", () => {
|
||||
cy.visit(baseUrl)
|
||||
.get(".info__license__identifier")
|
||||
.should("exist")
|
||||
.should("contains.text", "Apache-2.0")
|
||||
.should("contains.text", "SPDX License")
|
||||
.get(".info__license__url")
|
||||
.should("not.exist")
|
||||
})
|
||||
it("should render SPDX and Identifier anchor target xss links with safe `rel` attributes ", () => {
|
||||
cy.visit(baseUrl)
|
||||
.get(".info__license__identifier > a")
|
||||
.each(($el) => {
|
||||
cy.get($el)
|
||||
.should("have.attr", "rel")
|
||||
.and("include", "noopener")
|
||||
.and("include", "noreferrer")
|
||||
cy.get($el)
|
||||
.should("have.attr", "target")
|
||||
.and("equal", "_blank")
|
||||
})
|
||||
})
|
||||
})
|
||||
describe("URL and SPX are mutually exclusive", () => {
|
||||
it("should render nothing if both URL & SPDX exists", () => {
|
||||
const baseUrl = "/?url=/documents/features/license-openAPI31-error-both-identifier-and-url.yaml"
|
||||
cy.visit(baseUrl)
|
||||
.get(".info__license__identifier")
|
||||
.should("not.exist")
|
||||
.get(".info__license__url")
|
||||
.should("not.exist")
|
||||
})
|
||||
})
|
||||
})
|
||||
})
|
||||
@@ -101,7 +101,7 @@ describe("JSON Schema Form: Enum & Boolean in a Parameter", () => {
|
||||
.should("not.have.class", "invalid")
|
||||
.should("not.contains.text", "expectIsOptional")
|
||||
// cURL component
|
||||
cy.get(".responses-wrapper .curl-command")
|
||||
cy.get(".responses-wrapper .curl-command") // hangs browser here
|
||||
.should("exist")
|
||||
.get(".responses-wrapper .curl-command span")
|
||||
.should("contains.text", "expectIsOptional=false")
|
||||
@@ -120,7 +120,7 @@ describe("JSON Schema Form: Enum & Boolean in a Parameter", () => {
|
||||
.should("not.have.class", "invalid")
|
||||
.should("not.contains.text", "expectIsOptional")
|
||||
// cURL component
|
||||
cy.get(".responses-wrapper .curl-command")
|
||||
cy.get(".responses-wrapper .curl-command") // hangs browser here
|
||||
.should("exist")
|
||||
.get(".responses-wrapper .curl-command span")
|
||||
.should("not.contains.text", "expectIsOptional")
|
||||
|
||||
26
test/e2e-cypress/tests/features/webhooks.js
Normal file
26
test/e2e-cypress/tests/features/webhooks.js
Normal file
@@ -0,0 +1,26 @@
|
||||
describe("Render Webhooks Component", () => {
|
||||
describe("OpenAPI 3.1.x", () => {
|
||||
const baseUrl = "/?url=/documents/features/webhooks-openAPI31.yaml"
|
||||
it("should render a heading", () => {
|
||||
cy.visit(baseUrl)
|
||||
.get(".webhooks")
|
||||
.should("exist")
|
||||
.should("contains.text", "Webhooks")
|
||||
})
|
||||
it("should render an operation component", () => {
|
||||
cy.visit(baseUrl)
|
||||
.get(".webhooks #operations--postnewPet > .opblock-summary")
|
||||
.should("exist")
|
||||
.should("contains.text", "POST")
|
||||
.should("contains.text", "newPet")
|
||||
})
|
||||
})
|
||||
describe("OpenAPI 3.0.x", () => {
|
||||
const baseUrl = "/?url=/documents/features/webhooks-openAPI31.yaml"
|
||||
it("should render nothing", () => {
|
||||
cy.visit(baseUrl)
|
||||
.get(".webhooks")
|
||||
.should("not.exist")
|
||||
})
|
||||
})
|
||||
})
|
||||
Reference in New Issue
Block a user