Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
33 changes: 13 additions & 20 deletions src/core/plugins/oas3/components/request-body.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -5,8 +5,6 @@ import { Map, OrderedMap, List, fromJS } from "immutable"
import { getCommonExtensions, stringify, isEmptyValue, immutableToJS } from "core/utils"
import { getKnownSyntaxHighlighterLanguage } from "core/utils/jsonParse"

/* eslint-disable react/jsx-no-bind */

export const getDefaultRequestBodyValue = (requestBody, mediaType, activeExamplesKey, fn) => {
const mediaTypeValue = requestBody.getIn(["content", mediaType]) ?? OrderedMap()
const schema = mediaTypeValue.get("schema", OrderedMap()).toJS()
Expand Down Expand Up @@ -105,22 +103,15 @@ const RequestBody = ({
}
requestBodyErrors = List.isList(requestBodyErrors) ? requestBodyErrors : List()

if(!mediaTypeValue.size) {
const isFileContentType = fn.getIsFileContentType(contentType)
const isFileFormat = fn.getIsFileFormat(mediaTypeValue?.get("schema"))
const isOAS31FileSchema = specSelectors.isOAS31() && isFileContentType

if (!mediaTypeValue.size && !isOAS31FileSchema) {
return null
}

const isObjectContent = mediaTypeValue.getIn(["schema", "type"]) === "object"
const isBinaryFormat = mediaTypeValue.getIn(["schema", "format"]) === "binary"
const isBase64Format = mediaTypeValue.getIn(["schema", "format"]) === "base64"

if(
contentType === "application/octet-stream"
|| contentType.indexOf("image/") === 0
|| contentType.indexOf("audio/") === 0
|| contentType.indexOf("video/") === 0
|| isBinaryFormat
|| isBase64Format
) {

if (isFileContentType || isFileFormat) {
const Input = getComponent("Input")

if(!isExecute) {
Expand All @@ -132,6 +123,8 @@ const RequestBody = ({
return <Input type={"file"} onChange={handleFile} />
}

const isObjectContent = mediaTypeValue?.getIn(["schema", "type"]) === "object"

if (
isObjectContent &&
(
Expand Down Expand Up @@ -162,8 +155,8 @@ const RequestBody = ({
let commonExt = showCommonExtensions ? getCommonExtensions(schema) : null
const required = schemaForMediaType.get("required", List()).includes(key)
const typeLabel = fn.jsonSchema202012.getType(immutableToJS(schema))
const type = fn.jsonSchema202012.foldType(immutableToJS(schema?.get("type")))
const itemType = fn.jsonSchema202012.foldType(immutableToJS(schema?.getIn(["items", "type"])))
const type = fn.jsonSchema202012.foldType(immutableToJS(schema?.get("type")))
const itemType = fn.jsonSchema202012.foldType(immutableToJS(schema?.getIn(["items", "type"])))
const format = schema.get("format")
const description = schema.get("description")
const currentValue = requestBodyValue.getIn([key, "value"])
Expand All @@ -190,7 +183,7 @@ const RequestBody = ({
initialValue = JSON.parse(initialValue)
}

const isFile = type === "string" && (format === "binary" || format === "base64")
const isFile = fn.getIsFileFormat(schema)

const jsonSchemaForm = <JsonSchemaForm
fn={fn}
Expand Down Expand Up @@ -225,7 +218,7 @@ const RequestBody = ({
<Markdown source={ description }></Markdown>
{isExecute ? <div>
{(type === "object" || itemType === "object") ? (
<ModelExample
<ModelExample
getComponent={getComponent}
specPath={specPath.push("schema")}
getConfigs={getConfigs}
Expand Down
20 changes: 20 additions & 0 deletions src/core/plugins/oas3/fn.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
/**
* @prettier
*/

export const getIsFileFormat = (schema) => {
if (!schema) return false

const isStringType = schema.get("type") === "string"
const format = schema.get("format")
const isBinaryFormat = format === "binary"
const isBase64Format = format === "base64" || format === "byte"
Comment thread
char0n marked this conversation as resolved.

return isStringType && (isBinaryFormat || isBase64Format)
}

export const getIsFileContentType = (contentType) =>
contentType === "application/octet-stream" ||
contentType?.indexOf("image/") === 0 ||
contentType?.indexOf("audio/") === 0 ||
contentType?.indexOf("video/") === 0
2 changes: 2 additions & 0 deletions src/core/plugins/oas3/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@ import wrapComponents from "./wrap-components"
import * as actions from "./actions"
import * as selectors from "./selectors"
import reducers from "./reducers"
import * as fn from "./fn"

export default function () {
return {
Expand All @@ -28,5 +29,6 @@ export default function () {
selectors: { ...selectors },
},
},
fn,
}
}
8 changes: 4 additions & 4 deletions src/core/plugins/oas3/wrap-components/json-schema-string.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -6,14 +6,14 @@ export default OAS3ComponentWrapFactory(({ Ori, ...props }) => {
schema,
getComponent,
errors,
onChange
onChange,
fn
} = props

const format = schema && schema.get ? schema.get("format") : null
const type = schema && schema.get ? schema.get("type") : null
const isFileFormat = fn.getIsFileFormat(schema)
const Input = getComponent("Input")

if(type && type === "string" && (format && (format === "binary" || format === "base64"))) {
if (isFileFormat) {
return <Input type="file"
className={ errors.length ? "invalid" : ""}
title={ errors.length ? errors : ""}
Expand Down
2 changes: 2 additions & 0 deletions src/core/plugins/oas31/after-load.js
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ import {
getProperties,
} from "./json-schema-2020-12-extensions/fn"
import { wrapOAS31Fn } from "./fn"
import { makeGetIsFileFormat } from "./oas3-extensions/fn"

function afterLoad({ fn, getSystem }) {
// overrides for fn.jsonSchema202012
Expand All @@ -32,6 +33,7 @@ function afterLoad({ fn, getSystem }) {
getXmlSampleSchema: fn.jsonSchema202012.getXmlSampleSchema,
getSampleSchema: fn.jsonSchema202012.getSampleSchema,
mergeJsonSchema: fn.jsonSchema202012.mergeJsonSchema,
getIsFileFormat: makeGetIsFileFormat(fn),
},
getSystem()
)
Expand Down
23 changes: 23 additions & 0 deletions src/core/plugins/oas31/oas3-extensions/fn.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
/**
* @prettier
*/
import { immutableToJS } from "core/utils"

export const makeGetIsFileFormat = (fn) => {
const getIsFileFormat = (schema) => {
if (!schema) return null

const type = fn.jsonSchema202012.getType(immutableToJS(schema))
const isFileContentMediaType = fn.getIsFileContentType(
schema.get("contentMediaType")
)
const isBase64Encoding = schema.get("contentEncoding") === "base64"

return (
(type === "string" || type === "any") &&
Comment thread
char0n marked this conversation as resolved.
(isFileContentMediaType || isBase64Encoding)
)
}

return getIsFileFormat
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,65 @@
/**
* @prettier
*/

describe("OpenAPI 3.1.0 file upload", () => {
beforeEach(() => {
cy.visit("/?url=/documents/features/oas31-file-upload.yaml")
})

it("should render file input when contentMediaType of request body schema is application/octet-stream", () => {
cy.get(".opblock-summary-path span")
.contains("/requestBody-contentMediaType")
.click()
cy.contains("Try it out").click()
cy.get(".opblock-description-wrapper input[type=file]").should("exist")
})

it("should render file input when contentEncoding of request body schema is base64", () => {
cy.get(".opblock-summary-path span")
.contains("/requestBody-contentEncoding")
.click()
cy.contains("Try it out").click()
cy.get(".opblock-description-wrapper input[type=file]").should("exist")
})

it("should render file input when Media Type Object for file upload is empty", () => {
cy.get(".opblock-summary-path span")
.contains("/requestBody-noSchema")
.click()
cy.contains("Try it out").click()
cy.get(".opblock-description-wrapper input[type=file]").should("exist")
})

it("should render file input when contentMediaType of a parameter schema is application/octet-stream", () => {
cy.get(".opblock-summary-path span")
.contains("/parameter-contentMediaType")
.click()
cy.contains("Try it out").click()
cy.get(".parameters-col_description input[type=file]").should("exist")
})

it("should render file input when contentEncoding of a parameter schema is base64", () => {
cy.get(".opblock-summary-path span")
.contains("/parameter-contentEncoding")
.click()
cy.contains("Try it out").click()
cy.get(".parameters-col_description input[type=file]").should("exist")
})

it("should render file input when contentMediaType of a multipart/form-data object property is application/octet-stream", () => {
cy.get(".opblock-summary-path span")
.contains("/property-contentMediaType")
.click()
cy.contains("Try it out").click()
cy.get(".opblock-description-wrapper input[type=file]").should("exist")
})

it("should render file input when contentEncoding of a multipart/form-data object property is base64", () => {
cy.get(".opblock-summary-path span")
.contains("/property-contentEncoding")
.click()
cy.contains("Try it out").click()
cy.get(".opblock-description-wrapper input[type=file]").should("exist")
})
})
59 changes: 59 additions & 0 deletions test/e2e-cypress/static/documents/features/oas31-file-upload.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,59 @@
openapi: 3.1.0
paths:
/requestBody-contentMediaType:
post:
requestBody:
content:
application/unknown:
schema:
contentMediaType: application/octet-stream
/requestBody-contentEncoding:
post:
requestBody:
content:
application/unknown:
schema:
contentEncoding: base64
/requestBody-noSchema:
post:
requestBody:
content:
application/octet-stream: {}
/parameter-contentMediaType:
post:
parameters:
- in: query
name: file
schema:
type: string
contentMediaType: application/octet-stream
/parameter-contentEncoding:
post:
parameters:
- in: query
name: file
schema:
type: string
contentEncoding: base64
/property-contentMediaType:
post:
requestBody:
content:
multipart/form-data:
schema:
type: object
properties:
file:
type: string
contentMediaType: application/octet-stream
/property-contentEncoding:
post:
requestBody:
content:
multipart/form-data:
schema:
type: object
properties:
file:
type: string
contentEncoding: base64