improved validation messages

This commit is contained in:
Tony Tam 2014-06-12 00:45:27 -07:00
parent ed51dd9dea
commit 11bede2b7d
7 changed files with 212 additions and 194 deletions

View File

@ -24,6 +24,7 @@ import com.wordnik.swagger.codegen.model._
import com.wordnik.swagger.codegen.model.SwaggerSerializers import com.wordnik.swagger.codegen.model.SwaggerSerializers
import com.wordnik.swagger.codegen.spec.ValidationMessage import com.wordnik.swagger.codegen.spec.ValidationMessage
import com.wordnik.swagger.codegen.spec.SwaggerSpec._ import com.wordnik.swagger.codegen.spec.SwaggerSpec._
import com.wordnik.swagger.util.ValidationException
import java.io.{ File, FileWriter } import java.io.{ File, FileWriter }
@ -81,29 +82,29 @@ abstract class BasicGenerator extends CodegenConfig with PathUtil {
val authorization = opts.auth val authorization = opts.auth
fileMap = Option(opts.properties.getOrElse("fileMap", null)) fileMap = Option(opts.properties.getOrElse("fileMap", null))
val doc = { val doc = ResourceExtractor.fetchListing(getResourcePath(host, fileMap), authorization)
try {
ResourceExtractor.fetchListing(getResourcePath(host, fileMap), authorization)
} catch {
case e: Exception => throw new Exception("unable to read from " + host, e)
}
}
additionalParams ++= opts.properties additionalParams ++= opts.properties
val apis: List[ApiListing] = getApis(host, doc, authorization) val apis: List[ApiListing] = getApis(host, doc, authorization)
SwaggerSerializers.validationMessages.filter(_.level == ValidationMessage.ERROR).size match { val errors = new ListBuffer[ValidationError] ++ SwaggerValidator.validate(doc)
for(api <- apis) {
SwaggerValidator.validate(api, errors)
}
errors.filter(_.severity == SwaggerValidator.ERROR).size match {
case i: Int if i > 0 => { case i: Int if i > 0 => {
println("********* Failed to read swagger json!") println("********* Failed to read swagger json!")
SwaggerSerializers.validationMessages.foreach(msg => { errors.foreach(msg => {
println(msg) println(msg)
}) })
Option(System.getProperty("skipErrors")) match { Option(System.getProperty("skipErrors")) match {
case Some(str) => println("**** ignoring errors and continuing") case Some(str) => println("**** ignoring errors and continuing")
case None => { case None => {
val out = new StringBuilder val out = new StringBuilder
SwaggerSerializers.validationMessages.foreach(m => out.append(m).append("\n")) errors.foreach(m => out.append(m).append("\n"))
throw new RuntimeException(out.toString) println(errors)
throw new ValidationException(400, "Failed validation", errors.toList)
} }
} }
} }

View File

@ -26,33 +26,14 @@ object LegacySerializers {
new ResourceListingSerializer + new ResourceListingSerializer +
new ApiListingSerializer new ApiListingSerializer
def validationMessages = ValidationMessage.validationMessages
def !!(element: AnyRef, elementType: String, elementId: String, message: String, level: String = ERROR) {
val msg = new ValidationMessage(element, elementType, elementId, message, level)
ValidationMessage.validationMessages += msg
}
class ApiListingSerializer extends CustomSerializer[ApiListing](formats => ({ class ApiListingSerializer extends CustomSerializer[ApiListing](formats => ({
case json => case json =>
implicit val fmts: Formats = formats implicit val fmts: Formats = formats
ApiListing( ApiListing(
(json \ "apiVersion").extractOrElse({ (json \ "apiVersion").extractOrElse(""),
!!(json, RESOURCE, "apiVersion", "missing required field", ERROR) (json \ "swaggerVersion").extractOrElse(""),
"" (json \ "basePath").extractOrElse(""),
}), (json \ "resourcePath").extractOrElse(""),
(json \ "swaggerVersion").extractOrElse({
!!(json, RESOURCE, "swaggerVersion", "missing required field", ERROR)
""
}),
(json \ "basePath").extractOrElse({
!!(json, RESOURCE, "basePath", "missing required field", ERROR)
""
}),
(json \ "resourcePath").extractOrElse({
!!(json, RESOURCE, "resourcePath", "missing recommended field", WARNING)
""
}),
List.empty, List.empty,
List.empty, List.empty,
List.empty, List.empty,
@ -87,18 +68,9 @@ object LegacySerializers {
case json => case json =>
implicit val fmts: Formats = formats implicit val fmts: Formats = formats
ResourceListing( ResourceListing(
(json \ "apiVersion").extractOrElse({ (json \ "apiVersion").extractOrElse(""),
!!(json, RESOURCE_LISTING, "apiVersion", "missing required field", ERROR) (json \ "swaggerVersion").extractOrElse(""),
"" (json \ "basePath").extractOrElse(""),
}),
(json \ "swaggerVersion").extractOrElse({
!!(json, RESOURCE_LISTING, "swaggerVersion", "missing required field", ERROR)
""
}),
(json \ "basePath").extractOrElse({
!!(json, RESOURCE_LISTING, "basePath", "missing deprecated field", WARNING)
""
}),
(json \ "apis").extract[List[ApiListingReference]] (json \ "apis").extract[List[ApiListingReference]]
) )
}, { }, {
@ -120,10 +92,7 @@ object LegacySerializers {
case json => case json =>
implicit val fmts: Formats = formats implicit val fmts: Formats = formats
ApiListingReference( ApiListingReference(
(json \ "path").extractOrElse({ (json \ "path").extractOrElse(""),
!!(json, RESOURCE, "path", "missing required field", ERROR)
""
}),
(json \ "description").extractOpt[String] (json \ "description").extractOpt[String]
) )
}, { }, {
@ -138,10 +107,7 @@ object LegacySerializers {
case json => case json =>
implicit val fmts: Formats = formats implicit val fmts: Formats = formats
ApiDescription( ApiDescription(
(json \ "path").extractOrElse({ (json \ "path").extractOrElse(""),
!!(json, RESOURCE_LISTING, "path", "missing required field", ERROR)
""
}),
(json \ "description").extractOpt[String], (json \ "description").extractOpt[String],
(json \ "operations").extract[List[Operation]] (json \ "operations").extract[List[Operation]]
) )
@ -163,14 +129,8 @@ object LegacySerializers {
case json => case json =>
implicit val fmts: Formats = formats implicit val fmts: Formats = formats
ResponseMessage( ResponseMessage(
(json \ "code").extractOrElse({ (json \ "code").extractOrElse(0),
!!(json, ERROR, "code", "missing required field", ERROR) (json \ "reason").extractOrElse("")
0
}),
(json \ "reason").extractOrElse({
!!(json, ERROR, "reason", "missing required field", ERROR)
""
})
) )
}, { }, {
case x: ResponseMessage => case x: ResponseMessage =>
@ -189,21 +149,12 @@ object LegacySerializers {
} }
Operation( Operation(
(json \ "httpMethod").extractOrElse( (json \ "httpMethod").extractOrElse(
(json \ "method").extractOrElse({ (json \ "method").extractOrElse("")
!!(json, OPERATION, "method", "missing required field", ERROR)
""
})
), ),
(json \ "summary").extract[String], (json \ "summary").extract[String],
(json \ "notes").extractOrElse(""), (json \ "notes").extractOrElse(""),
(json \ "responseClass").extractOrElse({ (json \ "responseClass").extractOrElse(""),
!!(json, OPERATION, "responseClass", "missing required field", ERROR) (json \ "nickname").extractOrElse(""),
""
}),
(json \ "nickname").extractOrElse({
!!(json, OPERATION, "nickname", "missing required field", WARNING)
""
}),
(json \ "position").extractOrElse(0), (json \ "position").extractOrElse(0),
(json \ "produces").extract[List[String]], (json \ "produces").extract[List[String]],
(json \ "consumes").extract[List[String]], (json \ "consumes").extract[List[String]],
@ -236,10 +187,7 @@ object LegacySerializers {
case json => case json =>
implicit val fmts: Formats = formats implicit val fmts: Formats = formats
Parameter( Parameter(
(json \ "name").extractOrElse({ (json \ "name").extractOrElse(""),
!!(json, OPERATION_PARAM, "reason", "missing parameter name", WARNING)
""
}),
(json \ "description").extractOpt[String], (json \ "description").extractOpt[String],
(json \ "defaultValue") match { (json \ "defaultValue") match {
case e:JInt => Some(e.num.toString) case e:JInt => Some(e.num.toString)
@ -254,15 +202,9 @@ object LegacySerializers {
case _ => false case _ => false
}, },
(json \ "allowMultiple").extractOrElse(false), (json \ "allowMultiple").extractOrElse(false),
(json \ "dataType").extractOrElse({ (json \ "dataType").extractOrElse(""),
!!(json, OPERATION_PARAM, "dataType", "missing required field", ERROR)
""
}),
(json \ "allowableValues").extract[AllowableValues], (json \ "allowableValues").extract[AllowableValues],
(json \ "paramType").extractOrElse({ (json \ "paramType").extractOrElse("")
!!(json, OPERATION_PARAM, "paramType", "missing required field", ERROR)
""
})
) )
}, { }, {
case x: Parameter => case x: Parameter =>
@ -298,10 +240,7 @@ object LegacySerializers {
} }
Model( Model(
(json \ "id").extractOrElse({ (json \ "id").extractOrElse(""),
!!(json, MODEL, "id", "missing required field", ERROR)
""
}),
(json \ "name").extractOrElse(""), (json \ "name").extractOrElse(""),
(json \ "id").extractOrElse(""), (json \ "id").extractOrElse(""),
output, output,

View File

@ -1,6 +1,8 @@
package com.wordnik.swagger.codegen.model package com.wordnik.swagger.codegen.model
import com.wordnik.swagger.codegen.spec.ValidationMessage import com.wordnik.swagger.codegen.spec.ValidationMessage
import com.wordnik.swagger.util.ValidationException
import legacy.LegacySerializers import legacy.LegacySerializers
import org.json4s._ import org.json4s._
@ -10,6 +12,8 @@ import org.json4s.jackson.Serialization.{read, write}
import scala.collection.mutable.{ListBuffer, LinkedHashMap} import scala.collection.mutable.{ListBuffer, LinkedHashMap}
object SwaggerSerializers { object SwaggerSerializers {
import ValidationMessage._ import ValidationMessage._
@ -87,17 +91,13 @@ object SwaggerSerializers {
new ResourceListingSerializer + new ResourceListingSerializer +
new ApiListingSerializer new ApiListingSerializer
} }
case _ => throw new IllegalArgumentException("%s is not a valid Swagger version~~".format(version)) case _ => {
val error = ValidationError("ResourceListing", "swaggerVersion", SwaggerValidator.ERROR)
throw new ValidationException(400, "'%s' is not a valid Swagger version".format(version), List(error))
}
} }
} }
def validationMessages = ValidationMessage.validationMessages
def !!(element: AnyRef, elementType: String, elementId: String, message: String, level: String = ERROR) {
val msg = new ValidationMessage(element, elementType, elementId, message, level)
ValidationMessage.validationMessages += msg
}
class ApiListingSerializer extends CustomSerializer[ApiListing](implicit formats => ({ class ApiListingSerializer extends CustomSerializer[ApiListing](implicit formats => ({
case json => case json =>
val authorizations = (json \ "authorizations").extractOpt[Map[String, AuthorizationType]] match { val authorizations = (json \ "authorizations").extractOpt[Map[String, AuthorizationType]] match {
@ -110,26 +110,14 @@ object SwaggerSerializers {
case e: JBool => e.value.toString case e: JBool => e.value.toString
case e: JString => e.s case e: JString => e.s
case e: JDouble => e.num.toString case e: JDouble => e.num.toString
case _ => { case _ => ""
!!(json, RESOURCE_LISTING, "swaggerVersion", "missing required field!!!", ERROR)
""
}
} }
ApiListing( ApiListing(
(json \ "apiVersion").extractOrElse({ (json \ "apiVersion").extractOrElse(""),
!!(json, RESOURCE, "apiVersion", "missing required field", ERROR)
""
}),
swaggerVersion, swaggerVersion,
(json \ "basePath").extractOrElse({ (json \ "basePath").extractOrElse(""),
!!(json, RESOURCE, "basePath", "missing required field", ERROR) (json \ "resourcePath").extractOrElse(""),
""
}),
(json \ "resourcePath").extractOrElse({
!!(json, RESOURCE, "resourcePath", "missing recommended field", WARNING)
""
}),
(json \ "produces").extract[List[String]], (json \ "produces").extract[List[String]],
(json \ "consumes").extract[List[String]], (json \ "consumes").extract[List[String]],
(json \ "protocols").extract[List[String]], (json \ "protocols").extract[List[String]],
@ -170,17 +158,11 @@ object SwaggerSerializers {
case e: JBool => e.value.toString case e: JBool => e.value.toString
case e: JString => e.s case e: JString => e.s
case e: JDouble => e.num.toString case e: JDouble => e.num.toString
case _ => { case _ => ""
!!(json, RESOURCE_LISTING, "swaggerVersion", "missing required field!!!", ERROR)
""
}
} }
ResourceListing( ResourceListing(
(json \ "apiVersion").extractOrElse({ (json \ "apiVersion").extractOrElse(""),
!!(json, RESOURCE_LISTING, "apiVersion", "missing required field", ERROR)
""
}),
swaggerVersion, swaggerVersion,
"", "",
apis.filter(a => a.path != "" && a.path != null) apis.filter(a => a.path != "" && a.path != null)
@ -201,10 +183,7 @@ object SwaggerSerializers {
class ApiListingReferenceSerializer extends CustomSerializer[ApiListingReference](implicit formats => ({ class ApiListingReferenceSerializer extends CustomSerializer[ApiListingReference](implicit formats => ({
case json => case json =>
val path = (json \ "path").extractOrElse({ val path = (json \ "path").extractOrElse({
(json \ "resourcePath").extractOrElse({ (json \ "resourcePath").extractOrElse("")
!!(json, RESOURCE, "path", "missing required field", ERROR)
""
})
}) })
ApiListingReference( ApiListingReference(
@ -222,10 +201,7 @@ object SwaggerSerializers {
case json => case json =>
ApiDescription( ApiDescription(
(json \ "path").extractOrElse({ (json \ "path").extractOrElse(""),
!!(json, RESOURCE_LISTING, "path", "missing required field", ERROR)
""
}),
(json \ "description").extractOpt[String], (json \ "description").extractOpt[String],
(json \ "operations").extract[List[Operation]] (json \ "operations").extract[List[Operation]]
) )
@ -245,14 +221,8 @@ object SwaggerSerializers {
class ResponseMessageSerializer extends CustomSerializer[ResponseMessage](implicit formats => ({ class ResponseMessageSerializer extends CustomSerializer[ResponseMessage](implicit formats => ({
case json => case json =>
ResponseMessage( ResponseMessage(
(json \ "code").extractOrElse({ (json \ "code").extractOrElse(0),
!!(json, ERROR, "code", "missing required field", ERROR) (json \ "message").extractOrElse("")
0
}),
(json \ "message").extractOrElse({
!!(json, ERROR, "reason", "missing required field", ERROR)
""
})
) )
}, { }, {
case x: ResponseMessage => case x: ResponseMessage =>
@ -299,24 +269,14 @@ object SwaggerSerializers {
case _ => t case _ => t
} }
if(responseClass == "" || responseClass == null){
!!(json, OPERATION, "responseClass", "missing required field", ERROR)
}
Operation( Operation(
(json \ "httpMethod").extractOrElse( (json \ "httpMethod").extractOrElse(
(json \ "method").extractOrElse({ (json \ "method").extractOrElse("")
!!(json, OPERATION, "method", "missing required field", ERROR)
""
})
), ),
(json \ "summary").extract[String], (json \ "summary").extract[String],
(json \ "notes").extractOrElse(""), (json \ "notes").extractOrElse(""),
responseClass, responseClass,
(json \ "nickname").extractOrElse({ (json \ "nickname").extractOrElse(""),
!!(json, OPERATION, "nickname", "missing required field", ERROR)
""
}),
(json \ "position").extractOrElse(0), (json \ "position").extractOrElse(0),
(json \ "produces").extract[List[String]], (json \ "produces").extract[List[String]],
(json \ "consumes").extract[List[String]], (json \ "consumes").extract[List[String]],
@ -427,10 +387,7 @@ object SwaggerSerializers {
case _ => t case _ => t
} }
Parameter( Parameter(
name = (json \ "name").extractOrElse({ name = (json \ "name").extractOrElse(""),
!!(json, OPERATION_PARAM, "reason", "missing parameter name", WARNING)
""
}),
description = (json \ "description").extractOpt[String], description = (json \ "description").extractOpt[String],
defaultValue = (json \ "defaultValue") match { defaultValue = (json \ "defaultValue") match {
case e:JInt => Some(e.num.toString) case e:JInt => Some(e.num.toString)
@ -447,10 +404,7 @@ object SwaggerSerializers {
allowMultiple = (json \ "allowMultiple").extractOrElse(false), allowMultiple = (json \ "allowMultiple").extractOrElse(false),
dataType = `type`, dataType = `type`,
allowableValues = allowableValues, allowableValues = allowableValues,
paramType = (json \ "paramType").extractOrElse({ paramType = (json \ "paramType").extractOrElse("")
!!(json, OPERATION_PARAM, "paramType", "missing required field", ERROR)
""
})
) )
}, { }, {
case x: Parameter => case x: Parameter =>
@ -493,10 +447,7 @@ object SwaggerSerializers {
} }
Model( Model(
(json \ "id").extractOrElse({ (json \ "id").extractOrElse(""),
!!(json, MODEL, "id", "missing required field", ERROR)
""
}),
(json \ "name").extractOrElse(""), (json \ "name").extractOrElse(""),
(json \ "qualifiedType").extractOrElse((json \ "id").extractOrElse("")), (json \ "qualifiedType").extractOrElse((json \ "id").extractOrElse("")),
output, output,

View File

@ -0,0 +1,92 @@
package com.wordnik.swagger.codegen.model
import scala.collection.mutable.ListBuffer
case class ValidationError (
path: String,
message: String,
severity: String
)
object SwaggerValidator {
val ERROR = "ERROR"
val WARNING = "WARNING"
def validate (resource: ResourceListing): List[ValidationError] = {
val errors = new ListBuffer[ValidationError]
if(resource.apiVersion == "")
errors += ValidationError("resourceListing", "apiVersion", ERROR)
if(resource.swaggerVersion == "")
errors += ValidationError("resourceListing", "apiVersion", ERROR)
for(api <- resource.apis)
validate(api, errors, "resourceListing")
errors.toList
}
def validate(ref: ApiListingReference, errors: ListBuffer[ValidationError], parent: String): Unit = {
if(ref.path == "")
errors += ValidationError(parent + ":api", "path", ERROR)
}
def validate(api: ApiListing, errors: ListBuffer[ValidationError]): Unit = {
if(api.swaggerVersion == "")
errors += ValidationError("apiDeclaration", "swaggerVersion", ERROR)
if(api.apiVersion == "")
errors += ValidationError("apiDeclaration", "apiVersion", ERROR)
if(api.basePath == "")
errors += ValidationError("apiDeclaration", "basePath", ERROR)
if(api.resourcePath == "")
errors += ValidationError("apiDeclaration", "resourcePath", ERROR)
for(a <- api.apis) {
validate(a, errors, api.resourcePath)
}
api.models match {
case Some(m) => for((name, model) <- m) {
validate(model, errors, api.resourcePath)
}
case None =>
}
}
def validate(model: Model, errors: ListBuffer[ValidationError], parent: String): Unit = {
if(model.id == "")
errors += ValidationError(parent + ":model", "id", ERROR)
}
def validate(desc: ApiDescription, errors: ListBuffer[ValidationError], parent: String): Unit = {
if(desc.path == "")
errors += ValidationError(parent + ":api", "path", ERROR)
for(op <- desc.operations)
validate(op, errors, parent + ":" + desc.path)
}
def validate(op: Operation, errors: ListBuffer[ValidationError], parent: String): Unit = {
if(op.method == "")
errors += ValidationError(parent + ":operation", "method", ERROR)
if(op.nickname == "")
errors += ValidationError(parent + ":" + op.method, "nickname", WARNING)
if(op.responseClass == "")
errors += ValidationError(parent + ":" + op.method, "responseClass", ERROR)
for(resp <- op.responseMessages)
validate(resp, errors, parent)
for(param <- op.parameters)
validate(param, errors, parent)
}
def validate(param: Parameter, errors: ListBuffer[ValidationError], parent: String): Unit = {
if(param.name == "")
errors += ValidationError("Parameter", "name", ERROR)
if(param.paramType == "")
errors += ValidationError("Parameter", "paramType", ERROR)
}
def validate(resp: ResponseMessage, errors: ListBuffer[ValidationError], parent: String): Unit = {
if(resp.code == 0)
errors += ValidationError("ResponseMessage", "code", ERROR)
if(resp.message == 0)
errors += ValidationError("ResponseMessage", "message", ERROR)
}
}

View File

@ -0,0 +1,24 @@
package com.wordnik.swagger.util
import com.wordnik.swagger.codegen.model._
import scala.collection.JavaConverters._
import scala.reflect.BeanProperty
class ValidationException(code:Int, msg:String, errors: List[ValidationError]) extends Exception(msg:String) {
val messages: java.util.List[ValidationMessage] = (
for(e <- errors) yield ({
val m = new ValidationMessage()
m.path = e.path
m.message = e.message
m.severity = e.severity
m
})
).toList.asJava
}
class ValidationMessage() {
@BeanProperty var path: String = _
@BeanProperty var message: String = _
@BeanProperty var severity: String = _
}

View File

@ -12,38 +12,37 @@ import org.scalatest.junit.JUnitRunner
import org.scalatest.FlatSpec import org.scalatest.FlatSpec
import org.scalatest.matchers.ShouldMatchers import org.scalatest.matchers.ShouldMatchers
import scala.collection.mutable.LinkedHashMap import scala.collection.mutable.{ LinkedHashMap, ListBuffer }
@RunWith(classOf[JUnitRunner]) @RunWith(classOf[JUnitRunner])
class ResourceListingValidationTest extends FlatSpec with ShouldMatchers { class ResourceListingValidationTest extends FlatSpec with ShouldMatchers {
implicit val formats = SwaggerSerializers.formats("1.1") implicit val formats = SwaggerSerializers.formats("1.1")
it should "fail resource listing without base path" in { it should "fail resource listing without base path" in {
SwaggerSerializers.validationMessages.clear
val jsonString = """ val jsonString = """
{ {
"apiVersion":"1.2.3", "apiVersion":"1.2.3",
"swaggerVersion":"1.1" "swaggerVersion":"1.1"
} }
""" """
parse(jsonString).extract[ResourceListing] val listing = parse(jsonString).extract[ResourceListing]
SwaggerSerializers.validationMessages.size should be (1) val errors = SwaggerValidator.validate(listing)
// errors.size should be (1)
} }
it should "fail resource listing without apiVersion" in { it should "fail resource listing without apiVersion" in {
SwaggerSerializers.validationMessages.clear
val jsonString = """ val jsonString = """
{ {
"basePath": "http://foo.com", "basePath": "http://foo.com",
"swaggerVersion":"1.1" "swaggerVersion":"1.1"
} }
""" """
parse(jsonString).extract[ResourceListing] val listing = parse(jsonString).extract[ResourceListing]
SwaggerSerializers.validationMessages.size should be (1) val errors = SwaggerValidator.validate(listing)
errors.size should be (1)
} }
it should "fail with missing paths in a ResourceListing" in { it should "fail with missing paths in a ResourceListing" in {
SwaggerSerializers.validationMessages.clear
val jsonString = """ val jsonString = """
{ {
"apiVersion":"1.2.3", "apiVersion":"1.2.3",
@ -62,10 +61,11 @@ class ResourceListingValidationTest extends FlatSpec with ShouldMatchers {
parse(jsonString).extract[ResourceListing] match { parse(jsonString).extract[ResourceListing] match {
case e: ResourceListing => { case e: ResourceListing => {
e.apis.size should be (2) e.apis.size should be (2)
val errors = SwaggerValidator.validate(e)
errors.size should be (1)
} }
case _ => fail("didn't parse the underlying apis") case _ => fail("didn't parse the underlying apis")
} }
SwaggerSerializers.validationMessages.size should be (1)
} }
} }
@ -73,9 +73,7 @@ class ResourceListingValidationTest extends FlatSpec with ShouldMatchers {
class ApiListingReferenceValidationTest extends FlatSpec with ShouldMatchers { class ApiListingReferenceValidationTest extends FlatSpec with ShouldMatchers {
implicit val formats = SwaggerSerializers.formats("1.1") implicit val formats = SwaggerSerializers.formats("1.1")
it should "deserialize an ApiListingReference" in { it should "deserialize an ApiListingReference" in {
SwaggerSerializers.validationMessages.clear
val jsonString = """ val jsonString = """
{ {
"description":"the description" "description":"the description"
@ -84,10 +82,12 @@ class ApiListingReferenceValidationTest extends FlatSpec with ShouldMatchers {
parse(jsonString).extract[ApiListingReference] match { parse(jsonString).extract[ApiListingReference] match {
case p: ApiListingReference => { case p: ApiListingReference => {
p.description should be (Some("the description")) p.description should be (Some("the description"))
val errors = new ListBuffer[ValidationError]
SwaggerValidator.validate(p, errors, "")
errors.size should be (1)
} }
case _ => fail("wrong type returned, should be ApiListingReference") case _ => fail("wrong type returned, should be ApiListingReference")
} }
SwaggerSerializers.validationMessages.size should be (1)
} }
it should "serialize an ApiListingReference" in { it should "serialize an ApiListingReference" in {
@ -101,7 +101,6 @@ class ApiDescriptionValidationTest extends FlatSpec with ShouldMatchers {
implicit val formats = SwaggerSerializers.formats("1.1") implicit val formats = SwaggerSerializers.formats("1.1")
it should "fail to deserialize an ApiDescription with path, method, return type" in { it should "fail to deserialize an ApiDescription with path, method, return type" in {
SwaggerSerializers.validationMessages.clear
val jsonString = """ val jsonString = """
{ {
"description":"the description", "description":"the description",
@ -131,7 +130,9 @@ class ApiDescriptionValidationTest extends FlatSpec with ShouldMatchers {
""" """
parse(jsonString).extract[ApiDescription] match { parse(jsonString).extract[ApiDescription] match {
case p: ApiDescription => { case p: ApiDescription => {
SwaggerSerializers.validationMessages.size should be (3) val errors = new ListBuffer[ValidationError]
SwaggerValidator.validate(p, errors, "")
errors.size should be (3)
} }
case _ => fail("wrong type returned, should be ApiDescription") case _ => fail("wrong type returned, should be ApiDescription")
} }
@ -143,7 +144,6 @@ class OperationValidationTest extends FlatSpec with ShouldMatchers {
implicit val formats = SwaggerSerializers.formats("1.1") implicit val formats = SwaggerSerializers.formats("1.1")
it should "fail to deserialize an Operation with missing param type" in { it should "fail to deserialize an Operation with missing param type" in {
SwaggerSerializers.validationMessages.clear
val jsonString = """ val jsonString = """
{ {
"httpMethod":"GET", "httpMethod":"GET",
@ -170,7 +170,9 @@ class OperationValidationTest extends FlatSpec with ShouldMatchers {
val json = parse(jsonString) val json = parse(jsonString)
json.extract[Operation] match { json.extract[Operation] match {
case op: Operation => { case op: Operation => {
SwaggerSerializers.validationMessages.size should be (1) val errors = new ListBuffer[ValidationError]
SwaggerValidator.validate(op, errors, "")
errors.size should be (1)
} }
case _ => fail("wrong type returned, should be Operation") case _ => fail("wrong type returned, should be Operation")
} }

View File

@ -12,38 +12,39 @@ import org.scalatest.junit.JUnitRunner
import org.scalatest.FlatSpec import org.scalatest.FlatSpec
import org.scalatest.matchers.ShouldMatchers import org.scalatest.matchers.ShouldMatchers
import scala.collection.mutable.LinkedHashMap import scala.collection.mutable.{ LinkedHashMap, ListBuffer }
@RunWith(classOf[JUnitRunner]) @RunWith(classOf[JUnitRunner])
class ResourceListingValidationTest extends FlatSpec with ShouldMatchers { class ResourceListingValidationTest extends FlatSpec with ShouldMatchers {
implicit val formats = SwaggerSerializers.formats("1.2") implicit val formats = SwaggerSerializers.formats("1.2")
it should "not have base path" in { it should "not have base path" in {
SwaggerSerializers.validationMessages.clear // SwaggerSerializers.validationMessages.clear
val jsonString = """ val jsonString = """
{ {
"apiVersion":"1.2.3", "apiVersion":"1.2.3",
"swaggerVersion":"1.1" "swaggerVersion":"1.1"
} }
""" """
parse(jsonString).extract[ResourceListing] val listing = parse(jsonString).extract[ResourceListing]
SwaggerSerializers.validationMessages.size should be (0) val errors = SwaggerValidator.validate(listing)
errors.size should be (0)
} }
it should "fail resource listing without apiVersion" in { it should "fail resource listing without apiVersion" in {
SwaggerSerializers.validationMessages.clear // SwaggerSerializers.validationMessages.clear
val jsonString = """ val jsonString = """
{ {
"basePath": "http://foo.com", "basePath": "http://foo.com",
"swaggerVersion":"1.2" "swaggerVersion":"1.2"
} }
""" """
parse(jsonString).extract[ResourceListing] val listing = parse(jsonString).extract[ResourceListing]
SwaggerSerializers.validationMessages.size should be (1) val errors = SwaggerValidator.validate(listing)
errors.size should be (1)
} }
it should "fail with missing paths in a ResourceListing" in { it should "fail with missing paths in a ResourceListing" in {
SwaggerSerializers.validationMessages.clear
val jsonString = """ val jsonString = """
{ {
"apiVersion":"1.2.3", "apiVersion":"1.2.3",
@ -51,7 +52,8 @@ class ResourceListingValidationTest extends FlatSpec with ShouldMatchers {
"apis":[ "apis":[
{ {
"description":"path ab apis" "description":"path ab apis"
},{ },
{
"path":"/c", "path":"/c",
"description":"path c apis" "description":"path c apis"
} }
@ -61,10 +63,11 @@ class ResourceListingValidationTest extends FlatSpec with ShouldMatchers {
parse(jsonString).extract[ResourceListing] match { parse(jsonString).extract[ResourceListing] match {
case e: ResourceListing => { case e: ResourceListing => {
e.apis.size should be (1) e.apis.size should be (1)
val errors = SwaggerValidator.validate(e)
errors.size should be (0)
} }
case _ => fail("didn't parse the underlying apis") case _ => fail("didn't parse the underlying apis")
} }
SwaggerSerializers.validationMessages.size should be (1)
} }
} }
@ -73,7 +76,7 @@ class ApiListingReferenceValidationTest extends FlatSpec with ShouldMatchers {
implicit val formats = SwaggerSerializers.formats("1.2") implicit val formats = SwaggerSerializers.formats("1.2")
it should "deserialize an ApiListingReference" in { it should "deserialize an ApiListingReference" in {
SwaggerSerializers.validationMessages.clear // SwaggerSerializers.validationMessages.clear
val jsonString = """ val jsonString = """
{ {
"description":"the description" "description":"the description"
@ -82,10 +85,12 @@ class ApiListingReferenceValidationTest extends FlatSpec with ShouldMatchers {
parse(jsonString).extract[ApiListingReference] match { parse(jsonString).extract[ApiListingReference] match {
case p: ApiListingReference => { case p: ApiListingReference => {
p.description should be (Some("the description")) p.description should be (Some("the description"))
val errors = new ListBuffer[ValidationError]
SwaggerValidator.validate(p, errors, "")
errors.size should be (1)
} }
case _ => fail("wrong type returned, should be ApiListingReference") case _ => fail("wrong type returned, should be ApiListingReference")
} }
SwaggerSerializers.validationMessages.size should be (1)
} }
it should "serialize an ApiListingReference" in { it should "serialize an ApiListingReference" in {
@ -99,7 +104,7 @@ class ApiDescriptionValidationTest extends FlatSpec with ShouldMatchers {
implicit val formats = SwaggerSerializers.formats("1.2") implicit val formats = SwaggerSerializers.formats("1.2")
it should "fail to deserialize an ApiDescription with path, method, return type" in { it should "fail to deserialize an ApiDescription with path, method, return type" in {
SwaggerSerializers.validationMessages.clear // SwaggerSerializers.validationMessages.clear
val jsonString = """ val jsonString = """
{ {
"description":"the description", "description":"the description",
@ -126,7 +131,9 @@ class ApiDescriptionValidationTest extends FlatSpec with ShouldMatchers {
""" """
parse(jsonString).extract[ApiDescription] match { parse(jsonString).extract[ApiDescription] match {
case p: ApiDescription => { case p: ApiDescription => {
SwaggerSerializers.validationMessages.size should be (3) val errors = new ListBuffer[ValidationError]
SwaggerValidator.validate(p, errors, "")
errors.size should be (3)
} }
case _ => fail("wrong type returned, should be ApiDescription") case _ => fail("wrong type returned, should be ApiDescription")
} }
@ -138,7 +145,7 @@ class OperationValidationTest extends FlatSpec with ShouldMatchers {
implicit val formats = SwaggerSerializers.formats("1.2") implicit val formats = SwaggerSerializers.formats("1.2")
it should "fail to deserialize an Operation with missing param type" in { it should "fail to deserialize an Operation with missing param type" in {
SwaggerSerializers.validationMessages.clear // SwaggerSerializers.validationMessages.clear
val jsonString = """ val jsonString = """
{ {
"httpMethod":"GET", "httpMethod":"GET",
@ -162,7 +169,9 @@ class OperationValidationTest extends FlatSpec with ShouldMatchers {
val json = parse(jsonString) val json = parse(jsonString)
json.extract[Operation] match { json.extract[Operation] match {
case op: Operation => { case op: Operation => {
SwaggerSerializers.validationMessages.size should be (1) val errors = new ListBuffer[ValidationError]
SwaggerValidator.validate(op, errors, "")
errors.size should be (1)
} }
case _ => fail("wrong type returned, should be Operation") case _ => fail("wrong type returned, should be Operation")
} }