This commit is contained in:
2024-05-24 15:27:07 +03:00
parent 17df2ce6a9
commit fc1da2c238
643 changed files with 110185 additions and 231 deletions

View File

@ -0,0 +1,51 @@
describe("OAuth2 Bearer flow", () => {
beforeEach(() => {
const staticResponse = {
statusCode: 200,
body: {
name: "not a random secret for test",
}
}
cy.intercept("GET", "/get*", staticResponse).as(
"tokenRequest"
)
})
it("should be focused on input field with aria-label", () => {
cy.visit(
"/?url=/documents/features/auth-bearer-flow.yaml"
)
.get("button.authorize")
.click()
cy.focused()
.should("have.attr", "aria-label").and("eq", "auth-bearer-value")
})
it("should make a header request with proper sample cURL header", () => {
cy.visit(
"/?url=/documents/features/auth-bearer-flow.yaml"
)
.get("button.authorize")
.click()
.get("section > input")
.type("secret_token")
.get(".auth-btn-wrapper > .authorize")
.click()
.get("button.close-modal")
.click()
// Try-it-out
.get("#operations-default-get_get")
.click()
.get(".btn.try-out__btn")
.click()
.get(".btn.execute")
.click()
cy.wait("@tokenRequest")
.its("request")
.its("headers")
.its("authorization")
.should("equal", "Bearer secret_token")
.get(".curl")
.contains("Authorization: Bearer secret_token")
.should("be.visible")
})
})

View File

@ -0,0 +1,47 @@
describe("Check client_secret for OAuth2 Authorization Code flow with and without PKCE (#6290)", () => {
it("should display client_secret field for authorization code flow with PKCE", () => {
cy.visit(
"/?url=/documents/features/auth-code-flow-pkce-without-secret.yaml"
)
.window()
.then(win => {
// set auth config to use PKCE
let authConfigs = win.ui.authSelectors.getConfigs()
win.ui.authActions.configureAuth({
...authConfigs,
usePkceWithAuthorizationCodeGrant: true,
})
})
.get("button.authorize")
.click()
.get("h4")
.contains("authorizationCode with PKCE")
.get(".flow")
.contains("authorizationCode with PKCE")
.get("#client_secret")
.should("exist")
})
it("should display client_secret field for authorization code flow without PKCE", () => {
cy.visit(
"/?url=/documents/features/auth-code-flow-pkce-without-secret.yaml"
)
.window()
.then(win => {
// set auth config to not use PKCE
let authConfigs = win.ui.authSelectors.getConfigs()
win.ui.authActions.configureAuth({
...authConfigs,
usePkceWithAuthorizationCodeGrant: false,
})
})
.get("button.authorize")
.click()
.get("h4")
.contains("authorizationCode")
.get(".flow")
.contains("authorizationCode")
.get("#client_secret")
.should("exist")
})
})

View File

@ -0,0 +1,292 @@
describe("Deep linking feature", () => {
describe("in Swagger 2", () => {
const swagger2BaseUrl = "/?deepLinking=true&url=/documents/features/deep-linking.swagger.yaml"
describe("regular Operation", () => {
OperationDeeplinkTestFactory({
baseUrl: swagger2BaseUrl,
elementToGet: ".opblock-get",
correctElementId: "operations-myTag-myOperation",
correctFragment: "#/myTag/myOperation",
correctHref: "#/myTag/myOperation"
})
})
describe("Operation with whitespace in tag+id", () => {
const elementToGet = ".opblock-post"
const correctFragment = "#/my%20Tag/my%20Operation"
OperationDeeplinkTestFactory({
baseUrl: swagger2BaseUrl,
elementToGet,
correctElementId: "operations-my_Tag-my_Operation",
correctFragment,
correctHref: "#/my%20Tag/my%20Operation"
})
const legacyFragment = "#/my_Tag/my_Operation"
it("should expand the operation when reloaded and provided the legacy fragment", () => {
cy.visit(`${swagger2BaseUrl}${legacyFragment}`)
.reload()
.get(`${elementToGet}.is-open`)
.should("exist")
})
it.skip("should rewrite to the correct fragment when provided the legacy fragment", () => {
cy.visit(`${swagger2BaseUrl}${legacyFragment}`)
.reload()
.window()
.should("have.deep.property", "location.hash", correctFragment)
})
})
describe("Operation with underscores in tag+id", () => {
OperationDeeplinkTestFactory({
baseUrl: swagger2BaseUrl,
elementToGet: ".opblock-patch",
correctElementId: "operations-underscore_Tag-underscore_Operation",
correctFragment: "#/underscore_Tag/underscore_Operation",
correctHref: "#/underscore_Tag/underscore_Operation"
})
})
describe("Operation with UTF-16 characters", () => {
OperationDeeplinkTestFactory({
baseUrl: swagger2BaseUrl,
elementToGet: ".opblock-head",
correctElementId: "operations-шеллы-пошел",
correctFragment: "#/%D1%88%D0%B5%D0%BB%D0%BB%D1%8B/%D0%BF%D0%BE%D1%88%D0%B5%D0%BB",
correctHref: "#/шеллы/пошел"
})
})
describe("Operation with no operationId", () => {
OperationDeeplinkTestFactory({
baseUrl: swagger2BaseUrl,
elementToGet: ".opblock-put",
correctElementId: "operations-tagTwo-put_noOperationId",
correctFragment: "#/tagTwo/put_noOperationId",
correctHref: "#/tagTwo/put_noOperationId"
})
})
describe("regular Tag", () => {
TagDeeplinkTestFactory({
isTagCase: true,
baseUrl: swagger2BaseUrl,
elementToGet: `.opblock-tag[data-tag="myTag"][data-is-open="true"]`,
correctElementId: "operations-tag-myTag",
correctFragment: "#/myTag",
correctHref: "#/myTag"
})
})
describe("Tag with whitespace", () => {
TagDeeplinkTestFactory({
isTagCase: true,
baseUrl: swagger2BaseUrl,
elementToGet: `.opblock-tag[data-tag="my Tag"][data-is-open="true"]`,
correctElementId: "operations-tag-my_Tag",
correctFragment: "#/my%20Tag",
correctHref: "#/my%20Tag"
})
})
})
describe("in OpenAPI 3", () => {
const openAPI3BaseUrl = "/?deepLinking=true&url=/documents/features/deep-linking.openapi.yaml"
describe("regular Operation", () => {
OperationDeeplinkTestFactory({
baseUrl: openAPI3BaseUrl,
elementToGet: ".opblock-get",
correctElementId: "operations-myTag-myOperation",
correctFragment: "#/myTag/myOperation",
correctHref: "#/myTag/myOperation"
})
})
describe("Operation with whitespace in tag+id", () => {
const elementToGet = ".opblock-post"
const correctFragment = "#/my%20Tag/my%20Operation"
OperationDeeplinkTestFactory({
baseUrl: openAPI3BaseUrl,
elementToGet: ".opblock-post",
correctElementId: "operations-my_Tag-my_Operation",
correctFragment,
correctHref: "#/my%20Tag/my%20Operation"
})
const legacyFragment = "#/my_Tag/my_Operation"
it("should expand the operation when reloaded and provided the legacy fragment", () => {
cy.visit(`${openAPI3BaseUrl}${legacyFragment}`)
.reload()
.get(`${elementToGet}.is-open`)
.should("exist")
})
it.skip("should rewrite to the correct fragment when provided the legacy fragment", () => {
cy.visit(`${openAPI3BaseUrl}${legacyFragment}`)
.reload()
.window()
.should("have.deep.property", "location.hash", correctFragment)
})
})
describe("Operation with underscores in tag+id", () => {
OperationDeeplinkTestFactory({
baseUrl: openAPI3BaseUrl,
elementToGet: ".opblock-patch",
correctElementId: "operations-underscore_Tag-underscore_Operation",
correctFragment: "#/underscore_Tag/underscore_Operation",
correctHref: "#/underscore_Tag/underscore_Operation"
})
})
describe("Operation with UTF-16 characters", () => {
OperationDeeplinkTestFactory({
baseUrl: openAPI3BaseUrl,
elementToGet: ".opblock-head",
correctElementId: "operations-шеллы-пошел",
correctFragment: "#/%D1%88%D0%B5%D0%BB%D0%BB%D1%8B/%D0%BF%D0%BE%D1%88%D0%B5%D0%BB",
correctHref: "#/шеллы/пошел"
})
})
describe("Operation with no operationId", () => {
OperationDeeplinkTestFactory({
baseUrl: openAPI3BaseUrl,
elementToGet: ".opblock-put",
correctElementId: "operations-tagTwo-put_noOperationId",
correctFragment: "#/tagTwo/put_noOperationId",
correctHref: "#/tagTwo/put_noOperationId"
})
})
describe("regular Tag", () => {
TagDeeplinkTestFactory({
isTagCase: true,
baseUrl: openAPI3BaseUrl,
elementToGet: `.opblock-tag[data-tag="myTag"][data-is-open="true"]`,
correctElementId: "operations-tag-myTag",
correctFragment: "#/myTag",
correctHref: "#/myTag"
})
})
describe("Tag with whitespace", () => {
TagDeeplinkTestFactory({
isTagCase: true,
baseUrl: openAPI3BaseUrl,
elementToGet: `.opblock-tag[data-tag="my Tag"][data-is-open="true"]`,
correctElementId: "operations-tag-my_Tag",
correctFragment: "#/my%20Tag",
correctHref: "#/my%20Tag"
})
})
})
})
function OperationDeeplinkTestFactory({ baseUrl, elementToGet, correctElementId, correctFragment, correctHref }) {
it("should generate a correct element ID", () => {
cy.visit(baseUrl)
.get(elementToGet)
.should("have.id", correctElementId)
})
it("should add the correct element fragment to the URL when expanded", () => {
cy.visit(baseUrl)
.get(elementToGet)
.click()
cy.location().should((loc) => {
expect(loc.hash).to.eq(correctFragment)
})
})
it("should provide an anchor link that has the correct fragment as href", () => {
cy.visit(baseUrl)
.get(elementToGet)
.find("a")
.should("have.attr", "href", correctHref)
.click()
cy.location().should((loc) => {
expect(loc.hash).to.eq(correctFragment)
})
})
it("should expand the operation when reloaded", () => {
cy.visit(`${baseUrl}${correctFragment}`)
.get(`${elementToGet}.is-open`)
.should("exist")
})
it("should retain the correct fragment when reloaded", () => {
cy.visit(`${baseUrl}${correctFragment}`)
.reload()
.should("exist")
cy.location().should((loc) => {
expect(loc.hash).to.eq(correctFragment)
})
})
it("should expand a tag with docExpansion disabled", () => {
cy.visit(`${baseUrl}&docExpansion=none${correctFragment}`)
.get(`.opblock-tag-section.is-open`)
.should("have.length", 1)
})
it("should expand an operation with docExpansion disabled", () => {
cy.visit(`${baseUrl}&docExpansion=none${correctFragment}`)
.get(`.opblock.is-open`)
.should("have.length", 1)
})
}
function TagDeeplinkTestFactory({ baseUrl, elementToGet, correctElementId, correctFragment, correctHref, isTagCase = false }) {
it("should generate a correct element ID", () => {
cy.visit(baseUrl)
.get(elementToGet)
.should("have.id", correctElementId)
})
it("should add the correct element fragment to the URL when expanded", () => {
cy.visit(baseUrl)
.get(elementToGet)
.click()
.click() // tags need two clicks because they're expanded by default
cy.location().should((loc) => {
expect(loc.hash).to.eq(correctFragment)
})
})
it("should provide an anchor link that has the correct fragment as href", () => {
cy.visit(baseUrl)
.get(elementToGet)
.find("a")
.should("have.attr", "href", correctHref)
})
it("should expand the tag when reloaded", () => {
cy.visit(`${baseUrl}${correctFragment}`)
.get(`${elementToGet}[data-is-open="true"]`)
.should("exist")
})
it("should retain the correct fragment when reloaded", () => {
cy.visit(`${baseUrl}${correctFragment}`)
.reload()
.should("exist")
cy.location().should((loc) => {
expect(loc.hash).to.eq(correctFragment)
})
})
it("should expand a tag with docExpansion disabled", () => {
cy.visit(`${baseUrl}&docExpansion=none${correctFragment}`)
.get(`.opblock-tag-section.is-open`)
.should("have.length", 1)
})
}

View File

@ -0,0 +1,26 @@
describe("dynamic default oauth2RedirectUrl", () => {
it("should compute an oauth2RedirectUrl based on the browser's location at runtime", () => {
cy.visit("/")
.window()
.then(win => win.ui.getConfigs())
.should("include", { oauth2RedirectUrl: "http://localhost:3230/oauth2-redirect.html" })
})
it("should compute an oauth2RedirectUrl based on the browser's location at runtime, including the path", () => {
cy.visit("/pages/5085/")
.window()
.then(win => win.ui.getConfigs())
.should("include", { oauth2RedirectUrl: "http://localhost:3230/pages/5085/oauth2-redirect.html" })
})
it("should compute an oauth2RedirectUrl based on the browser's location at runtime, including the path, without confusing the file name for a folder name", () => {
cy.visit("/pages/5085/index.html")
.window()
.then(win => win.ui.getConfigs())
.should("include", { oauth2RedirectUrl: "http://localhost:3230/pages/5085/oauth2-redirect.html" })
})
it("should compute an oauth2RedirectUrl based on the browser's location at runtime, including the path, even it does not end with a slash", () => {
cy.visit("/pages/5085")
.window()
.then(win => win.ui.getConfigs())
.should("include", { oauth2RedirectUrl: "http://localhost:3230/pages/5085/oauth2-redirect.html" })
})
})

View File

