Repository: codekie/openapi-examples-validator (js)

Issue:
Support for nullable
My schema has properties that can be nullable. However, when I pass in, for example `userId: null` I get a validation error saying it should be integer. 

Pull request description:
Support nullables
Closes #37 

Patch:
diff --git a/.eslintrc.yml b/.eslintrc.yml
index 44d78e4..f33a798 100644
--- a/.eslintrc.yml
+++ b/.eslintrc.yml
@@ -50,6 +50,7 @@ rules:
     - 2
     - 4
     - SwitchCase: 1
+      ignoreComments: true
   key-spacing:
     - 2
     - beforeColon: false
diff --git a/package-lock.json b/package-lock.json
index 7e50402..88a6b8e 100644
--- a/package-lock.json
+++ b/package-lock.json
@@ -10217,12 +10217,6 @@
       "integrity": "sha512-PqpAxfrEhlSUWge8dwIp4tZnQ25DIOthpiaHNIthsjEFQD6EvqUKUDM7L8O2rShkFccYo1VjJR0coWfNkCubRw==",
       "dev": true
     },
-    "serialize-javascript": {
-      "version": "1.9.1",
-      "resolved": "https://registry.npmjs.org/serialize-javascript/-/serialize-javascript-1.9.1.tgz",
-      "integrity": "sha512-0Vb/54WJ6k5v8sSWN09S0ora+Hnr+cX40r9F170nT+mSkaxltoE/7R3OrIdBSUv1OoiobH1QoWQbCnAO+e8J1A==",
-      "dev": true
-    },
     "set-blocking": {
       "version": "2.0.0",
       "resolved": "https://registry.npmjs.org/set-blocking/-/set-blocking-2.0.0.tgz",
@@ -11394,47 +11388,6 @@
         }
       }
     },
-    "uglifyjs-webpack-plugin": {
-      "version": "2.2.0",
-      "resolved": "https://registry.npmjs.org/uglifyjs-webpack-plugin/-/uglifyjs-webpack-plugin-2.2.0.tgz",
-      "integrity": "sha512-mHSkufBmBuJ+KHQhv5H0MXijtsoA1lynJt1lXOaotja8/I0pR4L9oGaPIZw+bQBOFittXZg9OC1sXSGO9D9ZYg==",
-      "dev": true,
-      "requires": {
-        "cacache": "^12.0.2",
-        "find-cache-dir": "^2.1.0",
-        "is-wsl": "^1.1.0",
-        "schema-utils": "^1.0.0",
-        "serialize-javascript": "^1.7.0",
-        "source-map": "^0.6.1",
-        "uglify-js": "^3.6.0",
-        "webpack-sources": "^1.4.0",
-        "worker-farm": "^1.7.0"
-      },
-      "dependencies": {
-        "commander": {
-          "version": "2.20.0",
-          "resolved": "https://registry.npmjs.org/commander/-/commander-2.20.0.tgz",
-          "integrity": "sha512-7j2y+40w61zy6YC2iRNpUe/NwhNyoXrYpHMrSunaMG64nRnaf96zO/KMQR4OyN/UnE5KLyEBnKHd4aG3rskjpQ==",
-          "dev": true
-        },
-        "source-map": {
-          "version": "0.6.1",
-          "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz",
-          "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==",
-          "dev": true
-        },
-        "uglify-js": {
-          "version": "3.6.0",
-          "resolved": "https://registry.npmjs.org/uglify-js/-/uglify-js-3.6.0.tgz",
-          "integrity": "sha512-W+jrUHJr3DXKhrsS7NUVxn3zqMOFn0hL/Ei6v0anCIMoKC93TjcflTagwIHLW7SfMFfiQuktQyFVCFHGUE0+yg==",
-          "dev": true,
-          "requires": {
-            "commander": "~2.20.0",
-            "source-map": "~0.6.1"
-          }
-        }
-      }
-    },
     "underscore": {
       "version": "1.8.3",
       "resolved": "https://registry.npmjs.org/underscore/-/underscore-1.8.3.tgz",
diff --git a/package.json b/package.json
index 5ad7973..d6186ad 100644
--- a/package.json
+++ b/package.json
@@ -65,7 +65,6 @@
     "rimraf": "^3.0.2",
     "standard-version": "^7.1.0",
     "stryker-cli": "1.0.0",
-    "uglifyjs-webpack-plugin": "^2.2.0",
     "webpack": "^4.41.6",
     "webpack-cli": "^3.3.11"
   },
