feat: request snippets plugin (#6910)
This commit is contained in:
@@ -65,6 +65,8 @@ Parameter name | Docker variable | Description
|
|||||||
<a name="syntaxHighlight.activate"></a>`syntaxHighlight.activate` | _Unavailable_ | `Boolean=true`. Whether syntax highlighting should be activated or not.
|
<a name="syntaxHighlight.activate"></a>`syntaxHighlight.activate` | _Unavailable_ | `Boolean=true`. Whether syntax highlighting should be activated or not.
|
||||||
<a name="syntaxHighlight.theme"></a>`syntaxHighlight.theme` | _Unavailable_ | `String=["agate"*, "arta", "monokai", "nord", "obsidian", "tomorrow-night"]`. [Highlight.js](https://highlightjs.org/static/demo/) syntax coloring theme to use. (Only these 6 styles are available.)
|
<a name="syntaxHighlight.theme"></a>`syntaxHighlight.theme` | _Unavailable_ | `String=["agate"*, "arta", "monokai", "nord", "obsidian", "tomorrow-night"]`. [Highlight.js](https://highlightjs.org/static/demo/) syntax coloring theme to use. (Only these 6 styles are available.)
|
||||||
<a name="tryItOutEnabled"></a>`tryItOutEnabled` | `TRY_IT_OUT_ENABLED` | `Boolean=false`. Controls whether the "Try it out" section should be enabled by default.
|
<a name="tryItOutEnabled"></a>`tryItOutEnabled` | `TRY_IT_OUT_ENABLED` | `Boolean=false`. Controls whether the "Try it out" section should be enabled by default.
|
||||||
|
<a name="requestSnippets"></a>`requestSnippets` | _Unavailable_ | `Object`. This is the default configuration section for the the requestSnippets plugin.<br>requestSnippets: {<br> generators: {<br> "curl_bash": {<br> title: "cURL (bash)",<br> syntax: "bash"<br> },<br> "curl_powershell": {<br> title: "cURL (PowerShell)",<br> syntax: "powershell"<br> },<br> "curl_cmd": {<br> title: "cURL (CMD)",<br> syntax: "bash"<br> },<br> "node_native": {<br> title: "Node.js (Native)",<br> syntax: "javascript"<br> },<br> },<br> defaultExpanded: true,<br> languagesMask: null, // e.g. only show curl bash = \["curl_bash"\]<br>},
|
||||||
|
|
||||||
|
|
||||||
##### Network
|
##### Network
|
||||||
|
|
||||||
@@ -168,4 +170,4 @@ SPEC="{ \"openapi\": \"3.0.0\" }"
|
|||||||
```sh
|
```sh
|
||||||
SUPPORTED_SUBMIT_METHODS=['get', 'post']
|
SUPPORTED_SUBMIT_METHODS=['get', 'post']
|
||||||
URLS=[ { url: 'http://petstore.swagger.io/v2/swagger.json', name: 'Petstore' } ]
|
URLS=[ { url: 'http://petstore.swagger.io/v2/swagger.json', name: 'Petstore' } ]
|
||||||
```
|
```
|
||||||
|
|||||||
@@ -1,9 +1,9 @@
|
|||||||
import React from "react"
|
import React from "react"
|
||||||
import PropTypes from "prop-types"
|
import PropTypes from "prop-types"
|
||||||
import curlify from "core/curlify"
|
|
||||||
import { CopyToClipboard } from "react-copy-to-clipboard"
|
import { CopyToClipboard } from "react-copy-to-clipboard"
|
||||||
import {SyntaxHighlighter, getStyle} from "core/syntax-highlighting"
|
import {SyntaxHighlighter, getStyle} from "core/syntax-highlighting"
|
||||||
import get from "lodash/get"
|
import get from "lodash/get"
|
||||||
|
import { requestSnippetGenerator_curl_bash } from "../plugins/request-snippets/fn"
|
||||||
|
|
||||||
export default class Curl extends React.Component {
|
export default class Curl extends React.Component {
|
||||||
static propTypes = {
|
static propTypes = {
|
||||||
@@ -13,7 +13,7 @@ export default class Curl extends React.Component {
|
|||||||
|
|
||||||
render() {
|
render() {
|
||||||
let { request, getConfigs } = this.props
|
let { request, getConfigs } = this.props
|
||||||
let curl = curlify(request)
|
let curl = requestSnippetGenerator_curl_bash(request)
|
||||||
|
|
||||||
const config = getConfigs()
|
const config = getConfigs()
|
||||||
|
|
||||||
|
|||||||
@@ -49,7 +49,7 @@ export default class LiveResponse extends React.Component {
|
|||||||
|
|
||||||
render() {
|
render() {
|
||||||
const { response, getComponent, getConfigs, displayRequestDuration, specSelectors, path, method } = this.props
|
const { response, getComponent, getConfigs, displayRequestDuration, specSelectors, path, method } = this.props
|
||||||
const { showMutatedRequest } = getConfigs()
|
const { showMutatedRequest, requestSnippetsEnabled } = getConfigs()
|
||||||
|
|
||||||
const curlRequest = showMutatedRequest ? specSelectors.mutatedRequestFor(path, method) : specSelectors.requestFor(path, method)
|
const curlRequest = showMutatedRequest ? specSelectors.mutatedRequestFor(path, method) : specSelectors.requestFor(path, method)
|
||||||
const status = response.get("status")
|
const status = response.get("status")
|
||||||
@@ -62,7 +62,6 @@ export default class LiveResponse extends React.Component {
|
|||||||
const headersKeys = Object.keys(headers)
|
const headersKeys = Object.keys(headers)
|
||||||
const contentType = headers["content-type"] || headers["Content-Type"]
|
const contentType = headers["content-type"] || headers["Content-Type"]
|
||||||
|
|
||||||
const Curl = getComponent("curl")
|
|
||||||
const ResponseBody = getComponent("responseBody")
|
const ResponseBody = getComponent("responseBody")
|
||||||
const returnObject = headersKeys.map(key => {
|
const returnObject = headersKeys.map(key => {
|
||||||
var joinedHeaders = Array.isArray(headers[key]) ? headers[key].join() : headers[key]
|
var joinedHeaders = Array.isArray(headers[key]) ? headers[key].join() : headers[key]
|
||||||
@@ -70,10 +69,14 @@ export default class LiveResponse extends React.Component {
|
|||||||
})
|
})
|
||||||
const hasHeaders = returnObject.length !== 0
|
const hasHeaders = returnObject.length !== 0
|
||||||
const Markdown = getComponent("Markdown", true)
|
const Markdown = getComponent("Markdown", true)
|
||||||
|
const RequestSnippets = getComponent("RequestSnippets", true)
|
||||||
|
const Curl = getComponent("curl")
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div>
|
<div>
|
||||||
{ curlRequest && <Curl request={ curlRequest } getConfigs={ getConfigs } /> }
|
{ curlRequest && (requestSnippetsEnabled === true || requestSnippetsEnabled === "true"
|
||||||
|
? <RequestSnippets request={ curlRequest }/>
|
||||||
|
: <Curl request={ curlRequest } getConfigs={ getConfigs } />) }
|
||||||
{ url && <div>
|
{ url && <div>
|
||||||
<h4>Request URL</h4>
|
<h4>Request URL</h4>
|
||||||
<div className="request-url">
|
<div className="request-url">
|
||||||
|
|||||||
@@ -1,75 +0,0 @@
|
|||||||
import win from "./window"
|
|
||||||
import { Map } from "immutable"
|
|
||||||
|
|
||||||
/**
|
|
||||||
* if duplicate key name existed from FormData entries,
|
|
||||||
* we mutated the key name by appending a hashIdx
|
|
||||||
* @param {String} k - possibly mutated key name
|
|
||||||
* @return {String} - src key name
|
|
||||||
*/
|
|
||||||
const extractKey = (k) => {
|
|
||||||
const hashIdx = "_**[]"
|
|
||||||
if (k.indexOf(hashIdx) < 0) {
|
|
||||||
return k
|
|
||||||
}
|
|
||||||
return k.split(hashIdx)[0].trim()
|
|
||||||
}
|
|
||||||
|
|
||||||
export default function curl( request ){
|
|
||||||
let curlified = []
|
|
||||||
let isMultipartFormDataRequest = false
|
|
||||||
let headers = request.get("headers")
|
|
||||||
curlified.push( "curl" )
|
|
||||||
|
|
||||||
if (request.get("curlOptions")) {
|
|
||||||
curlified.push(...request.get("curlOptions"))
|
|
||||||
}
|
|
||||||
|
|
||||||
curlified.push( "-X", request.get("method") )
|
|
||||||
curlified.push( `"${request.get("url")}"`)
|
|
||||||
|
|
||||||
if ( headers && headers.size ) {
|
|
||||||
for( let p of request.get("headers").entries() ){
|
|
||||||
let [ h,v ] = p
|
|
||||||
curlified.push( "-H " )
|
|
||||||
curlified.push( `"${h}: ${v.replace(/\$/g, "\\$")}"` )
|
|
||||||
isMultipartFormDataRequest = isMultipartFormDataRequest || /^content-type$/i.test(h) && /^multipart\/form-data$/i.test(v)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if ( request.get("body") ){
|
|
||||||
if (isMultipartFormDataRequest && ["POST", "PUT", "PATCH"].includes(request.get("method"))) {
|
|
||||||
for( let [ k,v ] of request.get("body").entrySeq()) {
|
|
||||||
let extractedKey = extractKey(k)
|
|
||||||
curlified.push( "-F" )
|
|
||||||
if (v instanceof win.File) {
|
|
||||||
curlified.push(`"${extractedKey}=@${v.name}${v.type ? `;type=${v.type}` : ""}"` )
|
|
||||||
} else {
|
|
||||||
curlified.push(`"${extractedKey}=${v}"` )
|
|
||||||
}
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
curlified.push( "-d" )
|
|
||||||
let reqBody = request.get("body")
|
|
||||||
if (!Map.isMap(reqBody)) {
|
|
||||||
curlified.push( JSON.stringify( request.get("body") ).replace(/\\n/g, "").replace(/\$/g, "\\$") )
|
|
||||||
} else {
|
|
||||||
let curlifyToJoin = []
|
|
||||||
for (let [k, v] of request.get("body").entrySeq()) {
|
|
||||||
let extractedKey = extractKey(k)
|
|
||||||
if (v instanceof win.File) {
|
|
||||||
curlifyToJoin.push(`"${extractedKey}":{"name":"${v.name}"${v.type ? `,"type":"${v.type}"` : ""}}`)
|
|
||||||
} else {
|
|
||||||
curlifyToJoin.push(`"${extractedKey}":${JSON.stringify(v).replace(/\\n/g, "").replace("$", "\\$")}`)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
curlified.push(`{${curlifyToJoin.join()}}`)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
} else if(!request.get("body") && request.get("method") === "POST") {
|
|
||||||
curlified.push( "-d" )
|
|
||||||
curlified.push( "\"\"" )
|
|
||||||
}
|
|
||||||
|
|
||||||
return curlified.join( " " )
|
|
||||||
}
|
|
||||||
@@ -53,6 +53,29 @@ export default function SwaggerUI(opts) {
|
|||||||
showExtensions: false,
|
showExtensions: false,
|
||||||
showCommonExtensions: false,
|
showCommonExtensions: false,
|
||||||
withCredentials: undefined,
|
withCredentials: undefined,
|
||||||
|
requestSnippetsEnabled: false,
|
||||||
|
requestSnippets: {
|
||||||
|
generators: {
|
||||||
|
"curl_bash": {
|
||||||
|
title: "cURL (bash)",
|
||||||
|
syntax: "bash"
|
||||||
|
},
|
||||||
|
"curl_powershell": {
|
||||||
|
title: "cURL (PowerShell)",
|
||||||
|
syntax: "powershell"
|
||||||
|
},
|
||||||
|
"curl_cmd": {
|
||||||
|
title: "cURL (CMD)",
|
||||||
|
syntax: "bash"
|
||||||
|
},
|
||||||
|
"node_native": {
|
||||||
|
title: "Node.js (Native)",
|
||||||
|
syntax: "javascript"
|
||||||
|
},
|
||||||
|
},
|
||||||
|
defaultExpanded: true,
|
||||||
|
languagesMask: null, // e.g. only show curl bash = ["curl_bash"]
|
||||||
|
},
|
||||||
supportedSubmitMethods: [
|
supportedSubmitMethods: [
|
||||||
"get",
|
"get",
|
||||||
"put",
|
"put",
|
||||||
@@ -107,7 +130,8 @@ export default function SwaggerUI(opts) {
|
|||||||
spec: {
|
spec: {
|
||||||
spec: "",
|
spec: "",
|
||||||
url: constructorConfig.url
|
url: constructorConfig.url
|
||||||
}
|
},
|
||||||
|
requestSnippets: constructorConfig.requestSnippets
|
||||||
}, constructorConfig.initialState)
|
}, constructorConfig.initialState)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
217
src/core/plugins/request-snippets/fn.js
Normal file
217
src/core/plugins/request-snippets/fn.js
Normal file
@@ -0,0 +1,217 @@
|
|||||||
|
import win from "../../window"
|
||||||
|
import { Map } from "immutable"
|
||||||
|
import Url from "url-parse"
|
||||||
|
|
||||||
|
/**
|
||||||
|
* if duplicate key name existed from FormData entries,
|
||||||
|
* we mutated the key name by appending a hashIdx
|
||||||
|
* @param {String} k - possibly mutated key name
|
||||||
|
* @return {String} - src key name
|
||||||
|
*/
|
||||||
|
const extractKey = (k) => {
|
||||||
|
const hashIdx = "_**[]"
|
||||||
|
if (k.indexOf(hashIdx) < 0) {
|
||||||
|
return k
|
||||||
|
}
|
||||||
|
return k.split(hashIdx)[0].trim()
|
||||||
|
}
|
||||||
|
|
||||||
|
const escapeShell = (str) => {
|
||||||
|
if (str === "-d ") {
|
||||||
|
return str
|
||||||
|
}
|
||||||
|
// eslint-disable-next-line no-useless-escape
|
||||||
|
if (!/^[_\/-]/g.test(str))
|
||||||
|
return ("'" + str
|
||||||
|
.replace(/'/g, "'\\''") + "'")
|
||||||
|
else
|
||||||
|
return str
|
||||||
|
}
|
||||||
|
|
||||||
|
const escapeCMD = (str) => {
|
||||||
|
str = str
|
||||||
|
.replace(/\^/g, "^^")
|
||||||
|
.replace(/\\"/g, "\\\\\"")
|
||||||
|
.replace(/"/g, "\"\"")
|
||||||
|
.replace(/\n/g, "^\n")
|
||||||
|
if (str === "-d ") {
|
||||||
|
return str
|
||||||
|
.replace(/-d /g, "-d ^\n")
|
||||||
|
}
|
||||||
|
// eslint-disable-next-line no-useless-escape
|
||||||
|
if (!/^[_\/-]/g.test(str))
|
||||||
|
return "\"" + str + "\""
|
||||||
|
else
|
||||||
|
return str
|
||||||
|
}
|
||||||
|
|
||||||
|
const escapePowershell = (str) => {
|
||||||
|
if (str === "-d ") {
|
||||||
|
return str
|
||||||
|
}
|
||||||
|
if (/\n/.test(str)) {
|
||||||
|
return "@\"\n" + str.replace(/"/g, "\\\"").replace(/`/g, "``").replace(/\$/, "`$") + "\n\"@"
|
||||||
|
}
|
||||||
|
// eslint-disable-next-line no-useless-escape
|
||||||
|
if (!/^[_\/-]/g.test(str))
|
||||||
|
return "'" + str
|
||||||
|
.replace(/"/g, "\"\"")
|
||||||
|
.replace(/'/g, "''") + "'"
|
||||||
|
else
|
||||||
|
return str
|
||||||
|
}
|
||||||
|
|
||||||
|
function getStringBodyOfMap(request) {
|
||||||
|
let curlifyToJoin = []
|
||||||
|
for (let [k, v] of request.get("body").entrySeq()) {
|
||||||
|
let extractedKey = extractKey(k)
|
||||||
|
if (v instanceof win.File) {
|
||||||
|
curlifyToJoin.push(` "${extractedKey}": {\n "name": "${v.name}"${v.type ? `,\n "type": "${v.type}"` : ""}\n }`)
|
||||||
|
} else {
|
||||||
|
curlifyToJoin.push(` "${extractedKey}": ${JSON.stringify(v, null, 2).replace(/(\r\n|\r|\n)/g, "\n ")}`)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return `{\n${curlifyToJoin.join(",\n")}\n}`
|
||||||
|
}
|
||||||
|
|
||||||
|
const curlify = (request, escape, newLine, ext = "") => {
|
||||||
|
let isMultipartFormDataRequest = false
|
||||||
|
let curlified = ""
|
||||||
|
const addWords = (...args) => curlified += " " + args.map(escape).join(" ")
|
||||||
|
const addWordsWithoutLeadingSpace = (...args) => curlified += args.map(escape).join(" ")
|
||||||
|
const addNewLine = () => curlified += ` ${newLine}`
|
||||||
|
const addIndent = (level = 1) => curlified += " ".repeat(level)
|
||||||
|
let headers = request.get("headers")
|
||||||
|
curlified += "curl" + ext
|
||||||
|
|
||||||
|
if (request.has("curlOptions")) {
|
||||||
|
addWords(...request.get("curlOptions"))
|
||||||
|
}
|
||||||
|
|
||||||
|
addWords("-X", request.get("method"))
|
||||||
|
|
||||||
|
addNewLine()
|
||||||
|
addIndent()
|
||||||
|
addWordsWithoutLeadingSpace(`${request.get("url")}`)
|
||||||
|
|
||||||
|
if (headers && headers.size) {
|
||||||
|
for (let p of request.get("headers").entries()) {
|
||||||
|
addNewLine()
|
||||||
|
addIndent()
|
||||||
|
let [h, v] = p
|
||||||
|
addWordsWithoutLeadingSpace("-H", `${h}: ${v}`)
|
||||||
|
isMultipartFormDataRequest = isMultipartFormDataRequest || /^content-type$/i.test(h) && /^multipart\/form-data$/i.test(v)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (request.get("body")) {
|
||||||
|
if (isMultipartFormDataRequest && ["POST", "PUT", "PATCH"].includes(request.get("method"))) {
|
||||||
|
for (let [k, v] of request.get("body").entrySeq()) {
|
||||||
|
let extractedKey = extractKey(k)
|
||||||
|
addNewLine()
|
||||||
|
addIndent()
|
||||||
|
addWordsWithoutLeadingSpace("-F")
|
||||||
|
if (v instanceof win.File) {
|
||||||
|
addWords(`${extractedKey}=@${v.name}${v.type ? `;type=${v.type}` : ""}`)
|
||||||
|
} else {
|
||||||
|
addWords(`${extractedKey}=${v}`)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
addNewLine()
|
||||||
|
addIndent()
|
||||||
|
addWordsWithoutLeadingSpace("-d ")
|
||||||
|
let reqBody = request.get("body")
|
||||||
|
if (!Map.isMap(reqBody)) {
|
||||||
|
if (typeof reqBody !== "string") {
|
||||||
|
reqBody = JSON.stringify(reqBody)
|
||||||
|
}
|
||||||
|
addWordsWithoutLeadingSpace(reqBody)
|
||||||
|
} else {
|
||||||
|
addWordsWithoutLeadingSpace(getStringBodyOfMap(request))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} else if (!request.get("body") && request.get("method") === "POST") {
|
||||||
|
addNewLine()
|
||||||
|
addIndent()
|
||||||
|
addWordsWithoutLeadingSpace("-d ''")
|
||||||
|
}
|
||||||
|
|
||||||
|
return curlified
|
||||||
|
}
|
||||||
|
|
||||||
|
// eslint-disable-next-line camelcase
|
||||||
|
export const requestSnippetGenerator_curl_powershell = (request) => {
|
||||||
|
return curlify(request, escapePowershell, "`\n", ".exe")
|
||||||
|
}
|
||||||
|
|
||||||
|
// eslint-disable-next-line camelcase
|
||||||
|
export const requestSnippetGenerator_curl_bash = (request) => {
|
||||||
|
return curlify(request, escapeShell, "\\\n")
|
||||||
|
}
|
||||||
|
|
||||||
|
// eslint-disable-next-line camelcase
|
||||||
|
export const requestSnippetGenerator_curl_cmd = (request) => {
|
||||||
|
return curlify(request, escapeCMD, "^\n")
|
||||||
|
}
|
||||||
|
|
||||||
|
// eslint-disable-next-line camelcase
|
||||||
|
export const requestSnippetGenerator_node_native = (request) => {
|
||||||
|
const url = new Url(request.get("url"))
|
||||||
|
let isMultipartFormDataRequest = false
|
||||||
|
const headers = request.get("headers")
|
||||||
|
if(headers && headers.size) {
|
||||||
|
request.get("headers").map((val, key) => {
|
||||||
|
isMultipartFormDataRequest = isMultipartFormDataRequest || /^content-type$/i.test(key) && /^multipart\/form-data$/i.test(val)
|
||||||
|
})
|
||||||
|
}
|
||||||
|
const packageStr = url.protocol === "https:" ? "https" : "http"
|
||||||
|
let reqBody = request.get("body")
|
||||||
|
if (request.get("body")) {
|
||||||
|
if (isMultipartFormDataRequest && ["POST", "PUT", "PATCH"].includes(request.get("method"))) {
|
||||||
|
return "throw new Error(\"Currently unsupported content-type: /^multipart\\/form-data$/i\");"
|
||||||
|
} else {
|
||||||
|
if (!Map.isMap(reqBody)) {
|
||||||
|
if (typeof reqBody !== "string") {
|
||||||
|
reqBody = JSON.stringify(reqBody)
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
reqBody = getStringBodyOfMap(request)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} else if (!request.get("body") && request.get("method") === "POST") {
|
||||||
|
reqBody = ""
|
||||||
|
}
|
||||||
|
|
||||||
|
const stringBody = "`" + (reqBody || "")
|
||||||
|
.replace(/\\n/g, "\n")
|
||||||
|
.replace(/`/g, "\\`")
|
||||||
|
+ "`"
|
||||||
|
|
||||||
|
return `const http = require("${packageStr}");
|
||||||
|
|
||||||
|
const options = {
|
||||||
|
"method": "${request.get("method")}",
|
||||||
|
"hostname": "${url.host}",
|
||||||
|
"port": ${url.port || "null"},
|
||||||
|
"path": "${url.pathname}"${headers && headers.size ? `,
|
||||||
|
"headers": {
|
||||||
|
${request.get("headers").map((val, key) => `"${key}": "${val}"`).valueSeq().join(",\n ")}
|
||||||
|
}` : ""}
|
||||||
|
};
|
||||||
|
|
||||||
|
const req = http.request(options, function (res) {
|
||||||
|
const chunks = [];
|
||||||
|
|
||||||
|
res.on("data", function (chunk) {
|
||||||
|
chunks.push(chunk);
|
||||||
|
});
|
||||||
|
|
||||||
|
res.on("end", function () {
|
||||||
|
const body = Buffer.concat(chunks);
|
||||||
|
console.log(body.toString());
|
||||||
|
});
|
||||||
|
});
|
||||||
|
${reqBody ? `\nreq.write(${stringBody});` : ""}
|
||||||
|
req.end();`
|
||||||
|
}
|
||||||
16
src/core/plugins/request-snippets/index.js
Normal file
16
src/core/plugins/request-snippets/index.js
Normal file
@@ -0,0 +1,16 @@
|
|||||||
|
import * as fn from "./fn"
|
||||||
|
import * as selectors from "./selectors"
|
||||||
|
import { RequestSnippets } from "./request-snippets"
|
||||||
|
export default () => {
|
||||||
|
return {
|
||||||
|
components: {
|
||||||
|
RequestSnippets
|
||||||
|
},
|
||||||
|
fn,
|
||||||
|
statePlugins: {
|
||||||
|
requestSnippets: {
|
||||||
|
selectors
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
127
src/core/plugins/request-snippets/request-snippets.jsx
Normal file
127
src/core/plugins/request-snippets/request-snippets.jsx
Normal file
@@ -0,0 +1,127 @@
|
|||||||
|
import React from "react"
|
||||||
|
import { CopyToClipboard } from "react-copy-to-clipboard"
|
||||||
|
import PropTypes from "prop-types"
|
||||||
|
import get from "lodash/get"
|
||||||
|
import {SyntaxHighlighter, getStyle} from "core/syntax-highlighting"
|
||||||
|
|
||||||
|
export class RequestSnippets extends React.Component {
|
||||||
|
constructor() {
|
||||||
|
super()
|
||||||
|
this.state = {
|
||||||
|
activeLanguage: this.props?.requestSnippetsSelectors?.getSnippetGenerators()?.keySeq().first(),
|
||||||
|
expanded: this.props?.requestSnippetsSelectors?.getDefaultExpanded(),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static propTypes = {
|
||||||
|
request: PropTypes.object.isRequired,
|
||||||
|
requestSnippetsSelectors: PropTypes.object.isRequired,
|
||||||
|
getConfigs: PropTypes.object.isRequired,
|
||||||
|
requestSnippetsActions: PropTypes.object.isRequired,
|
||||||
|
}
|
||||||
|
render() {
|
||||||
|
const {request, getConfigs, requestSnippetsSelectors } = this.props
|
||||||
|
const snippetGenerators = requestSnippetsSelectors.getSnippetGenerators()
|
||||||
|
const activeLanguage = this.state.activeLanguage || snippetGenerators.keySeq().first()
|
||||||
|
const activeGenerator = snippetGenerators.get(activeLanguage)
|
||||||
|
const snippet = activeGenerator.get("fn")(request)
|
||||||
|
const onGenChange = (key) => {
|
||||||
|
const needsChange = activeLanguage !== key
|
||||||
|
if(needsChange) {
|
||||||
|
this.setState({
|
||||||
|
activeLanguage: key
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
||||||
|
const style = {
|
||||||
|
cursor: "pointer",
|
||||||
|
lineHeight: 1,
|
||||||
|
display: "inline-flex",
|
||||||
|
backgroundColor: "rgb(250, 250, 250)",
|
||||||
|
paddingBottom: "0",
|
||||||
|
paddingTop: "0",
|
||||||
|
border: "1px solid rgb(51, 51, 51)",
|
||||||
|
borderRadius: "4px 4px 0 0",
|
||||||
|
boxShadow: "none",
|
||||||
|
borderBottom: "none"
|
||||||
|
}
|
||||||
|
const activeStyle = {
|
||||||
|
cursor: "pointer",
|
||||||
|
lineHeight: 1,
|
||||||
|
display: "inline-flex",
|
||||||
|
backgroundColor: "rgb(51, 51, 51)",
|
||||||
|
boxShadow: "none",
|
||||||
|
border: "1px solid rgb(51, 51, 51)",
|
||||||
|
paddingBottom: "0",
|
||||||
|
paddingTop: "0",
|
||||||
|
borderRadius: "4px 4px 0 0",
|
||||||
|
marginTop: "-5px",
|
||||||
|
marginRight: "-5px",
|
||||||
|
marginLeft: "-5px",
|
||||||
|
zIndex: "9999",
|
||||||
|
borderBottom: "none"
|
||||||
|
}
|
||||||
|
const getBtnStyle = (key) => {
|
||||||
|
if (key === activeLanguage) {
|
||||||
|
return activeStyle
|
||||||
|
}
|
||||||
|
return style
|
||||||
|
}
|
||||||
|
const config = getConfigs()
|
||||||
|
|
||||||
|
const SnippetComponent = config?.syntaxHighlight?.activated
|
||||||
|
? <SyntaxHighlighter
|
||||||
|
language={activeGenerator.get("syntax")}
|
||||||
|
className="curl microlight"
|
||||||
|
onWheel={function(e) {return this.preventYScrollingBeyondElement(e)}}
|
||||||
|
style={getStyle(get(config, "syntaxHighlight.theme"))}
|
||||||
|
>
|
||||||
|
{snippet}
|
||||||
|
</SyntaxHighlighter>
|
||||||
|
:
|
||||||
|
<textarea readOnly={true} className="curl" value={snippet}></textarea>
|
||||||
|
|
||||||
|
const expanded = this.state.expanded === undefined ? this.props?.requestSnippetsSelectors?.getDefaultExpanded() : this.state.expanded
|
||||||
|
return (
|
||||||
|
<div>
|
||||||
|
<div style={{width: "100%", display: "flex", justifyContent: "flex-start", alignItems: "center", marginBottom: "15px"}}>
|
||||||
|
<h4
|
||||||
|
style={{ cursor: "pointer" }}
|
||||||
|
onClick={() => this.setState({expanded: !expanded})}
|
||||||
|
>Snippets</h4>
|
||||||
|
<button
|
||||||
|
onClick={() => this.setState({expanded: !expanded})}
|
||||||
|
style={{ border: "none", background: "none" }}
|
||||||
|
title={expanded ? "Collapse operation": "Expand operation"}
|
||||||
|
>
|
||||||
|
<svg className="arrow" width="10" height="10">
|
||||||
|
<use href={expanded ? "#large-arrow-down" : "#large-arrow"} xlinkHref={expanded ? "#large-arrow-down" : "#large-arrow"} />
|
||||||
|
</svg>
|
||||||
|
</button>
|
||||||
|
</div>
|
||||||
|
{
|
||||||
|
expanded && <div className="curl-command">
|
||||||
|
<div style={{paddingLeft: "15px", paddingRight: "10px", width: "100%", display: "flex"}}>
|
||||||
|
{
|
||||||
|
snippetGenerators.map((gen, key) => {
|
||||||
|
return (<div style={getBtnStyle(key)} className="btn" key={key} onClick={() => onGenChange(key)}>
|
||||||
|
<h4 style={key === activeLanguage ? {color: "white",} : {}}>{gen.get("title")}</h4>
|
||||||
|
</div>)
|
||||||
|
})
|
||||||
|
}
|
||||||
|
</div>
|
||||||
|
<div className="copy-to-clipboard">
|
||||||
|
<CopyToClipboard text={snippet}>
|
||||||
|
<button />
|
||||||
|
</CopyToClipboard>
|
||||||
|
</div>
|
||||||
|
<div>
|
||||||
|
{SnippetComponent}
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
}
|
||||||
|
</div>
|
||||||
|
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
||||||
45
src/core/plugins/request-snippets/selectors.js
Normal file
45
src/core/plugins/request-snippets/selectors.js
Normal file
@@ -0,0 +1,45 @@
|
|||||||
|
import { createSelector } from "reselect"
|
||||||
|
import { Map } from "immutable"
|
||||||
|
|
||||||
|
const state = state => state || Map()
|
||||||
|
|
||||||
|
export const getGenerators = createSelector(
|
||||||
|
state,
|
||||||
|
state => {
|
||||||
|
const languageKeys = state
|
||||||
|
.get("languages")
|
||||||
|
const generators = state
|
||||||
|
.get("generators", Map())
|
||||||
|
if(!languageKeys) {
|
||||||
|
return generators
|
||||||
|
}
|
||||||
|
return generators
|
||||||
|
.filter((v, key) => languageKeys.includes(key))
|
||||||
|
}
|
||||||
|
)
|
||||||
|
|
||||||
|
export const getSnippetGenerators = (state) => ({ fn }) => {
|
||||||
|
const getGenFn = (key) => fn[`requestSnippetGenerator_${key}`]
|
||||||
|
return getGenerators(state)
|
||||||
|
.map((gen, key) => {
|
||||||
|
const genFn = getGenFn(key)
|
||||||
|
if(typeof genFn !== "function") {
|
||||||
|
return null
|
||||||
|
}
|
||||||
|
|
||||||
|
return gen.set("fn", genFn)
|
||||||
|
})
|
||||||
|
.filter(v => v)
|
||||||
|
}
|
||||||
|
|
||||||
|
export const getActiveLanguage = createSelector(
|
||||||
|
state,
|
||||||
|
state => state
|
||||||
|
.get("activeLanguage")
|
||||||
|
)
|
||||||
|
|
||||||
|
export const getDefaultExpanded = createSelector(
|
||||||
|
state,
|
||||||
|
state => state
|
||||||
|
.get("defaultExpanded")
|
||||||
|
)
|
||||||
@@ -5,7 +5,7 @@ import serializeError from "serialize-error"
|
|||||||
import isString from "lodash/isString"
|
import isString from "lodash/isString"
|
||||||
import debounce from "lodash/debounce"
|
import debounce from "lodash/debounce"
|
||||||
import set from "lodash/set"
|
import set from "lodash/set"
|
||||||
import { isJSONObject, paramToValue, isEmptyValue } from "core/utils"
|
import { paramToValue, isEmptyValue } from "core/utils"
|
||||||
|
|
||||||
// Actions conform to FSA (flux-standard-actions)
|
// Actions conform to FSA (flux-standard-actions)
|
||||||
// {type: string,payload: Any|Error, meta: obj, error: bool}
|
// {type: string,payload: Any|Error, meta: obj, error: bool}
|
||||||
@@ -426,9 +426,7 @@ export const executeRequest = (req) =>
|
|||||||
const requestBody = oas3Selectors.requestBodyValue(pathName, method)
|
const requestBody = oas3Selectors.requestBodyValue(pathName, method)
|
||||||
const requestBodyInclusionSetting = oas3Selectors.requestBodyInclusionSetting(pathName, method)
|
const requestBodyInclusionSetting = oas3Selectors.requestBodyInclusionSetting(pathName, method)
|
||||||
|
|
||||||
if(isJSONObject(requestBody)) {
|
if(requestBody && requestBody.toJS) {
|
||||||
req.requestBody = JSON.parse(requestBody)
|
|
||||||
} else if(requestBody && requestBody.toJS) {
|
|
||||||
req.requestBody = requestBody
|
req.requestBody = requestBody
|
||||||
.map(
|
.map(
|
||||||
(val) => {
|
(val) => {
|
||||||
@@ -445,7 +443,7 @@ export const executeRequest = (req) =>
|
|||||||
) || requestBodyInclusionSetting.get(key)
|
) || requestBodyInclusionSetting.get(key)
|
||||||
)
|
)
|
||||||
.toJS()
|
.toJS()
|
||||||
} else{
|
} else {
|
||||||
req.requestBody = requestBody
|
req.requestBody = requestBody
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -3,6 +3,7 @@ import layout from "core/plugins/layout"
|
|||||||
import spec from "core/plugins/spec"
|
import spec from "core/plugins/spec"
|
||||||
import view from "core/plugins/view"
|
import view from "core/plugins/view"
|
||||||
import samples from "core/plugins/samples"
|
import samples from "core/plugins/samples"
|
||||||
|
import requestSnippets from "core/plugins/request-snippets"
|
||||||
import logs from "core/plugins/logs"
|
import logs from "core/plugins/logs"
|
||||||
import swaggerJs from "core/plugins/swagger-js"
|
import swaggerJs from "core/plugins/swagger-js"
|
||||||
import auth from "core/plugins/auth"
|
import auth from "core/plugins/auth"
|
||||||
@@ -191,6 +192,7 @@ export default function() {
|
|||||||
downloadUrlPlugin,
|
downloadUrlPlugin,
|
||||||
deepLinkingPlugin,
|
deepLinkingPlugin,
|
||||||
filter,
|
filter,
|
||||||
onComplete
|
onComplete,
|
||||||
|
requestSnippets
|
||||||
]
|
]
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -6,6 +6,8 @@ import xml from "react-syntax-highlighter/dist/esm/languages/hljs/xml"
|
|||||||
import bash from "react-syntax-highlighter/dist/esm/languages/hljs/bash"
|
import bash from "react-syntax-highlighter/dist/esm/languages/hljs/bash"
|
||||||
import yaml from "react-syntax-highlighter/dist/esm/languages/hljs/yaml"
|
import yaml from "react-syntax-highlighter/dist/esm/languages/hljs/yaml"
|
||||||
import http from "react-syntax-highlighter/dist/esm/languages/hljs/http"
|
import http from "react-syntax-highlighter/dist/esm/languages/hljs/http"
|
||||||
|
import powershell from "react-syntax-highlighter/dist/esm/languages/hljs/powershell"
|
||||||
|
import javascript from "react-syntax-highlighter/dist/esm/languages/hljs/javascript"
|
||||||
|
|
||||||
import agate from "react-syntax-highlighter/dist/esm/styles/hljs/agate"
|
import agate from "react-syntax-highlighter/dist/esm/styles/hljs/agate"
|
||||||
import arta from "react-syntax-highlighter/dist/esm/styles/hljs/arta"
|
import arta from "react-syntax-highlighter/dist/esm/styles/hljs/arta"
|
||||||
@@ -20,6 +22,8 @@ SyntaxHighlighter.registerLanguage("xml", xml)
|
|||||||
SyntaxHighlighter.registerLanguage("yaml", yaml)
|
SyntaxHighlighter.registerLanguage("yaml", yaml)
|
||||||
SyntaxHighlighter.registerLanguage("http", http)
|
SyntaxHighlighter.registerLanguage("http", http)
|
||||||
SyntaxHighlighter.registerLanguage("bash", bash)
|
SyntaxHighlighter.registerLanguage("bash", bash)
|
||||||
|
SyntaxHighlighter.registerLanguage("powershell", powershell)
|
||||||
|
SyntaxHighlighter.registerLanguage("javascript", javascript)
|
||||||
|
|
||||||
const styles = {agate, arta, monokai, nord, obsidian, "tomorrow-night": tomorrowNight}
|
const styles = {agate, arta, monokai, nord, obsidian, "tomorrow-night": tomorrowNight}
|
||||||
export const availableStyles = Object.keys(styles)
|
export const availableStyles = Object.keys(styles)
|
||||||
|
|||||||
@@ -32,25 +32,6 @@ const DEFAULT_RESPONSE_KEY = "default"
|
|||||||
|
|
||||||
export const isImmutable = (maybe) => Im.Iterable.isIterable(maybe)
|
export const isImmutable = (maybe) => Im.Iterable.isIterable(maybe)
|
||||||
|
|
||||||
export function isJSONObject (str) {
|
|
||||||
try {
|
|
||||||
var o = JSON.parse(str)
|
|
||||||
|
|
||||||
// Handle non-exception-throwing cases:
|
|
||||||
// Neither JSON.parse(false) or JSON.parse(1234) throw errors, hence the type-checking,
|
|
||||||
// but... JSON.parse(null) returns null, and typeof null === "object",
|
|
||||||
// so we must check for that, too. Thankfully, null is falsey, so this suffices:
|
|
||||||
if (o && typeof o === "object") {
|
|
||||||
return o
|
|
||||||
}
|
|
||||||
}
|
|
||||||
catch (e) {
|
|
||||||
// do nothing
|
|
||||||
}
|
|
||||||
|
|
||||||
return false
|
|
||||||
}
|
|
||||||
|
|
||||||
export function objectify (thing) {
|
export function objectify (thing) {
|
||||||
if(!isObject(thing))
|
if(!isObject(thing))
|
||||||
return {}
|
return {}
|
||||||
|
|||||||
@@ -208,7 +208,7 @@ function RequestBodyPrimitiveTestCases({
|
|||||||
// Assert on the curl body
|
// Assert on the curl body
|
||||||
// TODO: use an interceptor instead of curl
|
// TODO: use an interceptor instead of curl
|
||||||
.get(".curl")
|
.get(".curl")
|
||||||
.contains(`-d "${exampleA.serializedValue || exampleA.value}"`)
|
.contains(`-d '${exampleA.serializedValue || exampleA.value}'`)
|
||||||
})
|
})
|
||||||
|
|
||||||
it("should set default static and Try-It-Out values based on choosing the second member in static mode", () => {
|
it("should set default static and Try-It-Out values based on choosing the second member in static mode", () => {
|
||||||
@@ -234,7 +234,7 @@ function RequestBodyPrimitiveTestCases({
|
|||||||
// Assert on the request URL
|
// Assert on the request URL
|
||||||
// TODO: use an interceptor instead of curl
|
// TODO: use an interceptor instead of curl
|
||||||
.get(".curl")
|
.get(".curl")
|
||||||
.contains(`-d "${exampleB.serializedValue || exampleB.value}"`)
|
.contains(`-d '${exampleB.serializedValue || exampleB.value}'`)
|
||||||
})
|
})
|
||||||
|
|
||||||
it("should set default static and Try-It-Out values based on choosing the second member in Try-It-Out mode", () => {
|
it("should set default static and Try-It-Out values based on choosing the second member in Try-It-Out mode", () => {
|
||||||
@@ -257,7 +257,7 @@ function RequestBodyPrimitiveTestCases({
|
|||||||
// Assert on the request URL
|
// Assert on the request URL
|
||||||
// TODO: use an interceptor instead of curl
|
// TODO: use an interceptor instead of curl
|
||||||
.get(".curl")
|
.get(".curl")
|
||||||
.contains(`-d "${exampleB.serializedValue || exampleB.value}"`)
|
.contains(`-d '${exampleB.serializedValue || exampleB.value}'`)
|
||||||
// Switch to static docs
|
// Switch to static docs
|
||||||
.get(".try-out__btn")
|
.get(".try-out__btn")
|
||||||
.click()
|
.click()
|
||||||
@@ -323,7 +323,7 @@ function RequestBodyPrimitiveTestCases({
|
|||||||
// Assert on the request URL
|
// Assert on the request URL
|
||||||
// TODO: use an interceptor instead of curl
|
// TODO: use an interceptor instead of curl
|
||||||
.get(".curl")
|
.get(".curl")
|
||||||
.contains(`-d "${exampleB.serializedValue || exampleB.value}"`)
|
.contains(`-d '${exampleB.serializedValue || exampleB.value}'`)
|
||||||
})
|
})
|
||||||
|
|
||||||
it("should use the first example for the media type when changing the media type without prior interactions with the value", () => {
|
it("should use the first example for the media type when changing the media type without prior interactions with the value", () => {
|
||||||
@@ -349,7 +349,7 @@ function RequestBodyPrimitiveTestCases({
|
|||||||
// Assert on the request URL
|
// Assert on the request URL
|
||||||
// TODO: use an interceptor instead of curl
|
// TODO: use an interceptor instead of curl
|
||||||
.get(".curl")
|
.get(".curl")
|
||||||
.contains(`-d "${exampleA.serializedValue || exampleA.value}"`)
|
.contains(`-d '${exampleA.serializedValue || exampleA.value}'`)
|
||||||
})
|
})
|
||||||
|
|
||||||
it("static mode toggling: mediaType -> example -> mediaType -> example", () => {
|
it("static mode toggling: mediaType -> example -> mediaType -> example", () => {
|
||||||
@@ -489,7 +489,7 @@ function RequestBodyPrimitiveTestCases({
|
|||||||
// TODO: use an interceptor instead of curl
|
// TODO: use an interceptor instead of curl
|
||||||
.get(".curl")
|
.get(".curl")
|
||||||
.contains(
|
.contains(
|
||||||
`-d "${customUserInputExpectedCurlSubstring || customUserInput}"`
|
`-d '${customUserInputExpectedCurlSubstring || customUserInput}'`
|
||||||
)
|
)
|
||||||
|
|
||||||
// Choose exampleB
|
// Choose exampleB
|
||||||
@@ -508,7 +508,7 @@ function RequestBodyPrimitiveTestCases({
|
|||||||
// Assert on the curl body
|
// Assert on the curl body
|
||||||
// TODO: use an interceptor instead of curl
|
// TODO: use an interceptor instead of curl
|
||||||
.get(".curl")
|
.get(".curl")
|
||||||
.contains(`-d "${exampleB.serializedValue || exampleB.value}"`)
|
.contains(`-d '${exampleB.serializedValue || exampleB.value}'`)
|
||||||
|
|
||||||
// Ensure the modified value is still accessible
|
// Ensure the modified value is still accessible
|
||||||
.get(".opblock-section-request-body .examples-select > select")
|
.get(".opblock-section-request-body .examples-select > select")
|
||||||
@@ -530,7 +530,7 @@ function RequestBodyPrimitiveTestCases({
|
|||||||
// Assert on the curl body
|
// Assert on the curl body
|
||||||
// TODO: use an interceptor instead of curl
|
// TODO: use an interceptor instead of curl
|
||||||
.get(".curl")
|
.get(".curl")
|
||||||
.contains(`-d "${exampleB.serializedValue || exampleB.value}"`)
|
.contains(`-d '${exampleB.serializedValue || exampleB.value}'`)
|
||||||
|
|
||||||
// Ensure the modified value is still accessible
|
// Ensure the modified value is still accessible
|
||||||
.get(".opblock-section-request-body .examples-select > select")
|
.get(".opblock-section-request-body .examples-select > select")
|
||||||
@@ -552,7 +552,7 @@ function RequestBodyPrimitiveTestCases({
|
|||||||
// Assert on the curl body
|
// Assert on the curl body
|
||||||
// TODO: use an interceptor instead of curl
|
// TODO: use an interceptor instead of curl
|
||||||
.get(".curl")
|
.get(".curl")
|
||||||
.contains(`-d "${exampleA.serializedValue || exampleA.value}"`)
|
.contains(`-d '${exampleA.serializedValue || exampleA.value}'`)
|
||||||
|
|
||||||
// Ensure the modified value is still the same value
|
// Ensure the modified value is still the same value
|
||||||
.get(".opblock-section-request-body .examples-select > select")
|
.get(".opblock-section-request-body .examples-select > select")
|
||||||
@@ -571,7 +571,7 @@ function RequestBodyPrimitiveTestCases({
|
|||||||
// TODO: use an interceptor instead of curl
|
// TODO: use an interceptor instead of curl
|
||||||
.get(".curl")
|
.get(".curl")
|
||||||
.contains(
|
.contains(
|
||||||
`-d "${customUserInputExpectedCurlSubstring || customUserInput}"`
|
`-d '${customUserInputExpectedCurlSubstring || customUserInput}'`
|
||||||
)
|
)
|
||||||
})
|
})
|
||||||
|
|
||||||
|
|||||||
@@ -2,7 +2,7 @@
|
|||||||
* @prettier
|
* @prettier
|
||||||
*/
|
*/
|
||||||
|
|
||||||
const {
|
const {
|
||||||
ParameterPrimitiveTestCases,
|
ParameterPrimitiveTestCases,
|
||||||
RequestBodyPrimitiveTestCases,
|
RequestBodyPrimitiveTestCases,
|
||||||
ResponsePrimitiveTestCases,
|
ResponsePrimitiveTestCases,
|
||||||
@@ -256,7 +256,7 @@ describe("OpenAPI 3.0 Multiple Examples - core features", () => {
|
|||||||
.get("#operations-default-post_Array")
|
.get("#operations-default-post_Array")
|
||||||
.click()
|
.click()
|
||||||
.get(".json-schema-form-item > input")
|
.get(".json-schema-form-item > input")
|
||||||
.then(inputs => {
|
.then((inputs) => {
|
||||||
expect(inputs.map((i, el) => el.value).toArray()).to.deep.equal([
|
expect(inputs.map((i, el) => el.value).toArray()).to.deep.equal([
|
||||||
"a",
|
"a",
|
||||||
"b",
|
"b",
|
||||||
@@ -276,7 +276,7 @@ describe("OpenAPI 3.0 Multiple Examples - core features", () => {
|
|||||||
.get(".parameters-col_description .examples-select > select")
|
.get(".parameters-col_description .examples-select > select")
|
||||||
.select("ArrayExampleB")
|
.select("ArrayExampleB")
|
||||||
.get(".json-schema-form-item > input")
|
.get(".json-schema-form-item > input")
|
||||||
.then(inputs => {
|
.then((inputs) => {
|
||||||
expect(inputs.map((i, el) => el.value).toArray()).to.deep.equal([
|
expect(inputs.map((i, el) => el.value).toArray()).to.deep.equal([
|
||||||
"1",
|
"1",
|
||||||
"2",
|
"2",
|
||||||
@@ -317,7 +317,7 @@ describe("OpenAPI 3.0 Multiple Examples - core features", () => {
|
|||||||
.type("5")
|
.type("5")
|
||||||
// Assert against the input fields
|
// Assert against the input fields
|
||||||
.get(".json-schema-form-item > input")
|
.get(".json-schema-form-item > input")
|
||||||
.then(inputs => {
|
.then((inputs) => {
|
||||||
expect(inputs.map((i, el) => el.value).toArray()).to.deep.equal([
|
expect(inputs.map((i, el) => el.value).toArray()).to.deep.equal([
|
||||||
"1",
|
"1",
|
||||||
"2",
|
"2",
|
||||||
@@ -351,7 +351,7 @@ describe("OpenAPI 3.0 Multiple Examples - core features", () => {
|
|||||||
.select("ArrayExampleB")
|
.select("ArrayExampleB")
|
||||||
// Assert against the input fields
|
// Assert against the input fields
|
||||||
.get(".json-schema-form-item > input")
|
.get(".json-schema-form-item > input")
|
||||||
.then(inputs => {
|
.then((inputs) => {
|
||||||
expect(inputs.map((i, el) => el.value).toArray()).to.deep.equal([
|
expect(inputs.map((i, el) => el.value).toArray()).to.deep.equal([
|
||||||
"1",
|
"1",
|
||||||
"2",
|
"2",
|
||||||
@@ -367,7 +367,7 @@ describe("OpenAPI 3.0 Multiple Examples - core features", () => {
|
|||||||
.select("__MODIFIED__VALUE__")
|
.select("__MODIFIED__VALUE__")
|
||||||
// Assert that our modified value is back
|
// Assert that our modified value is back
|
||||||
.get(".json-schema-form-item > input")
|
.get(".json-schema-form-item > input")
|
||||||
.then(inputs => {
|
.then((inputs) => {
|
||||||
expect(inputs.map((i, el) => el.value).toArray()).to.deep.equal([
|
expect(inputs.map((i, el) => el.value).toArray()).to.deep.equal([
|
||||||
"1",
|
"1",
|
||||||
"2",
|
"2",
|
||||||
@@ -566,41 +566,43 @@ describe("OpenAPI 3.0 Multiple Examples - core features", () => {
|
|||||||
})
|
})
|
||||||
})
|
})
|
||||||
describe("in a Request Body", () => {
|
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({
|
RequestBodyPrimitiveTestCases({
|
||||||
operationDomId: "#operations-default-post_Object",
|
operationDomId: "#operations-default-post_Object",
|
||||||
primaryMediaType: "application/json",
|
primaryMediaType: "application/json",
|
||||||
// ↓ not a typo, Cypress requires escaping { when using `cy.type`
|
// ↓ not a typo, Cypress requires escaping { when using `cy.type`
|
||||||
customUserInput: `{{} "openapiIsCool": true }`,
|
customUserInput: `{{} "openapiIsCool": true }`,
|
||||||
customExpectedUrlSubstring: "?openapiIsCool=true",
|
customExpectedUrlSubstring: "?openapiIsCool=true",
|
||||||
customUserInputExpectedCurlSubstring: `{\\"openapiIsCool\\":true}`,
|
customUserInputExpectedCurlSubstring: `{ "openapiIsCool": true }`,
|
||||||
exampleA: {
|
exampleA: {
|
||||||
key: "ObjectExampleA",
|
key: "ObjectExampleA",
|
||||||
serializedValue: `{\\"firstName\\":\\"Kyle\\",\\"lastName\\":\\"Shockey\\",\\"email\\":\\"kyle.shockey@smartbear.com\\"}`,
|
serializedValue: exampleA,
|
||||||
value: JSON.stringify(
|
value: exampleA,
|
||||||
{
|
|
||||||
firstName: "Kyle",
|
|
||||||
lastName: "Shockey",
|
|
||||||
email: "kyle.shockey@smartbear.com",
|
|
||||||
},
|
|
||||||
null,
|
|
||||||
2
|
|
||||||
),
|
|
||||||
summary: "A user's contact info",
|
summary: "A user's contact info",
|
||||||
},
|
},
|
||||||
exampleB: {
|
exampleB: {
|
||||||
key: "ObjectExampleB",
|
key: "ObjectExampleB",
|
||||||
serializedValue: `{\\"name\\":\\"Abbey\\",\\"type\\":\\"kitten\\",\\"color\\":\\"calico\\",\\"gender\\":\\"female\\",\\"age\\":\\"11 weeks\\"}`,
|
serializedValue: exampleB,
|
||||||
value: JSON.stringify(
|
value: exampleB,
|
||||||
{
|
|
||||||
name: "Abbey",
|
|
||||||
type: "kitten",
|
|
||||||
color: "calico",
|
|
||||||
gender: "female",
|
|
||||||
age: "11 weeks",
|
|
||||||
},
|
|
||||||
null,
|
|
||||||
2
|
|
||||||
),
|
|
||||||
summary: "A wonderful kitten's info",
|
summary: "A wonderful kitten's info",
|
||||||
},
|
},
|
||||||
})
|
})
|
||||||
|
|||||||
@@ -95,7 +95,7 @@ describe("OpenAPI 3.0 Validation for Required Request Body and Request Body Fiel
|
|||||||
.get(".responses-wrapper .curl-command")
|
.get(".responses-wrapper .curl-command")
|
||||||
.should("exist")
|
.should("exist")
|
||||||
.get(".responses-wrapper .curl-command span")
|
.get(".responses-wrapper .curl-command span")
|
||||||
.should("contains.text", "\" \"")
|
.should("contains.text", "' '")
|
||||||
})
|
})
|
||||||
})
|
})
|
||||||
|
|
||||||
|
|||||||
@@ -3,9 +3,9 @@ import React from "react"
|
|||||||
import { fromJSOrdered } from "core/utils"
|
import { fromJSOrdered } from "core/utils"
|
||||||
import expect, { createSpy } from "expect"
|
import expect, { createSpy } from "expect"
|
||||||
import { shallow } from "enzyme"
|
import { shallow } from "enzyme"
|
||||||
import Curl from "components/curl"
|
|
||||||
import LiveResponse from "components/live-response"
|
import LiveResponse from "components/live-response"
|
||||||
import ResponseBody from "components/response-body"
|
import ResponseBody from "components/response-body"
|
||||||
|
import { RequestSnippets } from "core/plugins/request-snippets/request-snippets"
|
||||||
|
|
||||||
describe("<LiveResponse/>", function () {
|
describe("<LiveResponse/>", function () {
|
||||||
let request = fromJSOrdered({
|
let request = fromJSOrdered({
|
||||||
@@ -36,7 +36,7 @@ describe("<LiveResponse/>", function () {
|
|||||||
]
|
]
|
||||||
|
|
||||||
tests.forEach(function (test) {
|
tests.forEach(function (test) {
|
||||||
it("passes " + test.expected.request + " to Curl when showMutatedRequest = " + test.showMutatedRequest, function () {
|
it("passes " + test.expected.request + " to RequestSnippets when showMutatedRequest = " + test.showMutatedRequest, function () {
|
||||||
|
|
||||||
// Given
|
// Given
|
||||||
|
|
||||||
@@ -54,7 +54,7 @@ describe("<LiveResponse/>", function () {
|
|||||||
let requestForSpy = createSpy().andReturn(request)
|
let requestForSpy = createSpy().andReturn(request)
|
||||||
|
|
||||||
let components = {
|
let components = {
|
||||||
curl: Curl,
|
RequestSnippets: RequestSnippets,
|
||||||
responseBody: ResponseBody
|
responseBody: ResponseBody
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -69,7 +69,7 @@ describe("<LiveResponse/>", function () {
|
|||||||
return components[c]
|
return components[c]
|
||||||
},
|
},
|
||||||
displayRequestDuration: true,
|
displayRequestDuration: true,
|
||||||
getConfigs: () => ({ showMutatedRequest: test.showMutatedRequest })
|
getConfigs: () => ({ showMutatedRequest: test.showMutatedRequest, requestSnippetsEnabled: true })
|
||||||
}
|
}
|
||||||
|
|
||||||
// When
|
// When
|
||||||
@@ -79,9 +79,9 @@ describe("<LiveResponse/>", function () {
|
|||||||
expect(mutatedRequestForSpy.calls.length).toEqual(test.expected.mutatedRequestForCalls)
|
expect(mutatedRequestForSpy.calls.length).toEqual(test.expected.mutatedRequestForCalls)
|
||||||
expect(requestForSpy.calls.length).toEqual(test.expected.requestForCalls)
|
expect(requestForSpy.calls.length).toEqual(test.expected.requestForCalls)
|
||||||
|
|
||||||
const curl = wrapper.find(Curl)
|
const snippets = wrapper.find("RequestSnippets")
|
||||||
expect(curl.length).toEqual(1)
|
expect(snippets.length).toEqual(1)
|
||||||
expect(curl.props().request).toBe(requests[test.expected.request])
|
expect(snippets.props().request).toBe(requests[test.expected.request])
|
||||||
|
|
||||||
const expectedUrl = requests[test.expected.request].get("url")
|
const expectedUrl = requests[test.expected.request].get("url")
|
||||||
expect(wrapper.find("div.request-url pre.microlight").text()).toEqual(expectedUrl)
|
expect(wrapper.find("div.request-url pre.microlight").text()).toEqual(expectedUrl)
|
||||||
|
|||||||
@@ -1,18 +1,19 @@
|
|||||||
import Im from "immutable"
|
import Im from "immutable"
|
||||||
import curl from "core/curlify"
|
import { requestSnippetGenerator_curl_bash as curl } from "core/plugins/request-snippets/fn.js"
|
||||||
import win from "core/window"
|
import win from "core/window"
|
||||||
|
|
||||||
describe("curlify", function () {
|
describe("curlify", function () {
|
||||||
|
|
||||||
it("prints a curl statement with custom content-type", function () {
|
it("prints a curl statement with custom content-type", function () {
|
||||||
|
const body = JSON.stringify({
|
||||||
|
id: 0,
|
||||||
|
name: "doggie",
|
||||||
|
status: "available"
|
||||||
|
}, null, 2)
|
||||||
let req = {
|
let req = {
|
||||||
url: "http://example.com",
|
url: "http://example.com",
|
||||||
method: "POST",
|
method: "POST",
|
||||||
body: {
|
body,
|
||||||
id: 0,
|
|
||||||
name: "doggie",
|
|
||||||
status: "available"
|
|
||||||
},
|
|
||||||
headers: {
|
headers: {
|
||||||
Accept: "application/json",
|
Accept: "application/json",
|
||||||
"content-type": "application/json"
|
"content-type": "application/json"
|
||||||
@@ -21,7 +22,7 @@ describe("curlify", function () {
|
|||||||
|
|
||||||
let curlified = curl(Im.fromJS(req))
|
let curlified = curl(Im.fromJS(req))
|
||||||
|
|
||||||
expect(curlified).toEqual("curl -X POST \"http://example.com\" -H \"Accept: application/json\" -H \"content-type: application/json\" -d {\"id\":0,\"name\":\"doggie\",\"status\":\"available\"}")
|
expect(curlified).toEqual(`curl -X 'POST' \\\n 'http://example.com' \\\n -H 'Accept: application/json' \\\n -H 'content-type: application/json' \\\n -d '${body}'`)
|
||||||
})
|
})
|
||||||
|
|
||||||
it("does add a empty data param if no request body given", function () {
|
it("does add a empty data param if no request body given", function () {
|
||||||
@@ -32,7 +33,7 @@ describe("curlify", function () {
|
|||||||
|
|
||||||
let curlified = curl(Im.fromJS(req))
|
let curlified = curl(Im.fromJS(req))
|
||||||
|
|
||||||
expect(curlified).toEqual("curl -X POST \"http://example.com\" -d \"\"")
|
expect(curlified).toEqual("curl -X 'POST' \\\n 'http://example.com' \\\n -d ''")
|
||||||
})
|
})
|
||||||
|
|
||||||
it("does not change the case of header in curl", function () {
|
it("does not change the case of header in curl", function () {
|
||||||
@@ -46,7 +47,7 @@ describe("curlify", function () {
|
|||||||
|
|
||||||
let curlified = curl(Im.fromJS(req))
|
let curlified = curl(Im.fromJS(req))
|
||||||
|
|
||||||
expect(curlified).toEqual("curl -X POST \"http://example.com\" -H \"conTenT Type: application/Moar\" -d \"\"")
|
expect(curlified).toEqual("curl -X 'POST' \\\n 'http://example.com' \\\n -H 'conTenT Type: application/Moar' \\\n -d ''")
|
||||||
})
|
})
|
||||||
|
|
||||||
it("prints a curl statement with an array of query params", function () {
|
it("prints a curl statement with an array of query params", function () {
|
||||||
@@ -57,7 +58,7 @@ describe("curlify", function () {
|
|||||||
|
|
||||||
let curlified = curl(Im.fromJS(req))
|
let curlified = curl(Im.fromJS(req))
|
||||||
|
|
||||||
expect(curlified).toEqual("curl -X GET \"http://swaggerhub.com/v1/one?name=john|smith\"")
|
expect(curlified).toEqual("curl -X 'GET' \\\n 'http://swaggerhub.com/v1/one?name=john|smith'")
|
||||||
})
|
})
|
||||||
|
|
||||||
it("prints a curl statement with an array of query params and auth", function () {
|
it("prints a curl statement with an array of query params and auth", function () {
|
||||||
@@ -71,24 +72,25 @@ describe("curlify", function () {
|
|||||||
|
|
||||||
let curlified = curl(Im.fromJS(req))
|
let curlified = curl(Im.fromJS(req))
|
||||||
|
|
||||||
expect(curlified).toEqual("curl -X GET \"http://swaggerhub.com/v1/one?name=john|smith\" -H \"authorization: Basic Zm9vOmJhcg==\"")
|
expect(curlified).toEqual("curl -X 'GET' \\\n 'http://swaggerhub.com/v1/one?name=john|smith' \\\n -H 'authorization: Basic Zm9vOmJhcg=='")
|
||||||
})
|
})
|
||||||
|
|
||||||
it("prints a curl statement with html", function () {
|
it("prints a curl statement with html", function () {
|
||||||
|
const body = {
|
||||||
|
description: "<b>Test</b>"
|
||||||
|
}
|
||||||
let req = {
|
let req = {
|
||||||
url: "http://swaggerhub.com/v1/one?name=john|smith",
|
url: "http://swaggerhub.com/v1/one?name=john|smith",
|
||||||
method: "GET",
|
method: "GET",
|
||||||
headers: {
|
headers: {
|
||||||
accept: "application/json"
|
accept: "application/json"
|
||||||
},
|
},
|
||||||
body: {
|
body
|
||||||
description: "<b>Test</b>"
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
let curlified = curl(Im.fromJS(req))
|
let curlified = curl(Im.fromJS(req))
|
||||||
|
|
||||||
expect(curlified).toEqual("curl -X GET \"http://swaggerhub.com/v1/one?name=john|smith\" -H \"accept: application/json\" -d {\"description\":\"<b>Test</b>\"}")
|
expect(curlified).toEqual(`curl -X 'GET' \\\n 'http://swaggerhub.com/v1/one?name=john|smith' \\\n -H 'accept: application/json' \\\n -d '${JSON.stringify(body, null, 2)}'`)
|
||||||
})
|
})
|
||||||
|
|
||||||
it("handles post body with html", function () {
|
it("handles post body with html", function () {
|
||||||
@@ -105,7 +107,12 @@ describe("curlify", function () {
|
|||||||
|
|
||||||
let curlified = curl(Im.fromJS(req))
|
let curlified = curl(Im.fromJS(req))
|
||||||
|
|
||||||
expect(curlified).toEqual("curl -X POST \"http://swaggerhub.com/v1/one?name=john|smith\" -H \"accept: application/json\" -d {\"description\":\"<b>Test</b>\"}")
|
expect(curlified).toEqual(`curl -X 'POST' \\
|
||||||
|
'http://swaggerhub.com/v1/one?name=john|smith' \\
|
||||||
|
-H 'accept: application/json' \\
|
||||||
|
-d '{
|
||||||
|
"description": "<b>Test</b>"
|
||||||
|
}'`)
|
||||||
})
|
})
|
||||||
|
|
||||||
it("handles post body with special chars", function () {
|
it("handles post body with special chars", function () {
|
||||||
@@ -120,7 +127,7 @@ describe("curlify", function () {
|
|||||||
|
|
||||||
let curlified = curl(Im.fromJS(req))
|
let curlified = curl(Im.fromJS(req))
|
||||||
|
|
||||||
expect(curlified).toEqual("curl -X POST \"http://swaggerhub.com/v1/one?name=john|smith\" -d {\"description\":\"@prefix nif:<http://persistence.uni-leipzig.org/nlp2rdf/ontologies/nif-core#> .@prefix itsrdf: <http://www.w3.org/2005/11/its/rdf#> .\"}")
|
expect(curlified).toEqual("curl -X 'POST' \\\n 'http://swaggerhub.com/v1/one?name=john|smith' \\\n -d '{\n \"description\": \"@prefix nif:<http://persistence.uni-leipzig.org/nlp2rdf/ontologies/nif-core#> .\\n@prefix itsrdf: <http://www.w3.org/2005/11/its/rdf#> .\"\n}'")
|
||||||
})
|
})
|
||||||
|
|
||||||
it("handles delete form with parameters", function () {
|
it("handles delete form with parameters", function () {
|
||||||
@@ -134,7 +141,7 @@ describe("curlify", function () {
|
|||||||
|
|
||||||
let curlified = curl(Im.fromJS(req))
|
let curlified = curl(Im.fromJS(req))
|
||||||
|
|
||||||
expect(curlified).toEqual("curl -X DELETE \"http://example.com\" -H \"accept: application/x-www-form-urlencoded\"")
|
expect(curlified).toEqual("curl -X 'DELETE' \\\n 'http://example.com' \\\n -H 'accept: application/x-www-form-urlencoded'")
|
||||||
})
|
})
|
||||||
|
|
||||||
it("should print a curl with formData", function () {
|
it("should print a curl with formData", function () {
|
||||||
@@ -150,7 +157,7 @@ describe("curlify", function () {
|
|||||||
|
|
||||||
let curlified = curl(Im.fromJS(req))
|
let curlified = curl(Im.fromJS(req))
|
||||||
|
|
||||||
expect(curlified).toEqual("curl -X POST \"http://example.com\" -H \"content-type: multipart/form-data\" -F \"id=123\" -F \"name=Sahar\"")
|
expect(curlified).toEqual("curl -X 'POST' \\\n 'http://example.com' \\\n -H 'content-type: multipart/form-data' \\\n -F 'id=123' \\\n -F 'name=Sahar'")
|
||||||
})
|
})
|
||||||
|
|
||||||
it("should print a curl with formData that extracts array representation with hashIdx", function () {
|
it("should print a curl with formData that extracts array representation with hashIdx", function () {
|
||||||
@@ -170,7 +177,7 @@ describe("curlify", function () {
|
|||||||
|
|
||||||
let curlified = curl(Im.fromJS(req))
|
let curlified = curl(Im.fromJS(req))
|
||||||
|
|
||||||
expect(curlified).toEqual("curl -X POST \"http://example.com\" -H \"content-type: multipart/form-data\" -F \"id=123\" -F \"fruits[]=apple\" -F \"fruits[]=banana\" -F \"fruits[]=grape\"")
|
expect(curlified).toEqual("curl -X 'POST' \\\n 'http://example.com' \\\n -H 'content-type: multipart/form-data' \\\n -F 'id=123' \\\n -F 'fruits[]=apple' \\\n -F 'fruits[]=banana' \\\n -F 'fruits[]=grape'")
|
||||||
})
|
})
|
||||||
|
|
||||||
it("should print a curl with formData and file", function () {
|
it("should print a curl with formData and file", function () {
|
||||||
@@ -190,7 +197,7 @@ describe("curlify", function () {
|
|||||||
|
|
||||||
let curlified = curl(Im.fromJS(req))
|
let curlified = curl(Im.fromJS(req))
|
||||||
|
|
||||||
expect(curlified).toEqual("curl -X POST \"http://example.com\" -H \"content-type: multipart/form-data\" -F \"id=123\" -F \"file=@file.txt;type=text/plain\"")
|
expect(curlified).toEqual("curl -X 'POST' \\\n 'http://example.com' \\\n -H 'content-type: multipart/form-data' \\\n -F 'id=123' \\\n -F 'file=@file.txt;type=text/plain'")
|
||||||
})
|
})
|
||||||
|
|
||||||
it("should print a curl without form data type if type is unknown", function () {
|
it("should print a curl without form data type if type is unknown", function () {
|
||||||
@@ -210,7 +217,7 @@ describe("curlify", function () {
|
|||||||
|
|
||||||
let curlified = curl(Im.fromJS(req))
|
let curlified = curl(Im.fromJS(req))
|
||||||
|
|
||||||
expect(curlified).toEqual("curl -X POST \"http://example.com\" -H \"content-type: multipart/form-data\" -F \"id=123\" -F \"file=@file.txt\"")
|
expect(curlified).toEqual("curl -X 'POST' \\\n 'http://example.com' \\\n -H 'content-type: multipart/form-data' \\\n -F 'id=123' \\\n -F 'file=@file.txt'")
|
||||||
})
|
})
|
||||||
|
|
||||||
it("prints a curl post statement from an object", function () {
|
it("prints a curl post statement from an object", function () {
|
||||||
@@ -227,7 +234,7 @@ describe("curlify", function () {
|
|||||||
|
|
||||||
let curlified = curl(Im.fromJS(req))
|
let curlified = curl(Im.fromJS(req))
|
||||||
|
|
||||||
expect(curlified).toEqual("curl -X POST \"http://example.com\" -H \"accept: application/json\" -d {\"id\":10101}")
|
expect(curlified).toEqual("curl -X 'POST' \\\n 'http://example.com' \\\n -H 'accept: application/json' \\\n -d '{\n \"id\": 10101\n}'")
|
||||||
})
|
})
|
||||||
|
|
||||||
it("prints a curl post statement from a string containing a single quote", function () {
|
it("prints a curl post statement from a string containing a single quote", function () {
|
||||||
@@ -242,7 +249,7 @@ describe("curlify", function () {
|
|||||||
|
|
||||||
let curlified = curl(Im.fromJS(req))
|
let curlified = curl(Im.fromJS(req))
|
||||||
|
|
||||||
expect(curlified).toEqual("curl -X POST \"http://example.com\" -H \"accept: application/json\" -d \"{\\\"id\\\":\\\"foo'bar\\\"}\"")
|
expect(curlified).toEqual("curl -X 'POST' \\\n 'http://example.com' \\\n -H 'accept: application/json' \\\n -d '{\"id\":\"foo'\\''bar\"}'")
|
||||||
})
|
})
|
||||||
|
|
||||||
describe("given multiple entries with file", function () {
|
describe("given multiple entries with file", function () {
|
||||||
@@ -267,7 +274,7 @@ describe("curlify", function () {
|
|||||||
|
|
||||||
let curlified = curl(Im.fromJS(req))
|
let curlified = curl(Im.fromJS(req))
|
||||||
|
|
||||||
expect(curlified).toEqual("curl -X POST \"http://example.com\" -H \"x-custom-name: multipart/form-data\" -H \"content-type: multipart/form-data\" -F \"id=123\" -F \"file=@file.txt;type=text/plain\"")
|
expect(curlified).toEqual("curl -X 'POST' \\\n 'http://example.com' \\\n -H 'x-custom-name: multipart/form-data' \\\n -H 'content-type: multipart/form-data' \\\n -F 'id=123' \\\n -F 'file=@file.txt;type=text/plain'")
|
||||||
})
|
})
|
||||||
})
|
})
|
||||||
|
|
||||||
@@ -292,7 +299,7 @@ describe("curlify", function () {
|
|||||||
|
|
||||||
let curlified = curl(Im.fromJS(req))
|
let curlified = curl(Im.fromJS(req))
|
||||||
|
|
||||||
expect(curlified).toEqual("curl -X POST \"http://example.com\" -H \"content-type: multipart/form-data\" -H \"x-custom-name: any-value\" -F \"id=123\" -F \"file=@file.txt;type=text/plain\"")
|
expect(curlified).toEqual("curl -X 'POST' \\\n 'http://example.com' \\\n -H 'content-type: multipart/form-data' \\\n -H 'x-custom-name: any-value' \\\n -F 'id=123' \\\n -F 'file=@file.txt;type=text/plain'")
|
||||||
})
|
})
|
||||||
})
|
})
|
||||||
})
|
})
|
||||||
@@ -315,7 +322,7 @@ describe("curlify", function () {
|
|||||||
|
|
||||||
let curlified = curl(Im.fromJS(req))
|
let curlified = curl(Im.fromJS(req))
|
||||||
|
|
||||||
expect(curlified).toEqual("curl -X POST \"http://example.com\" -H \"x-custom-name: multipart/form-data\" -d {\"id\":\"123\",\"file\":{\"name\":\"file.txt\",\"type\":\"text/plain\"}}")
|
expect(curlified).toEqual("curl -X 'POST' \\\n 'http://example.com' \\\n -H 'x-custom-name: multipart/form-data' \\\n -d '{\n \"id\": \"123\",\n \"file\": {\n \"name\": \"file.txt\",\n \"type\": \"text/plain\"\n }\n}'")
|
||||||
})
|
})
|
||||||
|
|
||||||
it("shoud print a proper curl as -d <data>, no file type provided", function () {
|
it("shoud print a proper curl as -d <data>, no file type provided", function () {
|
||||||
@@ -335,36 +342,10 @@ describe("curlify", function () {
|
|||||||
|
|
||||||
let curlified = curl(Im.fromJS(req))
|
let curlified = curl(Im.fromJS(req))
|
||||||
|
|
||||||
expect(curlified).toEqual("curl -X POST \"http://example.com\" -H \"x-custom-name: multipart/form-data\" -d {\"id\":\"123\",\"file\":{\"name\":\"file.txt\"}}")
|
expect(curlified).toEqual("curl -X 'POST' \\\n 'http://example.com' \\\n -H 'x-custom-name: multipart/form-data' \\\n -d '{\n \"id\": \"123\",\n \"file\": {\n \"name\": \"file.txt\"\n }\n}'")
|
||||||
})
|
})
|
||||||
})
|
})
|
||||||
|
|
||||||
it("should escape dollar signs in headers and request body", function () {
|
|
||||||
let req = {
|
|
||||||
url: "http://example.com",
|
|
||||||
method: "POST",
|
|
||||||
headers: { "X-DOLLAR": "token/123$" },
|
|
||||||
body: "CREATE ($props)"
|
|
||||||
}
|
|
||||||
|
|
||||||
let curlified = curl(Im.fromJS(req))
|
|
||||||
|
|
||||||
expect(curlified).toEqual("curl -X POST \"http://example.com\" -H \"X-DOLLAR: token/123\\$\" -d \"CREATE (\\$props)\"")
|
|
||||||
})
|
|
||||||
|
|
||||||
it("should escape multiple dollar signs", function () {
|
|
||||||
let req = {
|
|
||||||
url: "http://example.com",
|
|
||||||
method: "POST",
|
|
||||||
headers: { },
|
|
||||||
body: "RETURN $x + $y"
|
|
||||||
}
|
|
||||||
|
|
||||||
let curlified = curl(Im.fromJS(req))
|
|
||||||
|
|
||||||
expect(curlified).toEqual("curl -X POST \"http://example.com\" -d \"RETURN \\$x + \\$y\"")
|
|
||||||
})
|
|
||||||
|
|
||||||
it("should include curlOptions from the request in the curl command", function () {
|
it("should include curlOptions from the request in the curl command", function () {
|
||||||
let req = {
|
let req = {
|
||||||
url: "http://example.com",
|
url: "http://example.com",
|
||||||
@@ -375,7 +356,7 @@ describe("curlify", function () {
|
|||||||
|
|
||||||
let curlified = curl(Im.fromJS(req))
|
let curlified = curl(Im.fromJS(req))
|
||||||
|
|
||||||
expect(curlified).toEqual("curl -g -X GET \"http://example.com\" -H \"X-DOLLAR: token/123\\$\"")
|
expect(curlified).toEqual("curl -g -X 'GET' \\\n 'http://example.com' \\\n -H 'X-DOLLAR: token/123$'")
|
||||||
})
|
})
|
||||||
|
|
||||||
it("should include multiple curlOptions from the request in the curl command", function () {
|
it("should include multiple curlOptions from the request in the curl command", function () {
|
||||||
@@ -388,6 +369,6 @@ describe("curlify", function () {
|
|||||||
|
|
||||||
let curlified = curl(Im.fromJS(req))
|
let curlified = curl(Im.fromJS(req))
|
||||||
|
|
||||||
expect(curlified).toEqual("curl -g --limit-rate 20k -X GET \"http://example.com\" -H \"X-DOLLAR: token/123\\$\"")
|
expect(curlified).toEqual("curl -g --limit-rate 20k -X 'GET' \\\n 'http://example.com' \\\n -H 'X-DOLLAR: token/123$'")
|
||||||
})
|
})
|
||||||
})
|
})
|
||||||
|
|||||||
Reference in New Issue
Block a user