Skip to content

Commit

Permalink
fix(oas3): fix getting initial values for request body in OpenAPI 3.x (
Browse files Browse the repository at this point in the history
  • Loading branch information
glowcloud authored Mar 29, 2024
1 parent 6a493fb commit 8086d97
Show file tree
Hide file tree
Showing 5 changed files with 279 additions and 46 deletions.
60 changes: 37 additions & 23 deletions src/core/plugins/oas3/components/request-body.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -150,39 +150,53 @@ const RequestBody = ({
<table>
<tbody>
{
Map.isMap(bodyProperties) && bodyProperties.entrySeq().map(([key, prop]) => {
if (prop.get("readOnly")) return
Map.isMap(bodyProperties) && bodyProperties.entrySeq().map(([key, schema]) => {
if (schema.get("readOnly")) return

const schemaWithoutKeywords = schema.filter((v, k) => k !== "oneOf"
&& k !== "anyOf"
&& k !== "$$ref"
)

let commonExt = showCommonExtensions ? getCommonExtensions(prop) : null
if (schemaWithoutKeywords.size === 0) {
const oneOf = schema.get("oneOf")
const anyOf = schema.get("anyOf")
const nestedSchema = List.isList(oneOf)
? oneOf.get(0)
: List.isList(anyOf)
? anyOf.get(0)
: null

if (Map.isMap(nestedSchema)) {
schema = nestedSchema
}
}

let commonExt = showCommonExtensions ? getCommonExtensions(schema) : null
const required = schemaForMediaType.get("required", List()).includes(key)
const type = prop.get("type")
const format = prop.get("format")
const description = prop.get("description")
const type = schema.get("type")
const format = schema.get("format")
const description = schema.get("description")
const currentValue = requestBodyValue.getIn([key, "value"])
const currentErrors = requestBodyValue.getIn([key, "errors"]) || requestBodyErrors
const included = requestBodyInclusionSetting.get(key) || false

const useInitialValFromSchemaSamples = prop.has("default")
|| prop.has("example")
|| prop.hasIn(["items", "example"])
|| prop.hasIn(["items", "default"])
const useInitialValFromEnum = prop.has("enum") && (prop.get("enum").size === 1 || required)
const useInitialValue = useInitialValFromSchemaSamples || useInitialValFromEnum

let initialValue = ""
if (type === "array" && !useInitialValue) {
initialValue = []
let initialValue = fn.getSampleSchema(schema, false, {
includeWriteOnly: true
})

if (initialValue === false) {
initialValue = "false"
}
if (type === "object" || useInitialValue) {
// TODO: what about example or examples from requestBody could be passed as exampleOverride
initialValue = fn.getSampleSchema(prop, false, {
includeWriteOnly: true
})

if (initialValue === 0) {
initialValue = "0"
}

if (typeof initialValue !== "string" && type === "object") {
initialValue = stringify(initialValue)
}

if (typeof initialValue === "string" && type === "array") {
initialValue = JSON.parse(initialValue)
}
Expand All @@ -201,7 +215,7 @@ const RequestBody = ({
{!showCommonExtensions || !commonExt.size ? null : commonExt.entrySeq().map(([key, v]) => <ParameterExt key={`${key}-${v}`} xKey={key} xVal={v} />)}
</div>
<div className="parameter__deprecated">
{ prop.get("deprecated") ? "deprecated": null }
{ schema.get("deprecated") ? "deprecated": null }
</div>
</td>
<td className="parameters-col_description">
Expand All @@ -210,7 +224,7 @@ const RequestBody = ({
<JsonSchemaForm
fn={fn}
dispatchInitialValue={!isFile}
schema={prop}
schema={schema}
description={key}
getComponent={getComponent}
value={currentValue === undefined ? initialValue : currentValue}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -31,8 +31,12 @@ describe("OpenAPI 3.0 Allow Empty Values in Request Body", () => {
.get(".try-out__btn")
.click()
// Request Body
.get(".opblock-body .opblock-section .opblock-section-request-body .parameters:nth-child(5) > .parameters-col_description .json-schema-form-item-remove")
.click()
.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 select")
.select("--")
.get(".opblock-body .opblock-section .opblock-section-request-body .parameters:nth-child(6) > .parameters-col_description .parameter__empty_value_toggle input")
.should("be.checked")
})
Expand All @@ -49,6 +53,8 @@ describe("OpenAPI 3.0 Allow Empty Values in Request Body", () => {
.get(".try-out__btn")
.click()
// Request Body
.get(".opblock-body .opblock-section .opblock-section-request-body .parameters:nth-child(5) > .parameters-col_description .json-schema-form-item-remove")
.click()
.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()
Expand All @@ -67,9 +73,11 @@ describe("OpenAPI 3.0 Allow Empty Values in Request Body", () => {
// 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")
// Remove example values
.get(".opblock-body .opblock-section .opblock-section-request-body .parameters:nth-child(5) > .parameters-col_description .json-schema-form-item-remove")
.click()
.get(".opblock-body .opblock-section .opblock-section-request-body .parameters:nth-child(6) > .parameters-col_description select")
.select("--")
// Execute
.get(".execute.opblock-control__btn")
.click()
Expand All @@ -92,11 +100,11 @@ describe("OpenAPI 3.0 Allow Empty Values in Request Body", () => {
.get(".try-out__btn")
.click()
// Request Body
.get(".opblock-body .opblock-section .opblock-section-request-body .parameters:nth-child(5) > .parameters-col_description .json-schema-form-item-remove")
.click()
.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
Expand All @@ -122,15 +130,14 @@ describe("OpenAPI 3.0 Allow Empty Values in Request Body", () => {
.get(".try-out__btn")
.click()
// Request Body
.get(".opblock-body .opblock-section .opblock-section-request-body .parameters:nth-child(5) > .parameters-col_description .json-schema-form-item-remove")
.click()
.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 select")
.select("--")
.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()
Expand Down
15 changes: 1 addition & 14 deletions test/e2e-cypress/e2e/features/oas3-request-body-required.cy.js
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,7 @@ describe("OpenAPI 3.0 Validation for Required Request Body and Request Body Fiel
.get(
".opblock-body .opblock-section .opblock-section-request-body .parameters:nth-child(1) > .parameters-col_description input"
)
.clear()
.should("not.have.class", "invalid")
// Execute
.get(".execute.opblock-control__btn")
Expand Down Expand Up @@ -163,11 +164,6 @@ describe("OpenAPI 3.0 Validation for Required Request Body and Request Body Fiel
// 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()
Expand Down Expand Up @@ -217,15 +213,6 @@ describe("OpenAPI 3.0 Validation for Required Request Body and Request Body Fiel
".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")
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
/**
* @prettier
*/

describe("OpenAPI 3.0 oneOf and anyOf example", () => {
it("should show example values for multipart/form-data and application/x-www-form-urlencoded content types", () => {
cy.visit("/?url=/documents/features/oas3-one-of-any-of-example.yaml").then(
() => {
cy.contains("/documentsWithCombineOneOf")
.click()
.get(".try-out__btn")
.click()
.get("textarea")
.contains("documentDate")
.should("exist")
cy.contains("/documentsWithCombineOneOf").click()
cy.contains("/documentsWithCombineAnyOf")
.click()
.get(".try-out__btn")
.contains("Try it out")
.click()
.get("textarea")
.contains("documentDate")
.should("exist")
}
)
})
})
Loading

0 comments on commit 8086d97

Please sign in to comment.