diff --git a/src/core/components/execute.jsx b/src/core/components/execute.jsx
index e6b3e1b0bed..eeb74ae9c00 100644
--- a/src/core/components/execute.jsx
+++ b/src/core/components/execute.jsx
@@ -25,7 +25,8 @@ export default class Execute extends Component {
let { path, method, specSelectors, oas3Selectors, oas3Actions } = this.props
let validationErrors = {
missingBodyValue: false,
- missingRequiredKeys: []
+ missingRequiredKeys: [],
+ valueErrors: []
}
// context: reset errors, then (re)validate
oas3Actions.clearRequestBodyValidateError({ path, method })
@@ -33,6 +34,7 @@ export default class Execute extends Component {
let oas3RequestBodyValue = oas3Selectors.requestBodyValue(path, method)
let oas3ValidateBeforeExecuteSuccess = oas3Selectors.validateBeforeExecute([path, method])
let oas3RequestContentType = oas3Selectors.requestContentType(path, method)
+ let oas3RequestBody = specSelectors.getOAS3RequestBody([path, method])
if (!oas3ValidateBeforeExecuteSuccess) {
validationErrors.missingBodyValue = true
@@ -47,12 +49,21 @@ export default class Execute extends Component {
oas3RequestContentType,
oas3RequestBodyValue
})
- if (!missingRequiredKeys || missingRequiredKeys.length < 1) {
+ let valueErrors = oas3Selectors.validateValues({
+ oas3RequestBody,
+ oas3RequestContentType,
+ oas3RequestBodyValue
+ })
+ if ((!missingRequiredKeys || missingRequiredKeys.length < 1)
+ && (!valueErrors || valueErrors.length < 1)) {
return true
}
missingRequiredKeys.forEach((missingKey) => {
validationErrors.missingRequiredKeys.push(missingKey)
})
+ valueErrors.forEach((error) => {
+ validationErrors.valueErrors.push(error)
+ })
oas3Actions.setRequestBodyValidateError({ path, method, validationErrors })
return false
}
diff --git a/src/core/components/operation.jsx b/src/core/components/operation.jsx
index 9e6046addb6..dce79c088b0 100644
--- a/src/core/components/operation.jsx
+++ b/src/core/components/operation.jsx
@@ -115,7 +115,10 @@ export default class Operation extends PureComponent {
let onChangeKey = [ path, method ] // Used to add values to _this_ operation ( indexed by path and method )
- const validationErrors = specSelectors.validationErrors([path, method])
+ const oas3ValidationErrors = specSelectors.isOAS3()
+ ? oas3Selectors.validationErrors(path, method)
+ : []
+ const validationErrors = specSelectors.validationErrors([path, method]).concat(oas3ValidationErrors)
return (
diff --git a/src/core/plugins/oas3/reducers.js b/src/core/plugins/oas3/reducers.js
index 9efdb267726..7ff4db056c1 100644
--- a/src/core/plugins/oas3/reducers.js
+++ b/src/core/plugins/oas3/reducers.js
@@ -81,6 +81,10 @@ export default {
}, missingKeyValues)
})
}
+ if (validationErrors.valueErrors && validationErrors.valueErrors.length > 0) {
+ // context: is application/json, with list of errors
+ return state.setIn(["requestData", path, method, "errors"], fromJS(validationErrors.valueErrors))
+ }
console.warn("unexpected result: SET_REQUEST_BODY_VALIDATE_ERROR")
return state
},
diff --git a/src/core/plugins/oas3/selectors.js b/src/core/plugins/oas3/selectors.js
index d902a2db698..52996b6c6e7 100644
--- a/src/core/plugins/oas3/selectors.js
+++ b/src/core/plugins/oas3/selectors.js
@@ -5,7 +5,7 @@ import { OrderedMap, Map, List } from "immutable"
import constant from "lodash/constant"
import { getDefaultRequestBodyValue } from "./components/request-body"
-import { stringify } from "core/utils"
+import { stringify, validateParam } from "core/utils"
// Helpers
@@ -165,6 +165,19 @@ export const requestBodyErrors = onlyOAS3((state, path, method) => {
return state.getIn(["requestData", path, method, "errors"]) || null
})
+export const validationErrors = onlyOAS3((state, path, method) => {
+ const errors = state.getIn(["requestData", path, method, "errors"]) || null
+ const result = []
+
+ if (errors && errors.count()) {
+ errors
+ .map((e) => (Map.isMap(e) ? `${e.get("propKey")}: ${e.get("error")}` : e))
+ .forEach((e) => result.push(e))
+ }
+
+ return result
+})
+
export const activeExamplesMember = onlyOAS3(
(state, path, method, type, name) => {
return (
@@ -295,6 +308,23 @@ export const validateShallowRequired = (
return missingRequiredKeys
}
+export const validateValues = (
+ state,
+ {
+ oas3RequestBody,
+ oas3RequestContentType,
+ oas3RequestBodyValue
+ }
+) => {
+ if (oas3RequestContentType !== "application/json") {
+ return []
+ }
+ return validateParam(oas3RequestBody, oas3RequestBodyValue, {
+ bypassRequiredCheck: false,
+ isOAS3: true,
+ })
+}
+
export const validOperationMethods = constant([
"get",
"put",
diff --git a/src/core/plugins/spec/selectors.js b/src/core/plugins/spec/selectors.js
index 82607ac8f1f..a9f196febfb 100644
--- a/src/core/plugins/spec/selectors.js
+++ b/src/core/plugins/spec/selectors.js
@@ -509,6 +509,10 @@ export const validateBeforeExecute = (state, pathMethod) => {
return validationErrors(state, pathMethod).length === 0
}
+export const getOAS3RequestBody = (state, pathMethod) => {
+ return state.getIn(["resolvedSubtrees", "paths", ...pathMethod, "requestBody"], fromJS([]))
+}
+
export const getOAS3RequiredRequestBodyContentType = (state, pathMethod) => {
let requiredObj = {
requestBody: false,
diff --git a/src/core/utils/index.js b/src/core/utils/index.js
index 9ff5770ee2e..0b9a6b11240 100644
--- a/src/core/utils/index.js
+++ b/src/core/utils/index.js
@@ -9,7 +9,7 @@
If you're refactoring something in here, feel free to break it out to a file
in `./helpers` if you have the time.
*/
-import Im, { fromJS, Set } from "immutable"
+import Im, { fromJS, Set, List } from "immutable"
import { sanitizeUrl as braintreeSanitizeUrl } from "@braintree/sanitize-url"
import camelCase from "lodash/camelCase"
import upperFirst from "lodash/upperFirst"
@@ -486,7 +486,7 @@ function validateValueBySchema(value, schema, requiredByParam, bypassRequiredChe
return errors
}
}
- if(schema && schema.has("required") && isFunc(requiredBySchema.isList) && requiredBySchema.isList()) {
+ if(schema && requiredBySchema && List.isList(requiredBySchema)) {
requiredBySchema.forEach(key => {
if(objectVal[key] === undefined) {
errors.push({ propKey: key, error: "Required property not found" })
diff --git a/test/unit/core/plugins/oas3/reducers.js b/test/unit/core/plugins/oas3/reducers.js
index 22371eb8943..cd3e5624316 100644
--- a/test/unit/core/plugins/oas3/reducers.js
+++ b/test/unit/core/plugins/oas3/reducers.js
@@ -314,6 +314,142 @@ describe("oas3 plugin - reducer", function () {
})
})
+ describe("valueErrors exists with length, e.g. application/json", () => {
+ it("should set errors", () => {
+ const state = fromJS({
+ requestData: {
+ "/pet": {
+ post: {
+ bodyValue: {
+ id: {
+ value: "10",
+ },
+ name: {
+ value: "",
+ },
+ },
+ requestContentType: "application/json"
+ }
+ }
+ }
+ })
+
+ const result = setRequestBodyValidateError(state, {
+ payload: {
+ path: "/pet",
+ method: "post",
+ validationErrors: {
+ missingBodyValue: null,
+ valueErrors: [
+ {
+ propKey: "name",
+ error: "Required property not found"
+ }
+ ]
+ },
+ }
+ })
+
+ const expectedResult = {
+ requestData: {
+ "/pet": {
+ post: {
+ bodyValue: {
+ id: {
+ value: "10",
+ },
+ name: {
+ value: "",
+ },
+ },
+ requestContentType: "application/json",
+ errors: [
+ {
+ propKey: "name",
+ error: "Required property not found"
+ }
+ ]
+ }
+ }
+ }
+ }
+
+ expect(result.toJS()).toEqual(expectedResult)
+ })
+
+ it("should overwrite errors", () => {
+ const state = fromJS({
+ requestData: {
+ "/pet": {
+ post: {
+ bodyValue: {
+ id: {
+ value: "10",
+ },
+ name: {
+ value: "",
+ },
+ },
+ requestContentType: "application/json",
+ errors: [
+ {
+ propKey: "id",
+ error: "some fake error"
+ },
+ {
+ propKey: "name",
+ error: "some fake error"
+ }
+ ]
+ }
+ }
+ }
+ })
+
+ const result = setRequestBodyValidateError(state, {
+ payload: {
+ path: "/pet",
+ method: "post",
+ validationErrors: {
+ missingBodyValue: null,
+ valueErrors: [
+ {
+ propKey: "name",
+ error: "Required property not found"
+ }
+ ]
+ },
+ }
+ })
+
+ const expectedResult = {
+ requestData: {
+ "/pet": {
+ post: {
+ bodyValue: {
+ id: {
+ value: "10",
+ },
+ name: {
+ value: "",
+ },
+ },
+ requestContentType: "application/json",
+ errors: [
+ {
+ propKey: "name",
+ error: "Required property not found"
+ }
+ ]
+ }
+ }
+ }
+ }
+
+ expect(result.toJS()).toEqual(expectedResult)
+ })
+ })
+
describe("other unexpected payload, e.g. no missingBodyValue or missingRequiredKeys", () => {
it("should not throw error if receiving unexpected validationError format. return state unchanged", () => {
const state = fromJS({