Skip to content

Commit 8086d97

Browse files
authored
fix(oas3): fix getting initial values for request body in OpenAPI 3.x (#9762)
Refs #9745
1 parent 6a493fb commit 8086d97

File tree

5 files changed

+279
-46
lines changed

5 files changed

+279
-46
lines changed

src/core/plugins/oas3/components/request-body.jsx

+37-23
Original file line numberDiff line numberDiff line change
@@ -150,39 +150,53 @@ const RequestBody = ({
150150
<table>
151151
<tbody>
152152
{
153-
Map.isMap(bodyProperties) && bodyProperties.entrySeq().map(([key, prop]) => {
154-
if (prop.get("readOnly")) return
153+
Map.isMap(bodyProperties) && bodyProperties.entrySeq().map(([key, schema]) => {
154+
if (schema.get("readOnly")) return
155+
156+
const schemaWithoutKeywords = schema.filter((v, k) => k !== "oneOf"
157+
&& k !== "anyOf"
158+
&& k !== "$$ref"
159+
)
155160

156-
let commonExt = showCommonExtensions ? getCommonExtensions(prop) : null
161+
if (schemaWithoutKeywords.size === 0) {
162+
const oneOf = schema.get("oneOf")
163+
const anyOf = schema.get("anyOf")
164+
const nestedSchema = List.isList(oneOf)
165+
? oneOf.get(0)
166+
: List.isList(anyOf)
167+
? anyOf.get(0)
168+
: null
169+
170+
if (Map.isMap(nestedSchema)) {
171+
schema = nestedSchema
172+
}
173+
}
174+
175+
let commonExt = showCommonExtensions ? getCommonExtensions(schema) : null
157176
const required = schemaForMediaType.get("required", List()).includes(key)
158-
const type = prop.get("type")
159-
const format = prop.get("format")
160-
const description = prop.get("description")
177+
const type = schema.get("type")
178+
const format = schema.get("format")
179+
const description = schema.get("description")
161180
const currentValue = requestBodyValue.getIn([key, "value"])
162181
const currentErrors = requestBodyValue.getIn([key, "errors"]) || requestBodyErrors
163182
const included = requestBodyInclusionSetting.get(key) || false
164183

165-
const useInitialValFromSchemaSamples = prop.has("default")
166-
|| prop.has("example")
167-
|| prop.hasIn(["items", "example"])
168-
|| prop.hasIn(["items", "default"])
169-
const useInitialValFromEnum = prop.has("enum") && (prop.get("enum").size === 1 || required)
170-
const useInitialValue = useInitialValFromSchemaSamples || useInitialValFromEnum
171-
172-
let initialValue = ""
173-
if (type === "array" && !useInitialValue) {
174-
initialValue = []
184+
let initialValue = fn.getSampleSchema(schema, false, {
185+
includeWriteOnly: true
186+
})
187+
188+
if (initialValue === false) {
189+
initialValue = "false"
175190
}
176-
if (type === "object" || useInitialValue) {
177-
// TODO: what about example or examples from requestBody could be passed as exampleOverride
178-
initialValue = fn.getSampleSchema(prop, false, {
179-
includeWriteOnly: true
180-
})
191+
192+
if (initialValue === 0) {
193+
initialValue = "0"
181194
}
182195

183196
if (typeof initialValue !== "string" && type === "object") {
184197
initialValue = stringify(initialValue)
185198
}
199+
186200
if (typeof initialValue === "string" && type === "array") {
187201
initialValue = JSON.parse(initialValue)
188202
}
@@ -201,7 +215,7 @@ const RequestBody = ({
201215
{!showCommonExtensions || !commonExt.size ? null : commonExt.entrySeq().map(([key, v]) => <ParameterExt key={`${key}-${v}`} xKey={key} xVal={v} />)}
202216
</div>
203217
<div className="parameter__deprecated">
204-
{ prop.get("deprecated") ? "deprecated": null }
218+
{ schema.get("deprecated") ? "deprecated": null }
205219
</div>
206220
</td>
207221
<td className="parameters-col_description">
@@ -210,7 +224,7 @@ const RequestBody = ({
210224
<JsonSchemaForm
211225
fn={fn}
212226
dispatchInitialValue={!isFile}
213-
schema={prop}
227+
schema={schema}
214228
description={key}
215229
getComponent={getComponent}
216230
value={currentValue === undefined ? initialValue : currentValue}

test/e2e-cypress/e2e/features/oas3-request-body-allow-empty-values.cy.js

+16-9
Original file line numberDiff line numberDiff line change
@@ -31,8 +31,12 @@ describe("OpenAPI 3.0 Allow Empty Values in Request Body", () => {
3131
.get(".try-out__btn")
3232
.click()
3333
// Request Body
34+
.get(".opblock-body .opblock-section .opblock-section-request-body .parameters:nth-child(5) > .parameters-col_description .json-schema-form-item-remove")
35+
.click()
3436
.get(".opblock-body .opblock-section .opblock-section-request-body .parameters:nth-child(5) > .parameters-col_description .parameter__empty_value_toggle input")
3537
.should("be.checked")
38+
.get(".opblock-body .opblock-section .opblock-section-request-body .parameters:nth-child(6) > .parameters-col_description select")
39+
.select("--")
3640
.get(".opblock-body .opblock-section .opblock-section-request-body .parameters:nth-child(6) > .parameters-col_description .parameter__empty_value_toggle input")
3741
.should("be.checked")
3842
})
@@ -49,6 +53,8 @@ describe("OpenAPI 3.0 Allow Empty Values in Request Body", () => {
4953
.get(".try-out__btn")
5054
.click()
5155
// Request Body
56+
.get(".opblock-body .opblock-section .opblock-section-request-body .parameters:nth-child(5) > .parameters-col_description .json-schema-form-item-remove")
57+
.click()
5258
.get(".opblock-body .opblock-section .opblock-section-request-body .parameters:nth-child(5) > .parameters-col_description .parameter__empty_value_toggle input")
5359
.should("be.checked")
5460
.uncheck()
@@ -67,9 +73,11 @@ describe("OpenAPI 3.0 Allow Empty Values in Request Body", () => {
6773
// Expand Try It Out
6874
.get(".try-out__btn")
6975
.click()
70-
// add item to pass required validation
71-
.get(".opblock-body .opblock-section .opblock-section-request-body .parameters:nth-child(4) > .parameters-col_description button")
76+
// Remove example values
77+
.get(".opblock-body .opblock-section .opblock-section-request-body .parameters:nth-child(5) > .parameters-col_description .json-schema-form-item-remove")
7278
.click()
79+
.get(".opblock-body .opblock-section .opblock-section-request-body .parameters:nth-child(6) > .parameters-col_description select")
80+
.select("--")
7381
// Execute
7482
.get(".execute.opblock-control__btn")
7583
.click()
@@ -92,11 +100,11 @@ describe("OpenAPI 3.0 Allow Empty Values in Request Body", () => {
92100
.get(".try-out__btn")
93101
.click()
94102
// Request Body
103+
.get(".opblock-body .opblock-section .opblock-section-request-body .parameters:nth-child(5) > .parameters-col_description .json-schema-form-item-remove")
104+
.click()
95105
.get(".opblock-body .opblock-section .opblock-section-request-body .parameters:nth-child(5) > .parameters-col_description .parameter__empty_value_toggle input")
96106
.uncheck()
97107
// add item to pass required validation
98-
.get(".opblock-body .opblock-section .opblock-section-request-body .parameters:nth-child(4) > .parameters-col_description button")
99-
.click()
100108
.get(".opblock-body .opblock-section .opblock-section-request-body .parameters:nth-child(4) input")
101109
.clear()
102110
// Execute
@@ -122,15 +130,14 @@ describe("OpenAPI 3.0 Allow Empty Values in Request Body", () => {
122130
.get(".try-out__btn")
123131
.click()
124132
// Request Body
133+
.get(".opblock-body .opblock-section .opblock-section-request-body .parameters:nth-child(5) > .parameters-col_description .json-schema-form-item-remove")
134+
.click()
125135
.get(".opblock-body .opblock-section .opblock-section-request-body .parameters:nth-child(5) > .parameters-col_description .parameter__empty_value_toggle input")
126136
.uncheck()
137+
.get(".opblock-body .opblock-section .opblock-section-request-body .parameters:nth-child(6) > .parameters-col_description select")
138+
.select("--")
127139
.get(".opblock-body .opblock-section .opblock-section-request-body .parameters:nth-child(6) > .parameters-col_description .parameter__empty_value_toggle input")
128140
.uncheck()
129-
// add item to pass required validation
130-
.get(".opblock-body .opblock-section .opblock-section-request-body .parameters:nth-child(4) > .parameters-col_description button")
131-
.click()
132-
.get(".opblock-body .opblock-section .opblock-section-request-body .parameters:nth-child(4) input")
133-
.clear()
134141
// Execute
135142
.get(".execute.opblock-control__btn")
136143
.click()

test/e2e-cypress/e2e/features/oas3-request-body-required.cy.js

+1-14
Original file line numberDiff line numberDiff line change
@@ -26,6 +26,7 @@ describe("OpenAPI 3.0 Validation for Required Request Body and Request Body Fiel
2626
.get(
2727
".opblock-body .opblock-section .opblock-section-request-body .parameters:nth-child(1) > .parameters-col_description input"
2828
)
29+
.clear()
2930
.should("not.have.class", "invalid")
3031
// Execute
3132
.get(".execute.opblock-control__btn")
@@ -163,11 +164,6 @@ describe("OpenAPI 3.0 Validation for Required Request Body and Request Body Fiel
163164
// Expand Try It Out
164165
.get(".try-out__btn")
165166
.click()
166-
// add item to get input
167-
.get(
168-
".opblock-body .opblock-section .opblock-section-request-body .parameters:nth-child(4) > .parameters-col_description button"
169-
)
170-
.click()
171167
// Execute
172168
.get(".execute.opblock-control__btn")
173169
.click()
@@ -217,15 +213,6 @@ describe("OpenAPI 3.0 Validation for Required Request Body and Request Body Fiel
217213
".opblock-body .opblock-section .opblock-section-request-body .parameters:nth-child(2) > .parameters-col_description input"
218214
)
219215
.should("not.have.class", "invalid")
220-
// add item to get input, just an extra confirmation of non-invalid class
221-
.get(
222-
".opblock-body .opblock-section .opblock-section-request-body .parameters:nth-child(4) > .parameters-col_description button"
223-
)
224-
.click()
225-
.get(
226-
".opblock-body .opblock-section .opblock-section-request-body .parameters:nth-child(4) > .parameters-col_description input"
227-
)
228-
.should("not.have.class", "invalid")
229216
})
230217
it("after application/x-www-form-urlencoded 'invalid' error, on switch content type to application/json, SHOULD be free of errors", () => {
231218
cy.visit("/?url=/documents/features/petstore-only-pet.openapi.yaml")
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,28 @@
1+
/**
2+
* @prettier
3+
*/
4+
5+
describe("OpenAPI 3.0 oneOf and anyOf example", () => {
6+
it("should show example values for multipart/form-data and application/x-www-form-urlencoded content types", () => {
7+
cy.visit("/?url=/documents/features/oas3-one-of-any-of-example.yaml").then(
8+
() => {
9+
cy.contains("/documentsWithCombineOneOf")
10+
.click()
11+
.get(".try-out__btn")
12+
.click()
13+
.get("textarea")
14+
.contains("documentDate")
15+
.should("exist")
16+
cy.contains("/documentsWithCombineOneOf").click()
17+
cy.contains("/documentsWithCombineAnyOf")
18+
.click()
19+
.get(".try-out__btn")
20+
.contains("Try it out")
21+
.click()
22+
.get("textarea")
23+
.contains("documentDate")
24+
.should("exist")
25+
}
26+
)
27+
})
28+
})

0 commit comments

Comments
 (0)