@ -0,0 +1,108 @@
describe("External docs feature", () => {
describe("in Swagger 2", () => {
ExternalDocsTest("/?url=/documents/features/external-docs.swagger.yaml")
})
describe("in OpenAPI 3", () => {
ExternalDocsTest("/?url=/documents/features/external-docs.openapi.yaml")
})
})
function ExternalDocsTest(baseUrl) {
describe("for Root", () => {
it("should display link to external docs with description", () => {
cy.visit(baseUrl)
.get(".info__extdocs")
.should("exist")
.and("contain.text", "Read external docs")
.and("have.attr", "href", "http://swagger.io")
})
it("should display link to external docs without description", () => {
cy
.intercept({
path: /^\/documents\/features\/external-docs\.(swagger|openapi)\.yaml\?intercept$/
}, (req) => {
delete req.headers["if-none-match"]
delete req.headers["if-modified-since"]
req.continue((res) => {
res.send({body: res.body.replace(" description: Read external docs\n", "")})
})
})
.visit(`${baseUrl}?intercept`)
.get(".info__extdocs")
.should("exist")
.and("contain.text", "http://swagger.io")
.and("have.attr", "href", "http://swagger.io")
})
})
describe("for Tags", () => {
it("should display link to external docs with description", () => {
cy.visit(baseUrl)
.get(`.opblock-tag[data-tag="pet"] .info__externaldocs`)
.should("exist")
.find("a")
.should("contain.text", "Pet Documentation")
.and("have.attr", "href", "http://swagger.io")
})
it("should display link to external docs without description", () => {
cy.visit(baseUrl)
.get(`.opblock-tag[data-tag="petWithoutDescription"] .info__externaldocs`)
.should("exist")
.find("a")
.should("contain.text", "http://swagger.io")
.and("have.attr", "href", "http://swagger.io")
})
})
describe("for Schemas", () => {
function SchemaTestFactory(type) {
return () => {
it("should display link with description", () => {
cy.visit(baseUrl)
.get(`.models #model-${type} button`)
.click()
.get(`.models #model-${type} .external-docs a`)
.should("contain.text", `${type} Docs`)
.and("have.attr", "href", "http://swagger.io")
})
it("should display link without description", () => {
cy.visit(baseUrl)
.get(`.models #model-${type}WithoutDescription button`)
.click()
.get(`.models #model-${type}WithoutDescription .external-docs a`)
.should("contain.text", "http://swagger.io")
.and("have.attr", "href", "http://swagger.io")
})
}
}
describe("Primitive Schema", SchemaTestFactory("Primitive"))
describe("Array Schema", SchemaTestFactory("Array"))
describe("Object Schema", SchemaTestFactory("Object"))
})
describe("for Operation", () => {
it("should display link to external docs with description", () => {
cy.visit(baseUrl)
.get("#operations-pet-updatePet button")
.click()
.get("#operations-pet-updatePet .opblock-external-docs-wrapper .opblock-external-docs__description")
.should("contain.text", "More details about putting a pet")
.get("#operations-pet-updatePet .opblock-external-docs-wrapper .opblock-external-docs__link")
.should("have.attr", "href", "http://swagger.io")
})
it("should display link to external docs without description", () => {
cy.visit(baseUrl)
.get("#operations-pet-addPet button")
.click()
.get("#operations-pet-addPet .opblock-external-docs-wrapper .opblock-external-docs__description")
.should("not.exist")
.get("#operations-pet-addPet .opblock-external-docs-wrapper .opblock-external-docs__link")
.should("have.attr", "href", "http://swagger.io")
})
})
}

View File

@ -0,0 +1,50 @@
describe("Model collapse/expand feature", () => {
describe("in Swagger 2", () => {
const swagger2BaseUrl = "/?deepLinking=true&url=/documents/features/models.swagger.yaml"
const urlFragment = "#/definitions/Pet"
ModelCollapseTest(swagger2BaseUrl, urlFragment)
})
describe("in OpenAPI 3", () => {
const openAPI3BaseUrl = "/?deepLinking=true&url=/documents/features/models.openapi.yaml"
ModelCollapseTest(openAPI3BaseUrl)
})
})
function ModelCollapseTest(baseUrl, urlFragment) {
it("Models section should be expanded on load", () => {
cy.visit(baseUrl)
.get(".models")
.should("have.class", "is-open")
.get("#model-Pet")
.should("exist")
})
it("Models section should collapse and expand when toggled", () => {
cy.visit(baseUrl)
.get(".models h4 .models-control")
.click()
.get(".models")
.should("not.have.class", "is-open")
.get("#model-Order")
.should("not.exist")
.get(".models h4 .models-control")
.click()
.get(".models")
.should("have.class", "is-open")
.get("#model-Order")
.should("exist")
})
it("Model should collapse and expand when toggled clicking button", () => {
cy.visit(baseUrl)
.get("#model-User .model-box .model-box-control")
.click()
.get("#model-User .model-box .model .inner-object")
.should("exist")
.get("#model-User .model-box .model-box-control")
.first()
.click()
.get("#model-User .model-box .model .inner-object")
.should("not.exist")
})
}

View File

@ -0,0 +1,662 @@
/**
* @prettier
*/
const {
ParameterPrimitiveTestCases,
RequestBodyPrimitiveTestCases,
ResponsePrimitiveTestCases,
} = require("../../helpers/multiple-examples")
describe("OpenAPI 3.0 Multiple Examples - core features", () => {
describe("/String", () => {
describe("in a parameter", () => {
ParameterPrimitiveTestCases({
operationDomId: "#operations-default-post_String",
parameterName: "message",
exampleA: {
key: "StringExampleA",
value: "hello world",
},
exampleB: {
key: "StringExampleB",
value: "The quick brown fox jumps over the lazy dog",
},
customUserInput: "OpenAPIs.org <3",
})
})
describe("in a Request Body", () => {
RequestBodyPrimitiveTestCases({
operationDomId: "#operations-default-post_String",
exampleA: {
key: "StringExampleA",
value: "hello world",
serializedValue: "hello world",
summary: "Don't just string me along...",
},
exampleB: {
key: "StringExampleB",
value: "The quick brown fox jumps over the lazy dog",
serializedValue: "The quick brown fox jumps over the lazy dog",
summary: "I'm a pangram!",
},
customUserInput: "OpenAPIs.org <3",
})
})
describe("in a Response", () => {
ResponsePrimitiveTestCases({
operationDomId: "#operations-default-post_String",
exampleA: {
key: "StringExampleA",
value: "hello world",
summary: "Don't just string me along...",
},
exampleB: {
key: "StringExampleB",
value: "The quick brown fox jumps over the lazy dog",
summary: "I'm a pangram!",
},
exampleC: {
key: "StringExampleC",
value: "JavaScript rules",
summary: "A third example, for use in special places...",
},
})
})
})
describe("/Number", () => {
describe("in a parameter", () => {
ParameterPrimitiveTestCases({
operationDomId: "#operations-default-post_Number",
parameterName: "message",
exampleA: {
key: "NumberExampleA",
value: "7710263025",
},
exampleB: {
key: "NumberExampleB",
value: "9007199254740991",
},
exampleC: {
key: "NumberExampleC",
value: "0",
},
customUserInput: "9001",
})
})
describe("in a Request Body", () => {
RequestBodyPrimitiveTestCases({
operationDomId: "#operations-default-post_Number",
exampleA: {
key: "NumberExampleA",
value: "7710263025",
summary: "World population",
},
exampleB: {
key: "NumberExampleB",
value: "9007199254740991",
summary: "Number.MAX_SAFE_INTEGER",
},
exampleC: {
key: "NumberExampleC",
value: "0",
},
customUserInput: "1337",
})
})
describe("in a Response", () => {
ResponsePrimitiveTestCases({
operationDomId: "#operations-default-post_Number",
exampleA: {
key: "NumberExampleA",
value: "7710263025",
summary: "World population",
},
exampleB: {
key: "NumberExampleB",
value: "9007199254740991",
summary: "Number.MAX_SAFE_INTEGER",
},
exampleC: {
key: "NumberExampleC",
value: "0",
},
})
})
})
describe("/Boolean", () => {
describe("in a parameter", () => {
it("should render and apply the first example and value by default", () => {
cy.visit(
"/?url=/documents/features/multiple-examples-core.openapi.yaml"
)
.get("#operations-default-post_Boolean")
.click()
// Assert on the initial dropdown value
.get("table.parameters .examples-select > select")
.find(":selected")
.should("have.text", "The truth will set you free")
// Assert on the initial JsonSchemaForm value
.get(".parameters-col_description > select")
.should("have.attr", "disabled")
.get(".parameters-col_description > select")
.find(":selected")
.should("have.text", "true")
// Execute
.get(".try-out__btn")
.click()
.get(".execute")
.click()
// Assert on the request URL
.get(".request-url")
.contains(`?message=true`)
})
it("should render and apply the second value when chosen", () => {
cy.visit(
"/?url=/documents/features/multiple-examples-core.openapi.yaml"
)
.get("#operations-default-post_Boolean")
.click()
// Set the dropdown value, then assert on it
.get("table.parameters .examples-select > select")
.select("BooleanExampleB")
.find(":selected")
.should("have.text", "Friends don't lie to friends")
// Set the JsonSchemaForm value, then assert on it
.get(".parameters-col_description > select")
.find(":selected")
.should("have.text", "false")
// Execute
.get(".try-out__btn")
.click()
.get(".execute")
.click()
// Assert on the request URL
.get(".request-url")
.contains(`?message=false`)
})
it("should track value changes against valid examples", () => {
cy.visit(
"/?url=/documents/features/multiple-examples-core.openapi.yaml"
)
.get("#operations-default-post_Boolean")
.click()
.get(".try-out__btn")
.click()
// Set the JsonSchemaForm value, then assert on it
.get(".parameters-col_description > select")
.select("false")
.find(":selected")
.should("have.text", "false")
// Assert on the dropdown value
.get("table.parameters .examples-select > select")
.find(":selected")
.should("have.text", "Friends don't lie to friends")
// Execute
.get(".execute")
.click()
// Assert on the request URL
.get(".request-url")
.contains(`?message=false`)
})
})
describe("in a Request Body", () => {
RequestBodyPrimitiveTestCases({
operationDomId: "#operations-default-post_Boolean",
exampleA: {
key: "BooleanExampleA",
value: "true",
summary: "The truth will set you free",
},
exampleB: {
key: "BooleanExampleB",
value: "false",
summary: "Friends don't lie to friends",
},
customUserInput: "tralse",
})
})
describe("in a Response", () => {
it("should render and apply the first example and value by default", () => {
cy.visit(
"/?url=/documents/features/multiple-examples-core.openapi.yaml"
)
.get("#operations-default-post_Boolean")
.click()
// Assert on the initial dropdown value
.get(".responses-wrapper .examples-select > select")
.find(":selected")
.should("have.text", "The truth will set you free")
// Assert on the example value
.get(".example.microlight")
.should("have.text", "true")
})
it("should render and apply the second value when chosen", () => {
cy.visit(
"/?url=/documents/features/multiple-examples-core.openapi.yaml"
)
.get("#operations-default-post_Boolean")
.click()
// Set the dropdown value, then assert on it
.get(".responses-wrapper .examples-select > select")
.select("BooleanExampleB")
.find(":selected")
.should("have.text", "Friends don't lie to friends")
// Assert on the example value
.get(".example.microlight")
.should("have.text", "false")
})
})
})
describe("/Array", () => {
describe("in a Parameter", () => {
it("should have the first example's array entries by default", () => {
cy.visit(
"/?url=/documents/features/multiple-examples-core.openapi.yaml"
)
.get("#operations-default-post_Array")
.click()
.get(".json-schema-form-item > input")
.then((inputs) => {
expect(inputs.map((i, el) => el.value).toArray()).to.deep.equal([
"a",
"b",
"c",
])
})
.get(".parameters-col_description .examples-select > select")
.find(":selected")
.should("have.text", "A lowly array of strings")
})
it("should switch to the second array's entries via dropdown", () => {
cy.visit(
"/?url=/documents/features/multiple-examples-core.openapi.yaml"
)
.get("#operations-default-post_Array")
.click()
.get(".parameters-col_description .examples-select > select")
.select("ArrayExampleB")
.get(".json-schema-form-item > input")
.then((inputs) => {
expect(inputs.map((i, el) => el.value).toArray()).to.deep.equal([
"1",
"2",
"3",
"4",
])
})
.get(".parameters-col_description .examples-select > select")
.find(":selected")
.should("have.text", "A lowly array of numbers")
})
it("should not allow modification of values in static mode", () => {
cy.visit(
"/?url=/documents/features/multiple-examples-core.openapi.yaml"
)
.get("#operations-default-post_Array")
.click()
.get(".parameters-col_description .examples-select > select")
.select("ArrayExampleB")
// Add a new item
.get(".json-schema-form-item > input")
.should("have.attr", "disabled")
})
it("should allow modification of values in Try-It-Out", () => {
cy.visit(
"/?url=/documents/features/multiple-examples-core.openapi.yaml"
)
.get("#operations-default-post_Array")
.click()
.get(".try-out__btn")
.click()
.get(".parameters-col_description .examples-select > select")
.select("ArrayExampleB")
// Add a new item
.get(".json-schema-form-item-add")
.click()
.get(".json-schema-form-item:last-of-type > input")
.type("{selectall}5")
// Assert against the input fields
.get(".json-schema-form-item > input")
.then((inputs) => {
expect(inputs.map((i, el) => el.value).toArray()).to.deep.equal([
"1",
"2",
"3",
"4",
"5",
])
})
.get(".parameters-col_description .examples-select > select")
.find(":selected")
.should("have.text", "[Modified value]")
})
it("should retain a modified value, and support returning to it", () => {
cy.visit(
"/?url=/documents/features/multiple-examples-core.openapi.yaml"
)
.get("#operations-default-post_Array")
.click()
.get(".try-out__btn")
.click()
.get(".parameters-col_description .examples-select > select")
.select("ArrayExampleB")
// Add a new item
.get(".json-schema-form-item-add")
.click()
.get(".json-schema-form-item:last-of-type > input")
.type("{selectall}5")
// Reset to an example
.get(".parameters-col_description .examples-select > select")
.select("ArrayExampleB")
// Assert against the input fields
.get(".json-schema-form-item > input")
.then((inputs) => {
expect(inputs.map((i, el) => el.value).toArray()).to.deep.equal([
"1",
"2",
"3",
"4",
])
})
.get(".parameters-col_description .examples-select > select")
.find(":selected")
.should("have.text", "A lowly array of numbers")
// Return to the modified value
.get(".parameters-col_description .examples-select > select")
.select("__MODIFIED__VALUE__")
// Assert that our modified value is back
.get(".json-schema-form-item > input")
.then((inputs) => {
expect(inputs.map((i, el) => el.value).toArray()).to.deep.equal([
"1",
"2",
"3",
"4",
"5",
])
})
.get(".parameters-col_description .examples-select > select")
.find(":selected")
.should("have.text", "[Modified value]")
})
})
describe("in a Request Body", () => {
it("should have the first example's array entries by default", () => {
cy.visit(
"/?url=/documents/features/multiple-examples-core.openapi.yaml"
)
.get("#operations-default-post_Array")
.click()
// Check HighlightCode value
.get(".opblock-section-request-body .highlight-code")
.should("include.text", JSON.stringify(["a", "b", "c"], null, 2))
// Check dropdown value
.get(".opblock-section-request-body .examples-select > select")
.find(":selected")
.should("have.text", "A lowly array of strings")
// Switch to Try-It-Out
.get(".try-out__btn")
.click()
// Check textarea value
.get(".opblock-section-request-body textarea")
.should("have.value", JSON.stringify(["a", "b", "c"], null, 2))
// Check dropdown value
.get(".opblock-section-request-body .examples-select > select")
.find(":selected")
.should("have.text", "A lowly array of strings")
})
it("should switch to the second array's entries via dropdown", () => {
cy.visit(
"/?url=/documents/features/multiple-examples-core.openapi.yaml"
)
.get("#operations-default-post_Array")
.click()
.get(".opblock-section-request-body .examples-select > select")
.select("ArrayExampleB")
.get(".opblock-section-request-body .highlight-code")
.should("include.text", JSON.stringify([1, 2, 3, 4], null, 2))
.get(".opblock-section-request-body .examples-select > select")
.find(":selected")
.should("have.text", "A lowly array of numbers")
// Switch to Try-It-Out
.get(".try-out__btn")
.click()
// Check textarea value
.get(".opblock-section-request-body textarea")
.should("include.text", JSON.stringify([1, 2, 3, 4], null, 2))
// Check dropdown value
.get(".opblock-section-request-body .examples-select > select")
.find(":selected")
.should("have.text", "A lowly array of numbers")
})
it("should allow modification of values", () => {
cy.visit(
"/?url=/documents/features/multiple-examples-core.openapi.yaml"
)
.get("#operations-default-post_Array")
.click()
// Switch to Try-It-Out
.get(".try-out__btn")
.click()
// Choose the second example
.get(".opblock-section-request-body .examples-select > select")
.select("ArrayExampleB")
// Change the value
.get(".opblock-section-request-body textarea")
.type(`{leftarrow}{leftarrow},{enter} 5`)
// Check that [Modified value] is displayed in dropdown
.get(".opblock-section-request-body .examples-select > select")
.find(":selected")
.should("have.text", "[Modified value]")
// Check textarea value
.get(".opblock-section-request-body textarea")
.should("include.text", JSON.stringify([1, 2, 3, 4, 5], null, 2))
})
it("should retain a modified value, and support returning to it", () => {
cy.visit(
"/?url=/documents/features/multiple-examples-core.openapi.yaml"
)
.get("#operations-default-post_Array")
.click()
// Switch to Try-It-Out
.get(".try-out__btn")
.click()
// Choose the second example as the example to start with
.get(".opblock-section-request-body .examples-select > select")
.select("ArrayExampleB")
// Change the value
.get(".opblock-section-request-body textarea")
.type(`{leftarrow}{leftarrow},{enter} 5`)
// Check that [Modified value] is displayed in dropdown
.get(".opblock-section-request-body .examples-select > select")
.find(":selected")
.should("have.text", "[Modified value]")
// Check textarea value
.get(".opblock-section-request-body textarea")
.should("include.text", JSON.stringify([1, 2, 3, 4, 5], null, 2))
// Choose the second example
.get(".opblock-section-request-body .examples-select > select")
.select("ArrayExampleB")
// Check that the example is displayed in dropdown
.get(".opblock-section-request-body .examples-select > select")
.find(":selected")
.should("have.text", "A lowly array of numbers")
// Check textarea value
.get(".opblock-section-request-body textarea")
.should("include.text", JSON.stringify([1, 2, 3, 4], null, 2))
// Switch back to the modified value
.get(".opblock-section-request-body .examples-select > select")
.select("__MODIFIED__VALUE__")
// Check textarea value
.get(".opblock-section-request-body textarea")
.should("include.text", JSON.stringify([1, 2, 3, 4, 5], null, 2))
})
})
describe("in a Response", () => {
it("should render and apply the first example and value by default", () => {
cy.visit(
"/?url=/documents/features/multiple-examples-core.openapi.yaml"
)
.get("#operations-default-post_Array")
.click()
// Assert on the initial dropdown value
.get(".responses-wrapper .examples-select > select")
.find(":selected")
.should("have.text", "A lowly array of strings")
// Assert on the example value
.get(".example.microlight")
.should("include.text", JSON.stringify(["a", "b", "c"], null, 2))
})
it("should render and apply the second value when chosen", () => {
cy.visit(
"/?url=/documents/features/multiple-examples-core.openapi.yaml"
)
.get("#operations-default-post_Array")
.click()
// Set the dropdown value, then assert on it
.get(".responses-wrapper .examples-select > select")
.select("ArrayExampleB")
.find(":selected")
.should("have.text", "A lowly array of numbers")
// Assert on the example value
.get(".example.microlight")
.should("include.text", JSON.stringify([1, 2, 3, 4], null, 2))
})
})
})
describe("/Object", () => {
describe("in a Parameter", () => {
ParameterPrimitiveTestCases({
operationDomId: "#operations-default-post_Object",
parameterName: "data",
customUserInput: `{{} "openapiIsCool": true }`,
customExpectedUrlSubstring: "?openapiIsCool=true",
exampleA: {
key: "ObjectExampleA",
serializedValue:
"firstName=Kyle&lastName=Shockey&email=kyle.shockey%40smartbear.com",
value: JSON.stringify(
{
firstName: "Kyle",
lastName: "Shockey",
email: "kyle.shockey@smartbear.com",
},
null,
2
),
},
exampleB: {
key: "ObjectExampleB",
serializedValue:
"name=Abbey&type=kitten&color=calico&gender=female&age=11%20weeks",
value: JSON.stringify(
{
name: "Abbey",
type: "kitten",
color: "calico",
gender: "female",
age: "11 weeks",
},
null,
2
),
},
})
})
describe("in a Request Body", () => {
const exampleA = JSON.stringify(
{
firstName: "Kyle",
lastName: "Shockey",
email: "kyle.shockey@smartbear.com",
},
null,
2
)
const exampleB = JSON.stringify(
{
name: "Abbey",
type: "kitten",
color: "calico",
gender: "female",
age: "11 weeks",
},
null,
2
)
RequestBodyPrimitiveTestCases({
operationDomId: "#operations-default-post_Object",
primaryMediaType: "application/json",
// ↓ not a typo, Cypress requires escaping { when using `cy.type`
customUserInput: `{{} "openapiIsCool": true }`,
customExpectedUrlSubstring: "?openapiIsCool=true",
customUserInputExpectedCurlSubstring: `{ "openapiIsCool": true }`,
exampleA: {
key: "ObjectExampleA",
serializedValue: exampleA,
value: exampleA,
summary: "A user's contact info",
},
exampleB: {
key: "ObjectExampleB",
serializedValue: exampleB,
value: exampleB,
summary: "A wonderful kitten's info",
},
})
it("should display an error message when input validation fails", () => {
cy.visit("/?url=/documents/features/multiple-examples-core.openapi.yaml")
// Expand the operation
.get("#operations-default-post_Object")
.click()
// Switch to Try-It-Out
.get(".try-out__btn")
.click()
// Set an invalid value
.get(".parameters-container > div > table > tbody > tr > td.parameters-col_description > div:nth-child(2) > textarea")
.type("{{{{ [[[[ <<<< invalid JSON here.")
// Execute the operation
.get(".execute")
.click()
// Verify that an error is shown
.get(".validation-errors")
.contains("Parameter string value must be valid JSON")
})
})
describe("in a Response", () => {
ResponsePrimitiveTestCases({
operationDomId: "#operations-default-post_Object",
exampleA: {
key: "ObjectExampleA",
value: JSON.stringify(
{
firstName: "Kyle",
lastName: "Shockey",
email: "kyle.shockey@smartbear.com",
},
null,
2
),
summary: "A user's contact info",
},
exampleB: {
key: "ObjectExampleB",
value: JSON.stringify(
{
name: "Abbey",
type: "kitten",
color: "calico",
gender: "female",
age: "11 weeks",
},
null,
2
),
summary: "A wonderful kitten's info",
},
})
})
})
})