diff --git a/src/const/result-type.js b/src/const/result-type.js
new file mode 100644
index 0000000..b134107
--- /dev/null
+++ b/src/const/result-type.js
@@ -0,0 +1,7 @@
+module.exports = {
+    parent: 'parent',
+    parentProperty: 'parentProperty',
+    path: 'path',
+    pointer: 'pointer',
+    value: 'value'
+};
diff --git a/src/impl/v2/index.js b/src/impl/v2/index.js
index 62214c1..55ac4cc 100644
--- a/src/impl/v2/index.js
+++ b/src/impl/v2/index.js
@@ -12,7 +12,8 @@ const PATH__EXAMPLES = '$..examples.application/json',
 
 module.exports = {
     buildValidationMap,
-    getJsonPathsToExamples
+    getJsonPathsToExamples,
+    prepare
 };
 
 // IMPLEMENTATION DETAILS
@@ -39,6 +40,17 @@ function buildValidationMap(pathsExamples) {
     }, {});
 }
 
+/**
+ * Pre-processes the OpenAPI-spec, for further use.
+ * The passed spec won't be modified. If a modification happens, a modified copy will be returned.
+ * @param {Object}  openapiSpec     The OpenAPI-spec as JSON-schema
+ * @return {Object} The prepared OpenAPI-spec
+ */
+function prepare(openapiSpec) {
+    // No pre-processing yet, so we return the original
+    return openapiSpec;
+}
+
 /**
  * Gets a JSON-path to the corresponding response-schema, based on a JSON-path to an example.
  * @param {String}  pathExample JSON-path to example
diff --git a/src/impl/v3/index.js b/src/impl/v3/index.js
index 83011ec..b0b381c 100644
--- a/src/impl/v3/index.js
+++ b/src/impl/v3/index.js
@@ -26,7 +26,8 @@ const ExampleType = {
 
 module.exports = {
     buildValidationMap,
-    getJsonPathsToExamples
+    getJsonPathsToExamples,
+    prepare
 };
 
 // IMPLEMENTATION DETAILS
@@ -68,6 +69,19 @@ function buildValidationMap(pathsExamples) {
     }, {});
 }
 
+/**
+ * Pre-processes the OpenAPI-spec, for further use.
+ * The passed spec won't be modified. If a modification happens, a modified copy will be returned.
+ * @param {Object}  openapiSpec     The OpenAPI-spec as JSON-schema
+ * @return {Object} The prepared OpenAPI-spec
+ */
+function prepare(openapiSpec) {
+    // None yet. I added this to implement `nullable` until I figured there was a property for that.
+    // I'll leave this here for now, as pre-processing might become necessary for other things.
+    // A "cloneDeep"-function will be required though (eg. `lodash.clonedeep`-dependency)
+    return openapiSpec;
+}
+
 /**
  * Gets a JSON-path to the corresponding response-schema, based on a JSON-path to an example.
  *
diff --git a/src/index.js b/src/index.js
index de9e0ee..6a2cbc1 100644
--- a/src/index.js
+++ b/src/index.js
@@ -10,6 +10,7 @@ const
     yaml = require('yaml'),
     { JSONPath: jsonPath } = require('jsonpath-plus'),
     { createError } = require('errno').custom,
+    ResultType = require('./const/result-type'),
     { getValidatorFactory, compileValidate } = require('./validator'),
     Determiner = require('./impl'),
     { ApplicationError, ErrorType } = require('./application-error'),
@@ -90,6 +91,7 @@ module.exports = {
  */
 function validateExamples(openapiSpec) {
     const impl = Determiner.getImplementation(openapiSpec);
+    openapiSpec = impl.prepare(openapiSpec);
     let pathsExamples = impl.getJsonPathsToExamples()
         .reduce((res, pathToExamples) => {
             return res.concat(_extractExamplePaths(openapiSpec, pathToExamples));
@@ -134,6 +136,8 @@ function validateExamplesByMap(filePathSchema, globMapExternalExamples, { cwdToM
         try {
             mapExternalExamples = JSON.parse(fs.readFileSync(filePathMapExternalExamples, 'utf-8'));
             openapiSpec = _parseSpec(filePathSchema);
+            openapiSpec = Determiner.getImplementation(openapiSpec)
+                .prepare(openapiSpec);
         } catch (err) {
             return createValidationResponse({ errors: [ApplicationError.create(err)] });
         }
@@ -173,6 +177,8 @@ function validateExample(filePathSchema, pathResponseSchema, filePathExample) {
     try {
         example = JSON.parse(fs.readFileSync(filePathExample, 'utf-8'));
         openapiSpec = _parseSpec(filePathSchema);
+        openapiSpec = Determiner.getImplementation(openapiSpec)
+            .prepare(openapiSpec);
         responseSchema = _extractResponseSchema(pathResponseSchema, openapiSpec);
     } catch (err) {
         return createValidationResponse({ errors: [ApplicationError.create(err)] });
@@ -312,7 +318,7 @@ function _extractExamplePaths(openapiSpec, jsonPathToExamples) {
     return jsonPath({
         json: openapiSpec,
         path: jsonPathToExamples,
-        resultType: 'path'
+        resultType: ResultType.path
     });
 }
 
@@ -415,7 +421,7 @@ function _getObjectByPath(path, json) {
         path,
         flatten: true,
         wrap: false,
-        resultType: 'value'
+        resultType: ResultType.value
     });
 }
 
@@ -459,7 +465,8 @@ function _validateExample({ createValidator, responseSchema, example, statistics
  */
 function _initValidatorFactory(specSchema) {
     return getValidatorFactory(specSchema, {
-        allErrors: true
+        allErrors: true,
+        nullable: true
     });
 }
 


Test patch:
diff --git a/test/data/v3/response-invalid-non-nullable.json b/test/data/v3/response-invalid-non-nullable.json
new file mode 100644
index 0000000..381738b
--- /dev/null
+++ b/test/data/v3/response-invalid-non-nullable.json
@@ -0,0 +1,213 @@
+{
+  "openapi": "3.0.0",
+  "info": {
+    "version": "1.0.0",
+    "title": "Swagger Petstore",
+    "license": {
+      "name": "MIT"
+    }
+  },
+  "servers": [
+    {
+      "url": "http://petstore.swagger.io/v1"
+    }
+  ],
+  "paths": {
+    "/pets": {
+      "get": {
+        "summary": "List all pets",
+        "operationId": "listPets",
+        "tags": [
+          "pets"
+        ],
+        "parameters": [
+          {
+            "name": "limit",
+            "in": "query",
+            "description": "How many items to return at one time (max 100)",
+            "required": false,
+            "schema": {
+              "type": "number"
+            }
+          }
+        ],
+        "responses": {
+          "200": {
+            "description": "An paged array of pets",
+            "headers": {
+              "x-next": {
+                "description": "A link to the next page of responses",
+                "schema": {
+                  "type": "string"
+                }
+              }
+            },
+            "content": {
+              "application/json": {
+                "schema": {
+                  "type": "array",
+                  "items": {
+                    "required": [
+                      "id",
+                      "name"
+                    ],
+                    "properties": {
+                      "id": {
+                        "type": "number"
+                      },
+                      "name": {
+                        "type": "string"
+                      },
+                      "tag": {
+                        "type": "string"
+                      },
+                      "age": {
+                        "type": "integer"
+                      }
+                    }
+                  }
+                },
+                "examples": {
+                  "single": {
+                    "value": [
+                      {
+                        "id": 0,
+                        "name": "Herbert",
+                        "tag": "Doggo",
+                        "age": null
+                      }
+                    ]
+                  }
+                }
+              }
+            }
+          },
+          "default": {
+            "description": "unexpected error",
+            "content": {
+              "application/json": {
+                "schema": {
+                  "required": [
+                    "code",
+                    "message"
+                  ],
+                  "properties": {
+                    "code": {
+                      "type": "number"
+                    },
+                    "message": {
+                      "type": "string"
+                    }
+                  }
+                }
+              }
+            }
+          }
+        }
+      },
+      "post": {
+        "summary": "Create a pet",
+        "operationId": "createPets",
+        "tags": [
+          "pets"
+        ],
+        "responses": {
+          "201": {
+            "description": "Null response"
+          },
+          "default": {
+            "description": "unexpected error",
+            "content": {
+              "application/json": {
+                "schema": {
+                  "required": [
+                    "code",
+                    "message"
+                  ],
+                  "properties": {
+                    "code": {
+                      "type": "number"
+                    },
+                    "message": {
+                      "type": "string"
+                    }
+                  }
+                }
+              }
+            }
+          }
+        }
+      }
+    },
+    "/pets/{petId}": {
+      "get": {
+        "summary": "Info for a specific pet",
+        "operationId": "showPetById",
+        "tags": [
+          "pets"
+        ],
+        "parameters": [
+          {
+            "name": "petId",
+            "in": "path",
+            "required": true,
+            "description": "The id of the pet to retrieve",
+            "schema": {
+              "type": "string"
+            }
+          }
+        ],
+        "responses": {
+          "200": {
+            "description": "Expected response to a valid request",
+            "content": {
+              "application/json": {
+                "schema": {
+                  "type": "array",
+                  "items": {
+                    "required": [
+                      "id",
+                      "name"
+                    ],
+                    "properties": {
+                      "id": {
+                        "type": "number"
+                      },
+                      "name": {
+                        "type": "string"
+                      },
+                      "tag": {
+                        "type": "string"
+                      }
+                    }
+                  }
+                }
+              }
+            }
+          },
+          "default": {
+            "description": "unexpected error",
+            "content": {
+              "application/json": {
+                "schema": {
+                  "required": [
+                    "code",
+                    "message"
+                  ],
+                  "properties": {
+                    "code": {
+                      "type": "number"
+                    },
+                    "message": {
+                      "type": "string"
+                    }
+                  }
+                }
+              }
+            }
+          }
+        }
+      }
+    }
+  }
+}
diff --git a/test/data/v3/response-nullable-invalid-definition.json b/test/data/v3/response-nullable-invalid-definition.json
new file mode 100644
index 0000000..7a71ec9
--- /dev/null
+++ b/test/data/v3/response-nullable-invalid-definition.json
@@ -0,0 +1,213 @@
+{
+  "openapi": "3.0.0",
+  "info": {
+    "version": "1.0.0",
+    "title": "Swagger Petstore",
+    "license": {
+      "name": "MIT"
+    }
+  },
+  "servers": [
+    {
+      "url": "http://petstore.swagger.io/v1"
+    }
+  ],
+  "paths": {
+    "/pets": {
+      "get": {
+        "summary": "List all pets",
+        "operationId": "listPets",
+        "tags": [
+          "pets"
+        ],
+        "parameters": [
+          {
+            "name": "limit",
+            "in": "query",
+            "description": "How many items to return at one time (max 100)",
+            "required": false,
+            "schema": {
+              "type": "number"
+            }
+          }
+        ],
+        "responses": {
+          "200": {
+            "description": "An paged array of pets",
+            "headers": {
+              "x-next": {
+                "description": "A link to the next page of responses",
+                "schema": {
+                  "type": "string"
+                }
+              }
+            },
+            "content": {
+              "application/json": {
+                "schema": {
+                  "type": "array",
+                  "items": {
+                    "required": [
+                      "id",
+                      "name"
+                    ],
+                    "properties": {
+                      "id": {
+                        "type": "number"
+                      },
+                      "name": {
+                        "type": "string"
+                      },
+                      "tag": {
+                        "type": "string"
+                      },
+                      "age": {
+                        "nullable": true
+                      }
+                    }
+                  }
+                },
+                "examples": {
+                  "single": {
+                    "value": [
+                      {
+                        "id": 0,
+                        "name": "Herbert",
+                        "tag": "Doggo",
+                        "age": 10
+                      }
+                    ]
+                  }
+                }
+              }
+            }
+          },
+          "default": {
+            "description": "unexpected error",
+            "content": {
+              "application/json": {
+                "schema": {
+                  "required": [
+                    "code",
+                    "message"
+                  ],
+                  "properties": {
+                    "code": {
+                      "type": "number"
+                    },
+                    "message": {
+                      "type": "string"
+                    }
+                  }
+                }
+              }
+            }
+          }
+        }
+      },
+      "post": {
+        "summary": "Create a pet",
+        "operationId": "createPets",
+        "tags": [
+          "pets"
+        ],
+        "responses": {
+          "201": {
+            "description": "Null response"
+          },
+          "default": {
+            "description": "unexpected error",
+            "content": {
+              "application/json": {
+                "schema": {
+                  "required": [
+                    "code",
+                    "message"
+                  ],
+                  "properties": {
+                    "code": {
+                      "type": "number"
+                    },
+                    "message": {
+                      "type": "string"
+                    }
+                  }
+                }
+              }
+            }
+          }
+        }
+      }
+    },
+    "/pets/{petId}": {
+      "get": {
+        "summary": "Info for a specific pet",
+        "operationId": "showPetById",
+        "tags": [
+          "pets"
+        ],
+        "parameters": [
+          {
+            "name": "petId",
+            "in": "path",
+            "required": true,
+            "description": "The id of the pet to retrieve",
+            "schema": {
+              "type": "string"
+            }
+          }
+        ],
+        "responses": {
+          "200": {
+            "description": "Expected response to a valid request",
+            "content": {
+              "application/json": {
+                "schema": {
+                  "type": "array",
+                  "items": {
+                    "required": [
+                      "id",
+                      "name"
+                    ],
+                    "properties": {
+                      "id": {
+                        "type": "number"
+                      },
+                      "name": {
+                        "type": "string"
+                      },
+                      "tag": {
+                        "type": "string"
+                      }
+                    }
+                  }
+                }
+              }
+            }
+          },
+          "default": {
+            "description": "unexpected error",
+            "content": {
+              "application/json": {
+                "schema": {
+                  "required": [
+                    "code",
+                    "message"
+                  ],
+                  "properties": {
+                    "code": {
+                      "type": "number"
+                    },
+                    "message": {
+                      "type": "string"
+                    }
+                  }
+                }
+              }
+            }
+          }
+        }
+      }
+    }
+  }
+}
diff --git a/test/data/v3/response-valid-nullable.json b/test/data/v3/response-valid-nullable.json
new file mode 100644
index 0000000..7430422
--- /dev/null
+++ b/test/data/v3/response-valid-nullable.json
@@ -0,0 +1,242 @@
+{
+  "openapi": "3.0.0",
+  "info": {
+    "version": "1.0.0",
+    "title": "Swagger Petstore",
+    "license": {
+      "name": "MIT"
+    }
+  },
+  "servers": [
+    {
+      "url": "http://petstore.swagger.io/v1"
+    }
+  ],
+  "paths": {
+    "/pets": {
+      "get": {
+        "summary": "List all pets",
+        "operationId": "listPets",
+        "tags": [
+          "pets"
+        ],
+        "parameters": [
+          {
+            "name": "limit",
+            "in": "query",
+            "description": "How many items to return at one time (max 100)",
+            "required": false,
+            "schema": {
+              "type": "number"
+            }
+          }
+        ],
+        "responses": {
+          "200": {
+            "description": "An paged array of pets",
+            "headers": {
+              "x-next": {
+                "description": "A link to the next page of responses",
+                "schema": {
+                  "type": "string"
+                }
+              }
+            },
+            "content": {
+              "application/json": {
+                "schema": {
+                  "type": "array",
+                  "items": {
+                    "required": [
+                      "id",
+                      "name"
+                    ],
+                    "properties": {
+                      "id": {
+                        "type": "number"
+                      },
+                      "name": {
+                        "type": "string"
+                      },
+                      "tag": {
+                        "type": "string"
+                      },
+                      "age": {
+                        "type": "number",
+                        "nullable": true
+                      }
+                    }
+                  }
+                },
+                "examples": {
+                  "single": {
+                    "value": [
+                      {
+                        "id": 0,
+                        "name": "Herbert",
+                        "tag": "Doggo",
+                        "age": null
+                      }
+                    ]
+                  }
+                }
+              }
+            }
+          },
+          "default": {
+            "description": "unexpected error",
+            "content": {
+              "application/json": {
+                "schema": {
+                  "required": [
+                    "code",
+                    "message"
+                  ],
+                  "properties": {
+                    "code": {
+                      "type": "number"
+                    },
+                    "message": {
+                      "type": "string"
+                    }
+                  }
+                }
+              }
+            }
+          }
+        }
+      },
+      "post": {
+        "summary": "Create a pet",
+        "operationId": "createPets",
+        "tags": [
+          "pets"
+        ],
+        "responses": {
+          "201": {
+            "description": "Null response"
+          },
+          "default": {
+            "description": "unexpected error",
+            "content": {
+              "application/json": {
+                "schema": {
+                  "required": [
+                    "code",
+                    "message"
+                  ],
+                  "properties": {
+                    "code": {
+                      "type": "number"
+                    },
+                    "message": {
+                      "type": "string"
+                    }
+                  }
+                }
+              }
+            }
+          }
+        }
+      }
+    },
+    "/pets/{petId}": {
+      "get": {
+        "summary": "Info for a specific pet",
+        "operationId": "showPetById",
+        "tags": [
+          "pets"
+        ],
+        "parameters": [
+          {
+            "name": "petId",
+            "in": "path",
+            "required": true,
+            "description": "The id of the pet to retrieve",
+            "schema": {
+              "type": "string"
+            }
+          }
+        ],
+        "responses": {
+          "200": {
+            "description": "Expected response to a valid request",
+            "content": {
+              "application/json": {
+                "schema": {
+                  "type": "array",
+                  "items": {
+                    "required": [
+                      "id",
+                      "name"
+                    ],
+                    "properties": {
+                      "id": {
+                        "type": "number"
+                      },
+                      "name": {
+                        "type": "string"
+                      },
+                      "tag": {
+                        "type": "string"
+                      },
+                      "age": {
+                        "type": "integer",
+                        "nullable": true
+                      }
+                    }
+                  }
+                },
+                "examples": {
+                  "withAgeNull": {
+                    "summary": "Example with a `null` age",
+                    "value": [
+                      {
+                        "id": 0,
+                        "name": "Fluffy",
+                        "tag": "Cat",
+                        "age": null
+                      }
+                    ]
+                  },
+                  "withAgeSet": {
+                    "summary": "Example with a set age",
+                    "value": [
+                      {
+                        "id": 0,
+                        "name": "Fluffy",
+                        "tag": "Cat",
+                        "age": 5
+                      }
+                    ]
+                  }
+                }
+              }
+            }
+          },
+          "default": {
+            "description": "unexpected error",
+            "content": {
+              "application/json": {
+                "schema": {
+                  "required": [
+                    "code",
+                    "message"
+                  ],
+                  "properties": {
+                    "code": {
+                      "type": "number"
+                    },
+                    "message": {
+                      "type": "string"
+                    }
+                  }
+                }
+              }
+            }
+          }
+        }
+      }
+    }
+  }
+}
diff --git a/test/specs/impl/v3/index.js b/test/specs/impl/v3/index.js
index 6242e42..172c989 100644
--- a/test/specs/impl/v3/index.js
+++ b/test/specs/impl/v3/index.js
@@ -15,9 +15,13 @@ const JSON_PATH__CONTEXT_MUTUALLY_EXCLUSIVE = '/paths/~1pets/get/responses/200/c
     FILE_PATH__VALID__REQUEST_PARAMETER = path.join(__dirname, '../../../data/v3/request-valid-parameter.json'),
     FILE_PATH__VALID__REQUEST_PARAMETER__EXAMPLES
         = path.join(__dirname, '../../../data/v3/request-valid-parameter-examples.json'),
+    FILE_PATH__NULLABLE_INVALID_DEFINITION
+        = path.join(__dirname, '../../../data/v3/response-nullable-invalid-definition.json'),
+    FILE_PATH__INVALID__NON_NULLABLE = path.join(__dirname, '../../../data/v3/response-invalid-non-nullable.json'),
     FILE_PATH__INVALID__REQUEST_PARAMETER = path.join(__dirname, '../../../data/v3/request-invalid-parameter.json'),
     FILE_PATH__INVALID__REQUEST_PARAMETER__EXAMPLES
         = path.join(__dirname, '../../../data/v3/request-invalid-parameter-examples.json'),
+    FILE_PATH__VALID__NULLABLE = path.join(__dirname, '../../../data/v3/response-valid-nullable.json'),
     FILE_PATH__VALID__REQUEST_BODY = path.join(__dirname, '../../../data/v3/request-valid-requestbody.json'),
     FILE_PATH__VALID__REQUEST_BODY__EXAMPLES
         = path.join(__dirname, '../../../data/v3/request-valid-requestbody-examples.json'),
@@ -114,4 +118,16 @@ describe('Main-module, for v3 should', function() {
             });
         });
     });
+    describe('be able to handle `nullable`-types', function() {
+        it('with `null` for non-nullable-type', function() {
+            validateFile(FILE_PATH__INVALID__NON_NULLABLE).valid.should.equal(false);
+        });
+        it('with nullable property', function() {
+            validateFile(FILE_PATH__VALID__NULLABLE).valid.should.equal(true);
+        });
+        it('with nullable property, but no type set', function() {
+            // Nullable will be ignored, if no `type` is set
+            validateFile(FILE_PATH__NULLABLE_INVALID_DEFINITION).valid.should.equal(true);
+        });
+    });
 });