View File

@ -0,0 +1,184 @@
// https://github.com/swagger-api/swagger-ui/issues/6201
// https://github.com/swagger-api/swagger-ui/issues/6250
// https://github.com/swagger-api/swagger-ui/issues/6476
describe("OpenAPI 3.0 Multiple Media Types with different schemas", () => {
const mediaTypeFormData = "multipart/form-data"
const mediaTypeUrlencoded = "application/x-www-form-urlencoded"
const mediaTypeJson = "application/json"
beforeEach(() => {
cy.intercept({
method: "POST",
url: "/post",
hostname: "httpbin.org",
}, {})
cy.visit(
"/?url=/documents/features/oas3-multiple-media-type.yaml"
)
.get("#operations-default-post_post")
.click()
// Expand Try It Out
.get(".try-out__btn")
.click()
// @alias Execute Button
cy.get(".execute.opblock-control__btn").as("executeBtn")
// @alias Media Type Dropdown
cy.get(".opblock-section-request-body .content-type").as("selectMediaType")
})
// In all cases,
// - assume that examples are populated based on schema (not explicitly tested)
// - assume validation passes based on successful "execute"
// - expect final cURL command result doees not contain unexpected artifacts from other content-type schemas
describe("multipart/form-data (only 'bar')", () => {
it("should execute multipart/form-data", () => {
cy.get("@selectMediaType")
.select(mediaTypeUrlencoded)
.get("@executeBtn")
.click()
.get("@selectMediaType")
.select(mediaTypeFormData)
.get("@executeBtn")
.click()
// cURL component
.get(".responses-wrapper .curl-command")
.should("exist")
.get(".responses-wrapper .curl-command span")
.should("contains.text", "bar")
.should("not.contains.text", "foo")
})
it("should execute application/x-www-form-urlencoded THEN execute multipart/form-data", () => {
cy.get("@selectMediaType")
.select(mediaTypeUrlencoded)
.get("@executeBtn")
.click()
.get("@selectMediaType")
.select(mediaTypeFormData)
.get("@executeBtn")
.click()
// cURL component
.get(".responses-wrapper .curl-command")
.should("exist")
.get(".responses-wrapper .curl-command span")
.should("contains.text", "bar")
.should("not.contains.text", "foo")
})
it("should execute application/json THEN execute multipart/form-data", () => {
cy.get("@selectMediaType")
.select(mediaTypeJson)
.get("@executeBtn")
.click()
.get("@selectMediaType")
.select(mediaTypeFormData)
.get("@executeBtn")
.click()
// cURL component
.get(".responses-wrapper .curl-command")
.should("exist")
.get(".responses-wrapper .curl-command span")
.should("contains.text", "bar")
.should("not.contains.text", "foo")
})
})
describe("application/x-www-form-urlencoded (only 'foo')", () => {
it("should execute application/x-www-form-urlencoded", () => {
cy.get("@selectMediaType")
.select(mediaTypeUrlencoded)
.get("@executeBtn")
.click()
// cURL component
.get(".responses-wrapper .curl-command")
.should("exist")
.get(".responses-wrapper .curl-command span")
.should("contains.text", "foo")
.should("not.contains.text", "bar")
})
it("should execute multipart/form-data THEN execute application/x-www-form-urlencoded", () => {
cy.get("@selectMediaType")
.select(mediaTypeFormData)
.get("@executeBtn")
.click()
.get("@selectMediaType")
.select(mediaTypeUrlencoded)
.get("@executeBtn")
.click()
// cURL component
.get(".responses-wrapper .curl-command")
.should("exist")
.get(".responses-wrapper .curl-command span")
.should("contains.text", "foo")
.should("not.contains.text", "bar")
})
it("should execute application/json THEN execute application/x-www-form-urlencoded", () => {
cy.get("@selectMediaType")
.select(mediaTypeJson)
.get("@executeBtn")
.click()
.get("@selectMediaType")
.select(mediaTypeUrlencoded)
.get("@executeBtn")
.click()
// cURL component
.get(".responses-wrapper .curl-command")
.should("exist")
.get(".responses-wrapper .curl-command span")
.should("contains.text", "foo")
.should("not.contains.text", "bar")
})
})
describe("application/json (both 'foo' and 'bar')", () => {
// note: form input for "application/json" is a string; not multiple form fields
it("should execute application/json", () => {
// final curl should have both "bar" and "foo"
cy.get("@selectMediaType")
.select(mediaTypeJson)
.get("@executeBtn")
.click()
.get("@executeBtn")
.click()
// cURL component
.get(".responses-wrapper .curl-command")
.should("exist")
.get(".responses-wrapper .curl-command span")
.should("contains.text", "foo")
.should("contains.text", "bar")
})
it("should execute multipart/form-data THEN execute application/json", () => {
cy.get("@selectMediaType")
.select(mediaTypeFormData)
.get("@executeBtn")
.click()
.get("@selectMediaType")
.select(mediaTypeJson)
.get("@executeBtn")
.click()
// cURL component
.get(".responses-wrapper .curl-command")
.should("exist")
.get(".responses-wrapper .curl-command span")
.should("contains.text", "foo")
.should("contains.text", "bar")
})
it("should execute application/x-www-form-urlencoded THEN execute application/json", () => {
// final curl should have both "bar" and "foo"
cy.get("@selectMediaType")
.select(mediaTypeUrlencoded)
.get("@executeBtn")
.click()
.get("@selectMediaType")
.select(mediaTypeJson)
.get("@executeBtn")
.click()
// cURL component
.get(".responses-wrapper .curl-command")
.should("exist")
.get(".responses-wrapper .curl-command span")
.should("contains.text", "foo")
.should("contains.text", "bar")
})
})
})

View File

@ -0,0 +1,82 @@
/**
* @prettier
*/
describe("OpenAPI 3.0 Multiple Servers", () => {
it("should render and execute for server '/test-url-1'", () => {
cy.visit(
"/?url=/documents/features/oas3-multiple-servers.yaml"
)
.get(".scheme-container .schemes .servers label > select")
.select("/test-url-1")
.get("#operations-default-get_")
.click()
// Expand Try It Out
.get(".try-out__btn")
.click()
// Execute
.get(".execute.opblock-control__btn")
.click()
.get(".responses-wrapper .request-url")
.should("contains.text", "/test-url-1")
})
it("should render and execute for server '/test-url-2'", () => {
cy.visit(
"/?url=/documents/features/oas3-multiple-servers.yaml"
)
.get(".scheme-container .schemes .servers label > select")
.select("/test-url-2")
.get("#operations-default-get_")
.click()
// Expand Try It Out
.get(".try-out__btn")
.click()
// Execute
.get(".execute.opblock-control__btn")
.click()
.get(".responses-wrapper .request-url")
.should("contains.text", "/test-url-2")
})
it("should render and execute for server '/test-url-1' after sequence: select '/test-url-2' -> Try-It-Out -> select '/test-url-1'", () => {
cy.visit(
"/?url=/documents/features/oas3-multiple-servers.yaml"
)
.get(".scheme-container .schemes .servers label > select")
.select("/test-url-2")
.get("#operations-default-get_")
.click()
// Expand Try It Out
.get(".try-out__btn")
.click()
// Select a different server
.get(".scheme-container .schemes .servers label > select")
.select("/test-url-1")
// Execute
.get(".execute.opblock-control__btn")
.click()
.get(".responses-wrapper .request-url")
.should("contains.text", "/test-url-1")
})
it("should render and execute for server '/test-url-switch-1' after changing api definition", () => {
cy.visit(
"/?url=/documents/features/oas3-multiple-servers.yaml"
)
.get(".scheme-container .schemes .servers label > select")
.select("/test-url-2")
cy.visit(
"/?url=/documents/features/oas3-multiple-servers-switch.yaml"
)
.get(".scheme-container .schemes .servers label > select")
.select("/test-url-switch-2")
.get("#operations-default-get_")
.click()
// Expand Try It Out
.get(".try-out__btn")
.click()
// Execute
.get(".execute.opblock-control__btn")
.click()
.get(".responses-wrapper .request-url")
.should("contains.text", "/test-url-switch-2")
})
})

View File

@ -0,0 +1,145 @@
/**
* @prettier
*/
describe("OpenAPI 3.0 Allow Empty Values in Request Body", () => {
it("should not apply or render to required fields", () => {
cy.visit(
"/?url=/documents/features/petstore-only-pet.openapi.yaml"
)
.get("#operations-pet-addPet")
.click()
.get(".opblock-section .opblock-section-request-body .body-param-content-type > select")
.select("application/x-www-form-urlencoded")
// Expand Try It Out
.get(".try-out__btn")
.click()
// Request Body
.get(".opblock-body .opblock-section .opblock-section-request-body .parameters:nth-child(2) > .parameters-col_description .parameter__empty_value_toggle input")
.should("not.exist")
})
it("by default, should be checked for all non-required fields", () => {
cy.visit(
"/?url=/documents/features/petstore-only-pet.openapi.yaml"
)
.get("#operations-pet-addPet")
.click()
.get(".opblock-section .opblock-section-request-body .body-param-content-type > select")
.select("application/x-www-form-urlencoded")
// Expand Try It Out
.get(".try-out__btn")
.click()
// Request Body
.get(".opblock-body .opblock-section .opblock-section-request-body .parameters:nth-child(5) > .parameters-col_description .parameter__empty_value_toggle input")
.should("be.checked")
.get(".opblock-body .opblock-section .opblock-section-request-body .parameters:nth-child(6) > .parameters-col_description .parameter__empty_value_toggle input")
.should("be.checked")
})
it("checkbox should be toggle-able", () => {
cy.visit(
"/?url=/documents/features/petstore-only-pet.openapi.yaml"
)
.get("#operations-pet-addPet")
.click()
.get(".opblock-section .opblock-section-request-body .body-param-content-type > select")
.select("application/x-www-form-urlencoded")
// Expand Try It Out
.get(".try-out__btn")
.click()
// Request Body
.get(".opblock-body .opblock-section .opblock-section-request-body .parameters:nth-child(5) > .parameters-col_description .parameter__empty_value_toggle input")
.should("be.checked")
.uncheck()
.get(".opblock-body .opblock-section .opblock-section-request-body .parameters:nth-child(5) > .parameters-col_description .parameter__empty_value_toggle input")
.should("not.be.checked")
})
it("on execute, should allow send with all empty values", () => {
cy.visit(
"/?url=/documents/features/petstore-only-pet.openapi.yaml"
)
.get("#operations-pet-addPet")
.click()
.get(".opblock-section .opblock-section-request-body .body-param-content-type > select")
.select("application/x-www-form-urlencoded")
// Expand Try It Out
.get(".try-out__btn")
.click()
// add item to pass required validation
.get(".opblock-body .opblock-section .opblock-section-request-body .parameters:nth-child(4) > .parameters-col_description button")
.click()
// Execute
.get(".execute.opblock-control__btn")
.click()
// cURL component
.get(".responses-wrapper .curl-command")
.should("exist")
.get(".responses-wrapper .curl-command span")
.should("contains.text", "tags=&status=")
})
it("on execute, should allow send with some empty values", () => {
cy.visit(
"/?url=/documents/features/petstore-only-pet.openapi.yaml"
)
.get("#operations-pet-addPet")
.click()
.get(".opblock-section .opblock-section-request-body .body-param-content-type > select")
.select("application/x-www-form-urlencoded")
// Expand Try It Out
.get(".try-out__btn")
.click()
// Request Body
.get(".opblock-body .opblock-section .opblock-section-request-body .parameters:nth-child(5) > .parameters-col_description .parameter__empty_value_toggle input")
.uncheck()
// add item to pass required validation
.get(".opblock-body .opblock-section .opblock-section-request-body .parameters:nth-child(4) > .parameters-col_description button")
.click()
.get(".opblock-body .opblock-section .opblock-section-request-body .parameters:nth-child(4) input")
.clear()
// Execute
.get(".execute.opblock-control__btn")
.click()
// cURL component
.get(".responses-wrapper .curl-command")
.should("exist")
.get(".responses-wrapper .curl-command span")
.should("contains.text", "&status=")
.should("not.contains.text", "tags=")
})
it("on execute, should allow send with skip all empty values", () => {
cy.visit(
"/?url=/documents/features/petstore-only-pet.openapi.yaml"
)
.get("#operations-pet-addPet")
.click()
.get(".opblock-section .opblock-section-request-body .body-param-content-type > select")
.select("application/x-www-form-urlencoded")
// Expand Try It Out
.get(".try-out__btn")
.click()
// Request Body
.get(".opblock-body .opblock-section .opblock-section-request-body .parameters:nth-child(5) > .parameters-col_description .parameter__empty_value_toggle input")
.uncheck()
.get(".opblock-body .opblock-section .opblock-section-request-body .parameters:nth-child(6) > .parameters-col_description .parameter__empty_value_toggle input")
.uncheck()
// add item to pass required validation
.get(".opblock-body .opblock-section .opblock-section-request-body .parameters:nth-child(4) > .parameters-col_description button")
.click()
.get(".opblock-body .opblock-section .opblock-section-request-body .parameters:nth-child(4) input")
.clear()
// Execute
.get(".execute.opblock-control__btn")
.click()
// cURL component
.get(".responses-wrapper .curl-command")
.should("exist")
.get(".responses-wrapper .curl-command span")
.should("not.contains.text", "tags=")
.should("not.contains.text", "status=")
})
})

View File

@ -0,0 +1,16 @@
describe("OAS3 default views", () => {
describe("multipart/form-data", () => {
it("should display calculated object string, when no examples provided (#7268)", () => {
cy.visit(
"/?url=/documents/features/request-body/multipart/default-views.yaml",
)
.get("#operations-default-post_test")
.click()
// Expand Try It Out
.get(".try-out__btn")
.click()
.get(".parameters-col_description textarea")
.should("contains.text", "\"stuff\": \"string\"")
})
})
})

View File

@ -0,0 +1,265 @@
/**
* @prettier
*/
describe("OpenAPI 3.0 Validation for Required Request Body and Request Body Fields", () => {
describe("Request Body required bug/5181", () => {
beforeEach(() => {
cy.intercept(
{
method: "POST",
url: "/anything/foos",
hostname: "httpbin.org",
},
{}
)
})
it("on execute, if empty value, SHOULD render class 'invalid' and should NOT render cURL component", () => {
cy.visit("/?url=/documents/bugs/5181.yaml")
.get("#operations-default-post_foos")
.click()
// Expand Try It Out
.get(".try-out__btn")
.click()
// get input
.get(
".opblock-body .opblock-section .opblock-section-request-body .parameters:nth-child(1) > .parameters-col_description input"
)
.should("not.have.class", "invalid")
// Execute
.get(".execute.opblock-control__btn")
.click()
// class "invalid" should now exist (and render red, which we won't check)
.get(
".opblock-body .opblock-section .opblock-section-request-body .parameters:nth-child(1) > .parameters-col_description input"
)
.should("have.class", "invalid")
// cURL component should not exist
.get(".responses-wrapper .curl-command")
.should("not.exist")
})
it("on execute, if value exists, should NOT render class 'invalid' and SHOULD render cURL component", () => {
cy.visit("/?url=/documents/bugs/5181.yaml")
.get("#operations-default-post_foos")
.click()
// Expand Try It Out
.get(".try-out__btn")
.click()
// get input
.get(
".opblock-body .opblock-section .opblock-section-request-body .parameters:nth-child(1) > .parameters-col_description input"
)
.type("abc")
// Execute
.get(".execute.opblock-control__btn")
.click()
.get(
".opblock-body .opblock-section .opblock-section-request-body .parameters:nth-child(1) > .parameters-col_description input"
)
.should("not.have.class", "invalid")
// cURL component should exist
.get(".responses-wrapper .curl-command")
.should("exist")
})
})
describe("Request Body required fields - application/json", () => {
it("on execute, if empty value, SHOULD render class 'invalid' and should NOT render cURL component", () => {
cy.visit("/?url=/documents/features/petstore-only-pet.openapi.yaml")
.get("#operations-pet-addPet")
.click()
// Expand Try It Out
.get(".try-out__btn")
.click()
// get and clear textarea
.get(
".opblock-body .opblock-section .opblock-section-request-body .body-param textarea"
)
.should("not.have.class", "invalid")
.clear()
// Execute
.get(".execute.opblock-control__btn")
.click()
// class "invalid" should now exist (and render red, which we won't check)
.get(
".opblock-body .opblock-section .opblock-section-request-body .body-param textarea"
)
.should("have.class", "invalid")
// cURL component should not exist
.get(".responses-wrapper .curl-command")
.should("not.exist")
})
it("on execute, if value exists, even if just single space, should NOT render class 'invalid' and SHOULD render cURL component that contains the single space", () => {
cy.visit("/?url=/documents/features/petstore-only-pet.openapi.yaml")
.get("#operations-pet-addPet")
.click()
// Expand Try It Out
.get(".try-out__btn")
.click()
// get, clear, then modify textarea
.get(
".opblock-body .opblock-section .opblock-section-request-body .body-param textarea"
)
.clear()
.type(" ")
// Execute
.get(".execute.opblock-control__btn")
.click()
.get(
".opblock-body .opblock-section .opblock-section-request-body .body-param textarea"
)
.should("not.have.class", "invalid")
// cURL component should exist
.get(".responses-wrapper .curl-command")
.should("exist")
.get(".responses-wrapper .curl-command span")
.should("contains.text", "' '")
})
})
/*
petstore ux notes:
- required field, but if example value exists, will populate the field. So this test will clear the example value.
- "add item" will insert an empty array, and display an input text box. This establishes a value for the field.
*/
describe("Request Body required fields - application/x-www-form-urlencoded", () => {
it("on execute, if empty value, SHOULD render class 'invalid' and should NOT render cURL component", () => {
cy.visit("/?url=/documents/features/petstore-only-pet.openapi.yaml")
.get("#operations-pet-addPet")
.click()
.get(
".opblock-section .opblock-section-request-body .body-param-content-type > select"
)
.select("application/x-www-form-urlencoded")
// Expand Try It Out
.get(".try-out__btn")
.click()
// get and clear input populated from example value
.get(
".opblock-body .opblock-section .opblock-section-request-body .parameters:nth-child(2) > .parameters-col_description input"
)
.clear()
// Execute
.get(".execute.opblock-control__btn")
.click()
// class "invalid" should now exist (and render red, which we won't check)
.get(
".opblock-body .opblock-section .opblock-section-request-body .parameters:nth-child(2) > .parameters-col_description input"
)
.should("have.class", "invalid")
// cURL component should not exist
.get(".responses-wrapper .curl-command")
.should("not.exist")
})
it("on execute, if all values exist, even if array exists but is empty, should NOT render class 'invalid' and SHOULD render cURL component", () => {
cy.visit("/?url=/documents/features/petstore-only-pet.openapi.yaml")
.get("#operations-pet-addPet")
.click()
.get(
".opblock-section .opblock-section-request-body .body-param-content-type > select"
)
.select("application/x-www-form-urlencoded")
// Expand Try It Out
.get(".try-out__btn")
.click()
// add item to get input
.get(
".opblock-body .opblock-section .opblock-section-request-body .parameters:nth-child(4) > .parameters-col_description button"
)
.click()
// Execute
.get(".execute.opblock-control__btn")
.click()
.get(
".opblock-body .opblock-section .opblock-section-request-body .parameters:nth-child(2) > .parameters-col_description input"
)
.should("have.value", "doggie")
.should("not.have.class", "invalid")
.get(
".opblock-body .opblock-section .opblock-section-request-body .parameters:nth-child(4) > .parameters-col_description input"
)
.should("have.value", "string")
.should("not.have.class", "invalid")
// cURL component should exist
.get(".responses-wrapper .curl-command")
.should("exist")
})
})
describe("Request Body: switching between Content Types", () => {
it("after application/json 'invalid' error, on switch content type to application/x-www-form-urlencoded, SHOULD be free of errors", () => {
cy.visit("/?url=/documents/features/petstore-only-pet.openapi.yaml")
.get("#operations-pet-addPet")
.click()
// Expand Try It Out
.get(".try-out__btn")
.click()
// get and clear textarea
.get(
".opblock-body .opblock-section .opblock-section-request-body .body-param textarea"
)
.should("not.have.class", "invalid")
.clear()
// Execute
.get(".execute.opblock-control__btn")
.click()
.get(
".opblock-body .opblock-section .opblock-section-request-body .body-param textarea"
)
.should("have.class", "invalid")
// switch content type
.get(
".opblock-section .opblock-section-request-body .body-param-content-type > select"
)
.select("application/x-www-form-urlencoded")
.get(
".opblock-body .opblock-section .opblock-section-request-body .parameters:nth-child(2) > .parameters-col_description input"
)
.should("not.have.class", "invalid")
// add item to get input, just an extra confirmation of non-invalid class
.get(
".opblock-body .opblock-section .opblock-section-request-body .parameters:nth-child(4) > .parameters-col_description button"
)
.click()
.get(
".opblock-body .opblock-section .opblock-section-request-body .parameters:nth-child(4) > .parameters-col_description input"
)
.should("not.have.class", "invalid")
})
it("after application/x-www-form-urlencoded 'invalid' error, on switch content type to application/json, SHOULD be free of errors", () => {
cy.visit("/?url=/documents/features/petstore-only-pet.openapi.yaml")
.get("#operations-pet-addPet")
.click()
.get(
".opblock-section .opblock-section-request-body .body-param-content-type > select"
)
.select("application/x-www-form-urlencoded")
// Expand Try It Out
.get(".try-out__btn")
.click()
// get and clear input
.get(
".opblock-body .opblock-section .opblock-section-request-body .parameters:nth-child(2) > .parameters-col_description input"
)
.clear()
// Execute
.get(".execute.opblock-control__btn")
.click()
// class "invalid" should now exist (and render red, which we won't check)
.get(
".opblock-body .opblock-section .opblock-section-request-body .parameters:nth-child(2) > .parameters-col_description input"
)
.should("have.class", "invalid")
// switch content type
.get(
".opblock-section .opblock-section-request-body .body-param-content-type > select"
)
.select("application/json")
.get(
".opblock-body .opblock-section .opblock-section-request-body .body-param textarea"
)
.should("not.have.class", "invalid")
})
})
})

View File

@ -0,0 +1,106 @@
function getExpandedTryout(page = null, operationId = "#operations-pet-addPet") {
return (page || cy.visit(
"/?url=/documents/features/petstore-only-pet.openapi.yaml",
))
.get(operationId)
.click()
// Expand Try It Out
.get(".try-out__btn")
.click()
}
const getRequestBodyFromCY = (page = null, operationId = "#operations-pet-addPet") =>
getExpandedTryout(page, operationId)
// get textarea
.get(".opblock-body .opblock-section .opblock-section-request-body .body-param textarea")
const xmlIndicator = "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n"
const userEditXmlSample = xmlIndicator +
"<pet>\n" +
"\t<id>420</id>\n" +
"\t<name>doggie<3</name>\n" +
"\t<category>\n" +
"\t\t<id>99999999999</id>\n" +
"\t\t<name>Dogiiiiiiiieeee</name>\n" +
"\t</category>\n" +
"\t<photoUrls>\n" +
"\t\t<photoUrl>string</photoUrl>\n" +
"\t</photoUrls>\n" +
"\t<tags>\n" +
"\t\t<tag>\n" +
"\t\t\t<id>0</id>\n" +
"\t\t\t<name>string</name>\n" +
"\t\t</tag>\n" +
"\t</tags>\n" +
"\t<status>available</status>\n" +
"</pet>"
describe("OAS3 Request Body user edit flows", () => {
// Case: Copy xml from email, paste into request body editor, change media-type to xml
it("it should never overwrite user edited value in case of media-type change", () => {
getRequestBodyFromCY()
// replace default sample with xml edited value
.type(`{selectall}${userEditXmlSample}`)
// change media type to xml, because I have forgotten it
.get(".opblock-section .opblock-section-request-body .body-param-content-type > select")
.select("application/xml")
// Ensure user edited body is not overwritten
.get(".opblock-section-request-body")
.within(() => {
cy
.get("textarea")
.should(($div) => {
expect($div.get(0).textContent).to.eq(userEditXmlSample)
})
})
})
// Case: User really wants to try out the brand new xml content-type
it("it should overwrite default value in case of content-type change, even within request body editor(#6836)", () => {
getRequestBodyFromCY()
// change media type to xml, because I have forgotten it (sry really wanted to try out the new xml content-type)
.get(".opblock-section .opblock-section-request-body .body-param-content-type > select")
.select("application/xml")
// Ensure default value is xml after content type change
.get(".opblock-section-request-body")
.within(() => {
cy
.get("textarea")
.should(($div) => {
expect($div.get(0).textContent).to.contain(xmlIndicator)
})
})
})
// Case: User wants to get the default value back
it("it reset the user edited value and render the default value in case of try out reset. (#6517)", () => {
getRequestBodyFromCY()
// replace default sample with bad value
.type("{selectall}ups that should not have happened")
// Cancel Try It Out
.get(".try-out__btn.reset")
.click()
// Ensure default value is xml after content type change
.get(".opblock-section-request-body")
.within(() => {
cy
.get("textarea")
.should(($div) => {
expect($div.get(0).textContent).to.not.contain("ups that should not have happened")
})
})
})
describe("multipart/", () => {
// Case: User wants to execute operation with media-type multipart/ with a enum property. The user expects the first enum value to be used when executed.
it("should use the first enum value on execute if not changed by user (#6976)", () => {
// test/e2e-cypress/static/documents/features/request-body/multipart/enum.yaml
getExpandedTryout(
cy.visit(
"/?url=/documents/features/request-body/multipart/enum.yaml",
), "#operations-default-post_test")
.get(".execute")
.click()
// Assert on the request URL
.get(".curl")
.contains("test_enum=A")
})
})
})

View File

@ -0,0 +1,70 @@
describe("XML schema rendering examples", () => {
it("Should render RequestBody example value when schema contains `oneOf` for mediaType `text/xml`", () => {
cy.visit("?url=/documents/features/oas3-xml.json")
.get("#operations-default-post_foo")
.click()
.get("label > .content-type-wrapper > .content-type option:selected")
.should("have.text", "text/xml")
.get(".body-param__example")
.should("contains.text", "<fooOne>")
})
it("Should render RequestBody example value when schema contains `anyOf` for mediaType `text/xml`", () => {
cy.visit("?url=/documents/features/oas3-xml.json")
.get("#operations-default-post_bar")
.click()
.get("label > .content-type-wrapper > .content-type option:selected")
.should("have.text", "text/xml")
.get(".body-param__example")
.should("contains.text", "<fooOne>")
})
it("Should render RequestBody example value when schema contains `oneOf` for mediaType `application/xml`", () => {
cy.visit("?url=/documents/features/oas3-xml.json")
.get("#operations-default-post_foobar")
.click()
.get("label > .content-type-wrapper > .content-type option:selected")
.should("have.text", "application/xml")
.get(".body-param__example")
.should("contains.text", "<fooOne>")
})
it("Should render RequestBody example value when schema contains `anyOf` for mediaType `application/xml`", () => {
cy.visit("?url=/documents/features/oas3-xml.json")
.get("#operations-default-post_barfoo")
.click()
.get("label > .content-type-wrapper > .content-type option:selected")
.should("have.text", "application/xml")
.get(".body-param__example")
.should("contains.text", "<fooOne>")
})
it("Should render RequestBody example value when switching mediaType to `text/xml` with singular content schema", () => {
cy.visit("?url=/documents/features/oas3-xml.json")
.get("#operations-default-post_barfoo")
.click()
.get("label > .content-type-wrapper > .content-type")
.select("text/xml")
.get(".body-param__example")
.should("contains.text", "<fooThree>")
})
it("Should render RequestBody example value when switching mediaType to `application/xml` with singular content schema", () => {
cy.visit("?url=/documents/features/oas3-xml.json")
.get("#operations-default-post_foo")
.click()
.get("label > .content-type-wrapper > .content-type")
.select("application/xml")
.get(".body-param__example")
.should("contains.text", "<fooTwo>")
})
it("Should render Response example value for mediaType `application/xml`", () => {
cy.visit("?url=/documents/features/oas3-xml.json")
.get("#operations-default-post_foo")
.click()
.get(".response-col_description > .model-example")
.should("contains.text", "<foobarResObj>")
})
it("Should render Response example value for mediaType `text/xml`", () => {
cy.visit("?url=/documents/features/oas3-xml.json")
.get("#operations-default-post_foobar")
.click()
.get(".response-col_description > .model-example")
.should("contains.text", "<foobarResObj>")
})
})

View File

@ -0,0 +1,66 @@
describe("OAuth2 Application flow", function() {
beforeEach(() => {
cy.server()
cy.route({
url: "**/oauth/*",
method: "POST"
}).as("tokenRequest")
})
// https://github.com/swagger-api/swagger-ui/issues/6395
it("should have first authorization input autofocused", () => {
cy
.visit("/?url=http://localhost:3231/swagger.yaml")
.get(".btn.authorize")
.click()
cy.focused()
.should("have.id", "oauth_username")
})
it("should make an application flow Authorization header request", () => {
cy
.visit("/?url=http://localhost:3231/swagger.yaml")
.get(".btn.authorize")
.click()
.get("div.modal-ux-content > div:nth-child(2)").within(() => {
cy.get("#client_id")
.clear()
.type("confidentialApplication")
.get("#client_secret")
.clear()
.type("topSecret")
.get("button.btn.modal-btn.auth.authorize.button")
.click()
})
cy.get("button.close-modal")
.click()
.get("#operations-default-get_application")
.click()
.get(".btn.try-out__btn")
.click()
.get(".btn.execute")
.click()
cy.get("@tokenRequest")
.its("request")
.its("body")
.should("equal", "grant_type=client_credentials")
cy.get("@tokenRequest")
.its("request")
.its("headers")
.its("authorization")
.should("equal", "Basic Y29uZmlkZW50aWFsQXBwbGljYXRpb246dG9wU2VjcmV0")
.get(".live-responses-table .response-col_status")
.contains("200")
})
})

View File

@ -0,0 +1,122 @@
describe("OAuth2 Password flow", function() {
beforeEach(() => {
cy.server()
cy.route({
url: "**/oauth/*",
method: "POST"
}).as("tokenRequest")
})
it("should make a password flow Authorization header request", () => {
cy
.visit("/?url=http://localhost:3231/swagger.yaml")
.get(".btn.authorize")
.click()
.get("#oauth_username")
.type("swagger")
.get("#oauth_password")
.type("password")
.get("#password_type")
.select("basic")
.get("#client_id")
.clear()
.type("application")
.get("#client_secret")
.clear()
.type("secret")
.get("div.modal-ux-content > div:nth-child(1) > div > div:nth-child(2) > div > div.auth-btn-wrapper > button.btn.modal-btn.auth.authorize.button")
.click()
.get("button.close-modal")
.click()
.get("#operations-default-get_password")
.click()
.get(".btn.try-out__btn")
.click()
.get(".btn.execute")
.click()
cy.get("@tokenRequest")
.its("request")
.its("body")
.should("include", "grant_type=password")
.should("include", "username=swagger")
.should("include", "password=password")
.should("not.include", "client_id")
.should("not.include", "client_secret")
cy.get("@tokenRequest")
.its("request")
.its("headers")
.its("authorization")
.should("equal", "Basic YXBwbGljYXRpb246c2VjcmV0")
.get(".live-responses-table .response-col_status")
.contains("200")
})
it("should make a Password flow request-body request", () => {
cy
.visit("/?url=http://localhost:3231/swagger.yaml")
.get(".btn.authorize")
.click()
.get("#oauth_username")
.type("swagger")
.get("#oauth_password")
.type("password")
.get("#password_type")
.select("request-body")
.get("#client_id")
.clear()
.type("application")
.get("#client_secret")
.clear()
.type("secret")
.get("div.modal-ux-content > div:nth-child(1) > div > div:nth-child(2) > div > div.auth-btn-wrapper > button.btn.modal-btn.auth.authorize.button")
.click()
.get("button.close-modal")
.click()
.get("#operations-default-get_password")
.click()
.get(".btn.try-out__btn")
.click()
.get(".btn.execute")
.click()
cy.get("@tokenRequest")
.its("request")
.its("body")
.should("include", "grant_type=password")
.should("include", "username=swagger")
.should("include", "password=password")
.should("include", "client_id=application")
.should("include", "client_secret=secret")
cy.get("@tokenRequest")
.its("request")
.its("headers")
.should("not.have.property", "authorization")
.get(".live-responses-table .response-col_status")
.contains("200")
})
})

View File

@ -0,0 +1,10 @@
describe("Parameter - Invalid definition with missing array 'items' (#7375)", () => {
it("should render gracefully with fallback to default value", () => {
cy.visit("/?url=/documents/features/parameter-array-missing-items.yaml")
.get("#operations-default-get_example1")
.click()
.get("tbody > tr > .parameters-col_description textarea")
.should("exist")
.should("contains.text", "{}")
})
})

View File

@ -0,0 +1,30 @@
describe("Parameter order", () => {
it("should be well ordered", () => {
cy.visit("/?url=/documents/features/parameter-order.yaml")
.get("#operations-default-post_test__id__related__relatedId_")
.click()
.get(".parameters > tbody")
.children()
.each((tr, i, arr) => {
const parameterTableRows = Array.from(arr)
expect(tr).to.have.attr("data-param-in")
if (i === 0) {
return
}
const inValue = tr[0].getAttribute("data-param-in")
if (!inValue) {
return
}
const beforeInValue = parameterTableRows[i - 1].getAttribute("data-param-in")
const sameAsBefore = beforeInValue === inValue
if (sameAsBefore) {
expect(parameterTableRows[i - 1]).to.have.attr("data-param-in", inValue)
return
}
for (let x = i + 1; x < parameterTableRows.length; x++) {
expect(parameterTableRows[x]).to.not.have.attr("data-param-in", beforeInValue)
}
})
})
})

View File

@ -0,0 +1,23 @@
describe("Loading specs by url.primaryName param", () => {
describe("with no param", () => {
it("should load the default spec", () => {
cy.visit("/pages/multiple-urls/index.html")
.get("span.url")
.contains("/documents/petstore-expanded.openapi.yaml")
})
})
describe("with an invalid param", () => {
it("should fall back to the default spec", () => {
cy.visit("/pages/multiple-urls/index.html?urls.primaryName=undefinedUrlName")
.get("span.url")
.contains("/documents/petstore-expanded.openapi.yaml")
})
})
describe("with a valid url.primaryName param", () => {
it("should render the requested spec", () => {
cy.visit("/pages/multiple-urls/index.html?urls.primaryName=Petstore Swagger")
.get("span.url")
.contains("/documents/petstore.swagger.yaml")
})
})
})

View File

@ -0,0 +1,114 @@
/**
* @prettier
*/
describe("OpenAPI 3.0 Request Body upload file button", () => {
describe("application/octet-stream", () => {
it("should display description with the correct content type", () => {
cy.visit("/?url=/documents/features/request-body-upload-file.yaml")
.get("#operations-default-uploadApplicationOctetStream")
.click()
.get(".opblock-section-request-body .opblock-description-wrapper i")
.should("have.text", "Example values are not available for application/octet-stream media types.")
})
it("should display a file upload button", () => {
cy.visit("/?url=/documents/features/request-body-upload-file.yaml")
.get("#operations-default-uploadApplicationOctetStream")
.click()
.get(".try-out__btn")
.click()
.get(".opblock-section-request-body .opblock-description-wrapper input")
.should("have.prop", "type", "file")
})
})
describe("image/png", () => {
it("should display description with the correct content type", () => {
cy.visit("/?url=/documents/features/request-body-upload-file.yaml")
.get("#operations-default-uploadImagePng")
.click()
.get(".opblock-section-request-body .opblock-description-wrapper i")
.should("have.text", "Example values are not available for image/png media types.")
})
it("should display a file upload button", () => {
cy.visit("/?url=/documents/features/request-body-upload-file.yaml")
.get("#operations-default-uploadApplicationOctetStream")
.click()
.get(".try-out__btn")
.click()
.get(".opblock-section-request-body .opblock-description-wrapper input")
.should("have.prop", "type", "file")
})
})
describe("audio/wav", () => {
it("should display description with the correct content type", () => {
cy.visit("/?url=/documents/features/request-body-upload-file.yaml")
.get("#operations-default-uploadAudioWav")
.click()
.get(".opblock-section-request-body .opblock-description-wrapper i")
.should("have.text", "Example values are not available for audio/wav media types.")
})
it("should display a file upload button", () => {
cy.visit("/?url=/documents/features/request-body-upload-file.yaml")
.get("#operations-default-uploadApplicationOctetStream")
.click()
.get(".try-out__btn")
.click()
.get(".opblock-section-request-body .opblock-description-wrapper input")
.should("have.prop", "type", "file")
})
})
describe("video/mpeg", () => {
it("should display description with the correct content type", () => {
cy.visit("/?url=/documents/features/request-body-upload-file.yaml")
.get("#operations-default-uploadVideoMpeg")
.click()
.get(".opblock-section-request-body .opblock-description-wrapper i")
.should("have.text", "Example values are not available for video/mpeg media types.")
})
it("should display a file upload button", () => {
cy.visit("/?url=/documents/features/request-body-upload-file.yaml")
.get("#operations-default-uploadApplicationOctetStream")
.click()
.get(".try-out__btn")
.click()
.get(".opblock-section-request-body .opblock-description-wrapper input")
.should("have.prop", "type", "file")
})
})
describe("schema format binary", () => {
it("should display description with the correct content type", () => {
cy.visit("/?url=/documents/features/request-body-upload-file.yaml")
.get("#operations-default-uploadSchemaFormatBinary")
.click()
.get(".opblock-section-request-body .opblock-description-wrapper i")
.should("have.text", "Example values are not available for application/x-custom media types.")
})
it("should display a file upload button", () => {
cy.visit("/?url=/documents/features/request-body-upload-file.yaml")
.get("#operations-default-uploadSchemaFormatBinary")
.click()
.get(".try-out__btn")
.click()
.get(".opblock-section-request-body .opblock-description-wrapper input")
.should("have.prop", "type", "file")
})
})
describe("schema format base64", () => {
it("should display description with the correct content type", () => {
cy.visit("/?url=/documents/features/request-body-upload-file.yaml")
.get("#operations-default-uploadSchemaFormatBase64")
.click()
.get(".opblock-section-request-body .opblock-description-wrapper i")
.should("have.text", "Example values are not available for application/x-custom media types.")
})
it("should display a file upload button", () => {
cy.visit("/?url=/documents/features/request-body-upload-file.yaml")
.get("#operations-default-uploadSchemaFormatBinary")
.click()
.get(".try-out__btn")
.click()
.get(".opblock-section-request-body .opblock-description-wrapper input")
.should("have.prop", "type", "file")
})
})
})

View File

@ -0,0 +1,49 @@
describe("Response extension feature", () => {
describe("in Swagger 2", () => {
const swagger2BaseUrl = "/?showExtensions=true&docExpansion=full&url=/documents/features/response-extension.swagger.yaml"
describe("without x- values", () => {
it("should omit response extensions section", () => {
cy.visit(swagger2BaseUrl)
.get("tr.response[data-code='200'] td.response-col_description div.response__extension")
.should("not.exist")
})
})
describe("with x- values", () => {
it("should list each value", () => {
const page = cy.visit(swagger2BaseUrl)
page.get("tr.response[data-code='404'] td.response-col_description div.response__extension:nth-child(2)")
.should("have.text", "x-error: true")
page.get("tr.response[data-code='404'] td.response-col_description div.response__extension:nth-child(3)")
.should("have.text", "x-error-codes: List [ \"NOT_FOUND\" ]")
})
})
})
describe("in OpenAPI 3", () => {
const openAPI3BaseUrl = "/?showExtensions=true&docExpansion=full&url=/documents/features/response-extension.openapi.yaml"
describe("without x- values", () => {
it("should omit response extensions section", () => {
cy.visit(openAPI3BaseUrl)
.get("tr.response[data-code='200'] td.response-col_description div.response__extension")
.should("not.exist")
})
})
describe("with x- values", () => {
it("should list each value", () => {
const page = cy.visit(openAPI3BaseUrl)
page.get("tr.response[data-code='404'] td.response-col_description div.response__extension:nth-child(2)")
.should("have.text", "x-error: true")
page.get("tr.response[data-code='404'] td.response-col_description div.response__extension:nth-child(3)")
.should("have.text", "x-error-codes: List [ \"NOT_FOUND\" ]")
})
})
})
})

View File

@ -0,0 +1,129 @@
/**
* @prettier
*/
describe("JSON Schema Form: Enum & Boolean in a Parameter", () => {
beforeEach(() => {
cy.visit(
"/?url=/documents/features/schema-form-enum-boolean.yaml"
)
.get("#operations-pet-findPetsByStatus")
.click()
// Expand Try It Out
.get(".try-out__btn")
.click()
// @alias Execute Button
cy.get(".execute.opblock-control__btn").as("executeBtn")
// @alias Parameters
cy.get(".opblock-section tbody > tr > .parameters-col_description > select")
.eq(0)
.as("enumIsRequired")
cy.get(".opblock-section tbody > tr > .parameters-col_description > select")
.eq(1)
.as("booleanIsOptional")
cy.get(".opblock-section tbody > tr > .parameters-col_description > select")
.eq(2)
.as("booleanIsRequired")
})
it("should render @enumIsRequired with list of three options", () => {
cy.get("@enumIsRequired")
.should("contains.text", "available")
.should("contains.text", "pending")
.should("contains.text", "sold")
.should("not.contains.text", "--")
.find("option")
.should("have.length", 3)
})
it("should render @booleanIsOptional with default empty string value (display '--')", () => {
cy.get("@booleanIsOptional")
.should("have.value", "")
.should("contains.text", "--")
})
it("should render @booleanIsRequired with default empty string value (display '--')", () => {
cy.get("@booleanIsRequired")
.should("have.value", "")
.should("contains.text", "--")
})
it("should NOT be able to execute with empty @enumIsRequired and @booleanIsRequired values", () => {
// Execute
cy.get("@executeBtn")
.click()
cy.get("@enumIsRequired")
.should("have.class", "invalid")
cy.get("@booleanIsRequired")
.should("have.class", "invalid")
// cURL component
cy.get(".responses-wrapper .curl-command")
.should("not.exist")
})
it("should NOT be able to execute with empty @booleanIsRequired value, but valid @enumIsRequired", () => {
cy.get("@enumIsRequired")
.select("pending")
// Execute
cy.get("@executeBtn")
.click()
cy.get("@enumIsRequired")
.should("not.have.class", "invalid")
cy.get("@booleanIsRequired")
.should("have.class", "invalid")
// cURL component
cy.get(".responses-wrapper .curl-command")
.should("not.exist")
})
it("should NOT be able to execute with empty @enumIsRequired value, but valid @booleanIsRequired", () => {
cy.get("@booleanIsRequired")
.select("false")
// Execute
cy.get("@executeBtn")
.click()
cy.get("@enumIsRequired")
.should("have.class", "invalid")
cy.get("@booleanIsRequired")
.should("not.have.class", "invalid")
// cURL component
cy.get(".responses-wrapper .curl-command")
.should("not.exist")
})
it("should execute, if @booleanIsOptional value is 'false'", () => {
cy.get("@enumIsRequired")
.select("pending")
cy.get("@booleanIsRequired")
.select("false")
cy.get("@booleanIsOptional")
.select("false")
// Execute
cy.get("@executeBtn")
.click()
cy.get("@enumIsRequired")
.should("not.have.class", "invalid")
cy.get("@booleanIsRequired")
.should("not.have.class", "invalid")
.should("not.contains.text", "expectIsOptional")
// cURL component
cy.get(".responses-wrapper .curl-command")
.should("exist")
.get(".responses-wrapper .curl-command span")
.should("contains.text", "expectIsOptional=false")
})
it("should execute, but NOT send @booleanIsOptional value if not provided", () => {
cy.get("@enumIsRequired")
.select("pending")
cy.get("@booleanIsRequired")
.select("false")
// Execute
cy.get("@executeBtn")
.click()
cy.get("@enumIsRequired")
.should("not.have.class", "invalid")
cy.get("@booleanIsRequired")
.should("not.have.class", "invalid")
.should("not.contains.text", "expectIsOptional")
// cURL component
cy.get(".responses-wrapper .curl-command")
.should("exist")
.get(".responses-wrapper .curl-command span")
.should("not.contains.text", "expectIsOptional")
})
})

View File

@ -0,0 +1,830 @@
/**
* @prettier
*/
describe("OpenAPI 3.0 Additional JsonSchemaForm in a Parameter", () => {
describe("incomplete API definition with missing schema key or schema value(s)", () => {
describe("parameter exists as global", () => {
it("should render when parameter exists as global, but missing schema key", () => {
cy.visit("/?url=/documents/features/schema-form-missing-values.yaml")
.get("#operations-default-get_case_one_no_schema")
.click()
.get(".opblock-description .renderedMarkdown p")
.should("have.text", "sf")
})
it("should render when parameter exists as global, but missing all schema values", () => {
cy.visit("/?url=/documents/features/schema-form-missing-values.yaml")
.get("#operations-default-get_case_one_no_type_or_format")
.click()
.get(".opblock-description .renderedMarkdown p")
.should("have.text", "sf")
})
it("should render when parameter exists as global, schema key exists, but missing schema values: format", () => {
cy.visit("/?url=/documents/features/schema-form-missing-values.yaml")
.get("#operations-default-get_case_one_format_only_no_type")
.click()
.get(".opblock-description .renderedMarkdown p")
.should("have.text", "sf")
})
it("should render when parameter exists as global, schema key exists, but missing schema value: type", () => {
cy.visit("/?url=/documents/features/schema-form-missing-values.yaml")
.get("#operations-default-get_case_one_type_only_no_format")
.click()
.get(".opblock-description .renderedMarkdown p")
.should("have.text", "sf")
})
})
describe("parameter exists in method", () => {
it("should render when parameter exists in method, but missing schema key", () => {
cy.visit("/?url=/documents/features/schema-form-missing-values.yaml")
.get("#operations-default-get_case_two_no_schema")
.click()
.get(".opblock-description .renderedMarkdown p")
.should("have.text", "sf")
})
it("should render when parameter exists in method, schema key exists, but missing all schema values", () => {
cy.visit("/?url=/documents/features/schema-form-missing-values.yaml")
.get("#operations-default-get_case_two_no_type_or_format")
.click()
.get(".opblock-description .renderedMarkdown p")
.should("have.text", "sf")
})
it("should render when parameter exists in method, schema key exists, but missing schema value: format", () => {
cy.visit("/?url=/documents/features/schema-form-missing-values.yaml")
.get("#operations-default-get_case_one_type_only_no_format")
.click()
.get(".opblock-description .renderedMarkdown p")
.should("have.text", "sf")
})
it("should render when parameter exists in method, schema key exists, but missing schema value: type", () => {
cy.visit("/?url=/documents/features/schema-form-missing-values.yaml")
.get("#operations-default-get_case_one_format_only_no_type")
.click()
.get(".opblock-description .renderedMarkdown p")
.should("have.text", "sf")
})
})
})
describe("/Array", () => {
describe("in a Parameter", () => {
it("should allow modification of values in Try-It-Out", () => {
cy.visit(
"/?url=/documents/features/multiple-examples-core.openapi.yaml"
)
.get("#operations-default-post_Array")
.click()
// Expand Try It Out
.get(".try-out__btn")
.click()
.get(".parameters-col_description .examples-select > select")
.select("ArrayExampleB")
// Add a new item
.get(".json-schema-form-item-add")
.click()
.get(".json-schema-form-item:last-of-type > input")
.type("{selectall}5")
// Assert against the input fields
.get(".json-schema-form-item > input")
.then((inputs) => {
expect(inputs.map((i, el) => el.value).toArray()).to.deep.equal([
"1",
"2",
"3",
"4",
"5",
])
})
.get(".parameters-col_description .examples-select > select")
.find(":selected")
.should("have.text", "[Modified value]")
})
it("should allow removal of added value in Try-It-Out", () => {
cy.visit(
"/?url=/documents/features/multiple-examples-core.openapi.yaml"
)
.get("#operations-default-post_Array")
.click()
// Expand Try It Out
.get(".try-out__btn")
.click()
.get(".parameters-col_description .examples-select > select")
.select("ArrayExampleB")
// Add a new item
.get(".json-schema-form-item-add")
.click()
.get(".json-schema-form-item:last-of-type > input")
.type("{selectall}5")
// Assert against the input fields
.get(".json-schema-form-item > input")
.then((inputs) => {
expect(inputs.map((i, el) => el.value).toArray()).to.deep.equal([
"1",
"2",
"3",
"4",
"5",
])
})
.get(".parameters-col_description .examples-select > select")
.find(":selected")
.should("have.text", "[Modified value]")
// Remove the last item that was just added
.get(
".json-schema-form-item:last-of-type > .json-schema-form-item-remove"
)
.click()
.get(".json-schema-form-item > input")
.then((inputs) => {
expect(inputs.map((i, el) => el.value).toArray()).to.deep.equal([
"1",
"2",
"3",
"4",
])
})
})
it("should allow removal of nth of values in Try-It-Out", () => {
cy.visit(
"/?url=/documents/features/multiple-examples-core.openapi.yaml"
)
.get("#operations-default-post_Array")
.click()
// Expand Try It Out
.get(".try-out__btn")
.click()
.get(".parameters-col_description .examples-select > select")
.select("ArrayExampleB")
// Add a new item
.get(".json-schema-form-item-add")
.click()
.get(".json-schema-form-item:last-of-type > input")
.type("{selectall}5")
// Assert against the input fields
.get(".json-schema-form-item > input")
.then((inputs) => {
expect(inputs.map((i, el) => el.value).toArray()).to.deep.equal([
"1",
"2",
"3",
"4",
"5",
])
})
.get(".parameters-col_description .examples-select > select")
.find(":selected")
.should("have.text", "[Modified value]")
// Remove the second item in list
.get(
".json-schema-form-item:nth-child(2) > .json-schema-form-item-remove"
)
.click()
.get(".json-schema-form-item > input")
.then((inputs) => {
expect(inputs.map((i, el) => el.value).toArray()).to.deep.equal([
"1",
"3",
"4",
"5",
])
})
})
it("should allow execution of operation in Try-It-Out", () => {
cy.visit(
"/?url=/documents/features/multiple-examples-core.openapi.yaml"
)
.get("#operations-default-post_Array")
.click()
// Expand Try It Out
.get(".try-out__btn")
.click()
.get(".parameters-col_description .examples-select > select")
.select("ArrayExampleB")
// Execute
.get(".execute.opblock-control__btn")
.click()
// Expect new element to be visible after Execute
.get(".btn-clear.opblock-control__btn")
.should("have.text", "Clear")
})
it("should add empty item and allow execution of operation in Try-It-Out", () => {
cy.visit(
"/?url=/documents/features/multiple-examples-core.openapi.yaml"
)
.get("#operations-default-post_Array")
.click()
// Expand Try It Out
.get(".try-out__btn")
.click()
.get(".parameters-col_description .examples-select > select")
.select("ArrayExampleB")
// Add a new item
.get(".json-schema-form-item-add")
.click()
// Execute without prior typing a value
.get(".execute.opblock-control__btn")
.click()
// Expect new element to be visible after Execute
.get(".btn-clear.opblock-control__btn")
.should("have.text", "Clear")
})
})
})
describe("Petstore", () => {
describe("/pet/findByStatus", () => {
it("should render the operation, execute with default value", () => {
cy.visit("/?url=/documents/features/schema-form-core.yaml")
.get("#operations-default-findPetsByStatus")
.click()
// Expand operation
.get(".opblock-title span")
.should("have.text", "Parameters")
// Expand Try It Out
.get(".try-out__btn")
.click()
// Execute
.get(".execute.opblock-control__btn")
.click()
// Expect new element to be visible after Execute
.get(".btn-clear.opblock-control__btn")
.should("have.text", "Clear")
// Compare Request URL
.get(".request-url pre.microlight")
.should("contain.text", "available")
})
it("should render the operation, modify value, and execute with modified value", () => {
cy.visit("/?url=/documents/features/schema-form-core.yaml")
.get("#operations-default-findPetsByStatus")
.click()
// Expand operation
.get(".opblock-title span")
.should("have.text", "Parameters")
// Expand Try It Out
.get(".try-out__btn")
.click()
// Select
.get(".parameters-col_description > select")
.select("pending")
// Execute
.get(".execute.opblock-control__btn")
.click()
// Expect new element to be visible after Execute
.get(".btn-clear.opblock-control__btn")
.should("have.text", "Clear")
// Compare Request URL
.get(".request-url pre.microlight")
.should("contain.text", "pending")
})
})
describe("/pet/findByTags", () => {
it("should allow modification of values in Try-It-Out", () => {
cy.visit("/?url=/documents/features/schema-form-core.yaml")
.get("#operations-pet-findPetsByTags")
.click()
// Expand Try It Out
.get(".try-out__btn")
.click()
// Add a new item
.get(".json-schema-form-item-add")
.click()
.get(".json-schema-form-item > input")
.type("{selectall}spotted")
// Assert against the input fields
.get(".json-schema-form-item > input")
.then((inputs) => {
expect(inputs.map((i, el) => el.value).toArray()).to.deep.equal([
"spotted",
])
})
})
it("should allow removal of added value in Try-It-Out", () => {
cy.visit("/?url=/documents/features/schema-form-core.yaml")
.get("#operations-pet-findPetsByTags")
.click()
// Expand Try It Out
.get(".try-out__btn")
.click()
// Add a new item
.get(".json-schema-form-item-add")
.click()
.get(".json-schema-form-item:last-of-type > input")
.type("{selectall}spotted")
// Assert against the input fields
.get(".json-schema-form-item > input")
.then((inputs) => {
expect(inputs.map((i, el) => el.value).toArray()).to.deep.equal([
"spotted",
])
})
// Remove the last item that was just added
.get(
".json-schema-form-item:last-of-type > .json-schema-form-item-remove"
)
.click()
.get(".json-schema-form-item > input")
.should("not.exist")
})
it("should allow removal of nth of values in Try-It-Out", () => {
cy.visit("/?url=/documents/features/schema-form-core.yaml")
.get("#operations-pet-findPetsByTags")
.click()
// Expand Try It Out
.get(".try-out__btn")
.click()
// Add a new item
.get(".json-schema-form-item-add")
.click()
.get(".json-schema-form-item:last-of-type > input")
.type("{selectall}spotted")
// Assert against the input fields
.get(".json-schema-form-item > input")
.then((inputs) => {
expect(inputs.map((i, el) => el.value).toArray()).to.deep.equal([
"spotted",
])
})
// Add a 2nd new item
.get(".json-schema-form-item-add")
.click()
.get(".json-schema-form-item:last-of-type > input")
.type("{selectall}large")
// Assert against the input fields
.get(".json-schema-form-item > input")
.then((inputs) => {
expect(inputs.map((i, el) => el.value).toArray()).to.deep.equal([
"spotted",
"large",
])
})
// Add a 3rd new item
.get(".json-schema-form-item-add")
.click()
.get(".json-schema-form-item:last-of-type > input")
.type("{selectall}puppy")
// Assert against the input fields
.get(".json-schema-form-item > input")
.then((inputs) => {
expect(inputs.map((i, el) => el.value).toArray()).to.deep.equal([
"spotted",
"large",
"puppy",
])
})
// Remove the second item in list
.get(
".json-schema-form-item:nth-child(2) > .json-schema-form-item-remove"
)
.click()
.get(".json-schema-form-item > input")
.then((inputs) => {
expect(inputs.map((i, el) => el.value).toArray()).to.deep.equal([
"spotted",
"puppy",
])
})
})
it("should allow execution of operation without modifications in Try-It-Out (debounce)", () => {
cy.visit("/?url=/documents/features/schema-form-core.yaml")
.get("#operations-pet-findPetsByTags")
.click()
// Expand Try It Out
.get(".try-out__btn")
.click()
// Execute
.get(".execute.opblock-control__btn")
.click()
// Expect new element to be visible after Execute
.get(".btn-clear.opblock-control__btn")
.should("have.text", "Clear")
// Compare Request URL
.get(".request-url pre.microlight")
.should("contain.text", "findByTags")
})
it("should add empty item and allow execution of operation in Try-It-Out (debounce)", () => {
cy.visit("/?url=/documents/features/schema-form-core.yaml")
.get("#operations-pet-findPetsByTags")
.click()
// Expand Try It Out
.get(".try-out__btn")
.click()
// Add a new item
.get(".json-schema-form-item-add")
.click()
// Execute without prior typing a value
.get(".execute.opblock-control__btn")
.click()
// Expect new element to be visible after Execute
.get(".btn-clear.opblock-control__btn")
.should("have.text", "Clear")
// Compare Request URL
.get(".request-url pre.microlight")
.should("contain.text", "findByTags")
})
it("should add modified item and allow execution of operation in Try-It-Out", () => {
cy.visit("/?url=/documents/features/schema-form-core.yaml")
.get("#operations-pet-findPetsByTags")
.click()
// Expand Try It Out
.get(".try-out__btn")
.click()
// Add a new item
.get(".json-schema-form-item-add")
.click()
.get(".json-schema-form-item > input")
.type("{selectall}spotted")
// Assert against the input fields
.get(".json-schema-form-item > input")
.then((inputs) => {
expect(inputs.map((i, el) => el.value).toArray()).to.deep.equal([
"spotted",
])
})
// Execute
.get(".execute.opblock-control__btn")
.click()
// Expect new element to be visible after Execute
.get(".btn-clear.opblock-control__btn")
.should("have.text", "Clear")
// Compare Request URL
.get(".request-url pre.microlight")
.should("contain.text", "spotted")
})
it("should add 3 modified items, remove the middle child, and allow execution of operation Try-It-Out", () => {
cy.visit("/?url=/documents/features/schema-form-core.yaml")
.get("#operations-pet-findPetsByTags")
.click()
// Expand Try It Out
.get(".try-out__btn")
.click()
// Add a new item
.get(".json-schema-form-item-add")
.click()
.get(".json-schema-form-item:last-of-type > input")
.type("{selectall}spotted")
// Assert against the input fields
.get(".json-schema-form-item > input")
.then((inputs) => {
expect(inputs.map((i, el) => el.value).toArray()).to.deep.equal([
"spotted",
])
})
// Add a 2nd new item
.get(".json-schema-form-item-add")
.click()
.get(".json-schema-form-item:last-of-type > input")
.type("{selectall}large")
// Assert against the input fields
.get(".json-schema-form-item > input")
.then((inputs) => {
expect(inputs.map((i, el) => el.value).toArray()).to.deep.equal([
"spotted",
"large",
])
})
// Add a 3rd new item
.get(".json-schema-form-item-add")
.click()
.get(".json-schema-form-item:last-of-type > input")
.type("{selectall}puppy")
// Assert against the input fields
.get(".json-schema-form-item > input")
.then((inputs) => {
expect(inputs.map((i, el) => el.value).toArray()).to.deep.equal([
"spotted",
"large",
"puppy",
])
})
// Remove the second item in list
.get(
".json-schema-form-item:nth-child(2) > .json-schema-form-item-remove"
)
.click()
.get(".json-schema-form-item > input")
.then((inputs) => {
expect(inputs.map((i, el) => el.value).toArray()).to.deep.equal([
"spotted",
"puppy",
])
})
// Execute
.get(".execute.opblock-control__btn")
.click()
// Expect new element to be visible after Execute
.get(".btn-clear.opblock-control__btn")
.should("have.text", "Clear")
// Compare Request URL
.get(".request-url pre.microlight")
.should("contain.text", "tags=spotted&tags=puppy")
.should("not.have.text", "large")
})
})
describe("/petOwner/{petOwnerId}", () => {
// This is a (GET) debounce test for schema type: string
it("should render the operation, and allow execute of operation with empty value (debounce)", () => {
cy.visit("/?url=/documents/features/schema-form-core.yaml")
.get("#operations-petOwner-getPetOwnerById")
.click()
// Expand operation
.get(".opblock-title span")
.should("have.text", "Parameters")
// Expand Try It Out
.get(".try-out__btn")
.click()
// Execute
.get(".execute.opblock-control__btn")
.click()
// Expect new element to be visible after Execute
.get(".btn-clear.opblock-control__btn")
.should("have.text", "Clear")
// Compare Request URL
.get(".request-url pre.microlight")
.should("contain.text", "petOwner")
})
it("should render the operation, and input field, and allow execute of operation", () => {
cy.visit("/?url=/documents/features/schema-form-core.yaml")
.get("#operations-petOwner-getPetOwnerById")
.click()
// Expand operation
.get(".opblock-title span")
.should("have.text", "Parameters")
// Expand Try It Out
.get(".try-out__btn")
.click()
.get(".parameters-col_description > input")
.type("123")
// Execute
.get(".execute.opblock-control__btn")
.click()
// Expect new element to be visible after Execute
.get(".btn-clear.opblock-control__btn")
.should("have.text", "Clear")
// Compare Request URL
.get(".request-url pre.microlight")
.should("contain.text", "petOwner")
.should("contain.text", "123")
})
})
describe("/petOwner/listOfServiceTrainer", () => {
it("should allow execution of operation with value=true in Try-It-Out", () => {
cy.visit("/?url=/documents/features/schema-form-core.yaml")
.get("#operations-petOwner-listOfServiceTrainer")
.click()
// Expand Try It Out
.get(".try-out__btn")
.click()
// add 1st item
.get(".json-schema-form-item-add")
.click()
.get(".json-schema-form-item > select")
.select("true")
// Execute
.get(".execute.opblock-control__btn")
.click()
// Expect new element to be visible after Execute
.get(".btn-clear.opblock-control__btn")
.should("have.text", "Clear")
// Compare Request URL
.get(".request-url pre.microlight")
.should("contain.text", "tags=true")
})
it("should allow execution of operation with value=false in Try-It-Out", () => {
cy.visit("/?url=/documents/features/schema-form-core.yaml")
.get("#operations-petOwner-listOfServiceTrainer")
.click()
// Expand Try It Out
.get(".try-out__btn")
.click()
// add 1st item
.get(".json-schema-form-item-add")
.click()
.get(".json-schema-form-item > select")
.select("false")
// Execute
.get(".execute.opblock-control__btn")
.click()
// Expect new element to be visible after Execute
.get(".btn-clear.opblock-control__btn")
.should("have.text", "Clear")
// Compare Request URL
.get(".request-url pre.microlight")
.should("contain.text", "tags=false")
})
it("should allow execution of operation with value=true&value=false in Try-It-Out", () => {
cy.visit("/?url=/documents/features/schema-form-core.yaml")
.get("#operations-petOwner-listOfServiceTrainer")
.click()
// Expand Try It Out
.get(".try-out__btn")
.click()
// add 1st item
.get(".json-schema-form-item-add")
.click()
.get(".json-schema-form-item > select")
.select("true")
// add 2nd item
.get(".json-schema-form-item-add")
.click()
.get(".json-schema-form-item:last-of-type > select")
.select("false")
// Execute
.get(".execute.opblock-control__btn")
.click()
// Expect new element to be visible after Execute
.get(".btn-clear.opblock-control__btn")
.should("have.text", "Clear")
// Compare Request URL
.get(".request-url pre.microlight")
.should("contain.text", "tags=true&tags=false")
})
it("should allow execution of operation with value=false after removing value=true in Try-It-Out", () => {
cy.visit("/?url=/documents/features/schema-form-core.yaml")
.get("#operations-petOwner-listOfServiceTrainer")
.click()
// Expand Try It Out
.get(".try-out__btn")
.click()
// add 1st item
.get(".json-schema-form-item-add")
.click()
.get(".json-schema-form-item > select")
.select("true")
// add 2nd item
.get(".json-schema-form-item-add")
.click()
.get(".json-schema-form-item:last-of-type > select")
.select("false")
// remove 1st item
.get(
".json-schema-form-item:nth-child(1) > .json-schema-form-item-remove"
)
.click()
// Execute
.get(".execute.opblock-control__btn")
.click()
// Expect new element to be visible after Execute
.get(".btn-clear.opblock-control__btn")
.should("have.text", "Clear")
// Compare Request URL
.get(".request-url pre.microlight")
.should("contain.text", "tags=false")
})
it("should allow execution of operation with value=(empty) in Try-It-Out", () => {
cy.visit("/?url=/documents/features/schema-form-core.yaml")
.get("#operations-petOwner-listOfServiceTrainer")
.click()
// Expand Try It Out
.get(".try-out__btn")
.click()
// Execute
.get(".execute.opblock-control__btn")
.click()
// Expect new element to be visible after Execute
.get(".btn-clear.opblock-control__btn")
.should("have.text", "Clear")
// Compare Request URL
.get(".request-url pre.microlight")
.should("contain.text", "listOfServiceTrainer")
})
})
describe("/petOwner/findByPreference", () => {
it("should allow execution of operation with value=(empty) in Try-It-Out", () => {
cy.visit("/?url=/documents/features/schema-form-core.yaml")
.get("#operations-petOwner-findByPreference")
.click()
// Expand Try It Out
.get(".try-out__btn")
.click()
// Execute
.get(".execute.opblock-control__btn")
.click()
// Expect new element to be visible after Execute
.get(".btn-clear.opblock-control__btn")
.should("have.text", "Clear")
// Compare Request URL
.get(".request-url pre.microlight")
.should("contain.text", "findByPreference")
})
it("should allow execution of operation with selected value in Try-It-Out", () => {
cy.visit("/?url=/documents/features/schema-form-core.yaml")
.get("#operations-petOwner-findByPreference")
.click()
// Expand Try It Out
.get(".try-out__btn")
.click()
// Select
.get(".parameters-col_description > select")
.select("dog")
// Execute
.get(".execute.opblock-control__btn")
.click()
// Expect new element to be visible after Execute
.get(".btn-clear.opblock-control__btn")
.should("have.text", "Clear")
// Compare Request URL
.get(".request-url pre.microlight")
.should("contain.text", "findByPreference")
.should("contain.text", "dog")
})
it("should allow execution of operation with multiple selected values in Try-It-Out", () => {
cy.visit("/?url=/documents/features/schema-form-core.yaml")
.get("#operations-petOwner-findByPreference")
.click()
// Expand Try It Out
.get(".try-out__btn")
.click()
// Select
.get(".parameters-col_description > select")
.select(["dog", "cat"])
// Execute
.get(".execute.opblock-control__btn")
.click()
// Expect new element to be visible after Execute
.get(".btn-clear.opblock-control__btn")
.should("have.text", "Clear")
// Compare Request URL
.get(".request-url pre.microlight")
.should("contain.text", "findByPreference")
.should("contain.text", "dog")
.should("contain.text", "cat")
})
})
describe("/petOwner/createWithList", () => {
it("should allow execution of operation with default text in textArea in Try-It-Out", () => {
cy.visit("/?url=/documents/features/schema-form-core.yaml")
.get("#operations-petOwner-petOwnerCreateWithList")
.click()
// Expand Try It Out
.get(".try-out__btn")
.click()
// Execute
.get(".execute.opblock-control__btn")
.click()
// Expect new element to be visible after Execute
.get(".btn-clear.opblock-control__btn")
.should("have.text", "Clear")
// Compare Request URL
.get(".request-url pre.microlight")
.should("contain.text", "createWithList")
})
it("should allow execution of operation with cleared textArea in Try-It-Out", () => {
cy.visit("/?url=/documents/features/schema-form-core.yaml")
.get("#operations-petOwner-petOwnerCreateWithList")
.click()
// Expand Try It Out
.get(".try-out__btn")
.click()
.get(".body-param__text")
.clear()
// Execute
.get(".execute.opblock-control__btn")
.click()
// Expect new element to be visible after Execute
.get(".btn-clear.opblock-control__btn")
.should("have.text", "Clear")
// Compare Request URL
.get(".request-url pre.microlight")
.should("contain.text", "createWithList")
})
it("should allow execution of operation with modified textArea in Try-It-Out", () => {
cy.visit("/?url=/documents/features/schema-form-core.yaml")
.get("#operations-petOwner-petOwnerCreateWithList")
.click()
// Expand Try It Out
.get(".try-out__btn")
.click()
.get(".body-param__text")
.clear()
// note: adding this much type adds 6+ seconds to test
.type(
`[
{
"id": 10,
"petId": 201,
"petOwnerFirstName": "John",
},
{
"id": 11,
"petId": 201,
"petOwnerFirstName": "Jane",
}
]`
)
.should("contain.text", "Jane")
.should("contain.text", "201")
// Execute
.get(".execute.opblock-control__btn")
.click()
// Expect new element to be visible after Execute
.get(".btn-clear.opblock-control__btn")
.should("have.text", "Clear")
// Compare Request URL
.get(".request-url pre.microlight")
.should("contain.text", "createWithList")
// Compare Curl
.get(".curl")
.should("contain.text", "Jane")
.should("contain.text", "201")
})
})
})
})

View File

@ -0,0 +1,31 @@
/**
* @prettier
*/
describe("Parse YAML as YAML@1.2 with json_schema for all JSON-supported types", () => {
it("should have date string even without quotes", () => {
cy.visit("/?url=/documents/features/spec-parse-to-json.yaml")
.get("#operations-default-get_foo")
.click()
// Responses -> example value tab
.get(".language-json > :nth-child(3)")
.should("have.text", "\"without-quotes\"")
.get(".language-json > :nth-child(5)")
.should("have.text", "\"1999-11-31\"")
// Responses -> schema tab
.get(".model-example > .tab > :nth-child(2)")
.click()
.get(":nth-child(1) > :nth-child(2) > .model > :nth-child(1)")
.click()
.get(
":nth-child(1) > :nth-child(2) > .model > :nth-child(1) > .prop > .property"
) // first element, without-quotes
.should("have.text", "example: 1999-11-31")
.get(":nth-child(2) > :nth-child(2) > .model > :nth-child(1)")
.click()
.get(
":nth-child(2) > :nth-child(2) > .model > :nth-child(1) > .prop > .property"
) // second element, with quotes
.should("have.text", "example: 1999-12-31")
})
})

View File

@ -0,0 +1,40 @@
/**
* @prettier
*/
describe("Syntax Highlighting for JSON value cases", () => {
// expect span contains entire string sample
// fail case is if the string sample gets broken up into segments
// due react-syntax-highlighter attempting to escape characters into multiple segments
describe("OAS 2", () => {
it("should render full syntax highlighted string in Request (param body) example", () => {
cy.visit("/?url=/documents/features/syntax-highlighting-json-oas2.yaml")
.get("#operations-default-post_setServices")
.click()
.get(".body-param__example > .language-json > :nth-child(10)")
.should("have.text", "\"79daf5b4-aa4b-1452-eae5-42c231477ba7\"")
})
it("should render full syntax highlighted string in Response example", () => {
cy.visit("/?url=/documents/features/syntax-highlighting-json-oas2.yaml")
.get("#operations-default-post_setServices")
.click()
.get(".example > .language-json > :nth-child(28)")
.should("have.text", "\"5ff06f632bb165394501b05d3a833355\"")
})
})
describe("OAS 3", () => {
it("should render full syntax highlighted string in Request example", () => {
cy.visit("/?url=/documents/features/syntax-highlighting-json-oas3.yaml")
.get("#operations-default-post_setServices")
.click()
.get(".body-param__example > .language-json > :nth-child(15)")
.should("have.text", "\"22a124b4-594b-4452-bdf5-fc3ef1477ba7\"")
})
it("should render full syntax highlighted string in Response example", () => {
cy.visit("/?url=/documents/features/syntax-highlighting-json-oas3.yaml")
.get("#operations-default-post_setServices")
.click()
.get(".example > .language-json > :nth-child(33)")
.should("have.text", "\"f0009babde9dbe204540d79cf754408e\"")
})
})
})

View File

@ -0,0 +1,22 @@
describe("Try it out enabled configuration", () => {
it("should enable the try it out section when true", () => {
cy
.visit("?tryItOutEnabled=true&url=/documents/features/try-it-out-enabled.yaml")
.get("#operations-default-get_")
.click()
.get(".try-out__btn")
.should("have.text","Cancel")
})
it("should disable the try it out section when false", () => {
cy
.visit("?tryItOutEnabled=false&url=/documents/features/try-it-out-enabled.yaml")
.get("#operations-default-get_")
.click()
.get(".try-out__btn")
.should("have.text","Try it out ")
})
})

View File

@ -0,0 +1,15 @@
describe("Try It Out: schema required properties can be overridden", () => {
it("should execute", () => {
cy
.visit("?tryItOutEnabled=true&url=/documents/features/try-it-out-schema-required-override-allowed.yaml")
.get("#operations-default-setDeliveryLocation")
.click()
.get(".body-param__text")
.should("include.value", "testProperty")
.clear() // swagger-ui will auto insert "{}" into textarea
.get(".execute-wrapper > .btn")
.click()
.get(".curl-command")
.should("exist")
})
})

View File

@ -0,0 +1,111 @@
describe("configuration options: `urls` and `urls.primaryName`", () => {
describe("`urls` only", () => {
it("should render a list of URLs correctly", () => {
cy.visit("/?configUrl=/configs/urls.yaml")
.get("select")
.children()
.should("have.length", 2)
.get("select > option")
.eq(0)
.should("have.text", "One")
.should("have.attr", "value", "/documents/features/urls/1.yaml")
.get("select > option")
.eq(1)
.should("have.text", "Two")
.should("have.attr", "value", "/documents/features/urls/2.yaml")
})
it("should render the first URL in the list", () => {
cy.visit("/?configUrl=/configs/urls.yaml")
.get("h2.title")
.should("have.text", "One")
.window()
.then(win => win.ui.specSelectors.url())
.should("equal", "/documents/features/urls/1.yaml")
})
})
it("should respect a `urls.primaryName`", () => {
cy.visit("/?configUrl=/configs/urls-primary-name.yaml")
.get("select")
.should("have.value", "/documents/features/urls/2.yaml")
.get("h2.title")
.should("have.text", "Two")
.window()
.then(win => win.ui.specSelectors.url())
.should("equal", "/documents/features/urls/2.yaml")
})
})
describe("urls with server variables", () => {
it("should compute a url and default server variables", () => {
cy.visit("/?configUrl=/configs/urls-server-variables.yaml")
.get("code")
.should("have.text", "https://localhost:3200/oneFirstUrl")
.get("tr > :nth-child(1)")
.should("have.text", "basePath")
.get("input")
.should("have.value", "/oneFirstUrl")
})
it("should change server variables", () => {
cy.visit("/?configUrl=/configs/urls-server-variables.yaml")
.get("code")
.should("have.text", "https://localhost:3200/oneFirstUrl")
.get("tr > :nth-child(1)")
.should("have.text", "basePath")
.get("input")
.should("have.value", "/oneFirstUrl")
.get(".servers > label > select")
.eq(0)
.select(1)
.get("input")
.should("have.value", "/oneSecondUrl")
})
it("should select and compute second url", () => {
cy.visit("/?configUrl=/configs/urls-server-variables.yaml")
.get("select > option")
.eq(1)
.should("have.text", "Two")
.get("select")
.eq(0)
.select(1)
.get("code")
.should("have.text", "https://localhost:3200/twoFirstUrl")
.get("input")
.should("have.value", "/twoFirstUrl")
})
it("should select second url, then toggle back to first url", () => {
cy.visit("/?configUrl=/configs/urls-server-variables.yaml")
.get("select > option")
.get("select")
.eq(0)
.select(1)
.get("input")
.should("have.value", "/twoFirstUrl")
// toggle url back
.get("select")
.eq(0)
.select(0)
.get("code")
.should("have.text", "https://localhost:3200/oneFirstUrl")
.get("input")
.should("have.value", "/oneFirstUrl")
})
it("should change server variables, then select second url, and maintain server variables index", () => {
cy.visit("/?configUrl=/configs/urls-server-variables.yaml")
.get(".servers > label >select")
.eq(0)
.select(1)
.get("input")
.should("have.value", "/oneSecondUrl")
// change url
.get("select > option")
.get("select")
.eq(0)
.select(1)
.get("input")
.should("have.value", "/twoSecondUrl")
.get("input")
.should("have.value", "/twoSecondUrl")
})
})