Skip to content

Commit

Permalink
ensure extra got copied over whenever copy method is used (#239)
Browse files Browse the repository at this point in the history
Co-authored-by: aonyshchuk <[email protected]>
  • Loading branch information
andyglow and aonyshchuk authored Dec 30, 2021
1 parent 513d2bc commit e12aee0
Show file tree
Hide file tree
Showing 2 changed files with 63 additions and 5 deletions.
12 changes: 7 additions & 5 deletions core/src/main/scala/json/Schema.scala
Original file line number Diff line number Diff line change
Expand Up @@ -281,14 +281,15 @@ object Schema {
}

def dropField(pred: Field[_] => Boolean): `object`[T] =
copy(fields = this.fields.filterNot(pred))
def withField(f: Field[_]): `object`[T] = copy(fields = fields + f)
copy(fields = this.fields.filterNot(pred)).withExtraFrom(this)
def withField(f: Field[_]): `object`[T] = copy(fields = fields + f).withExtraFrom(this)
def withField(name: String, tpe: Schema[_], required: Boolean = true): `object`[T] = withField(Field(name, tpe, required))
def withFieldsUpdated(pf: PartialFunction[Field[_], Field[_]]): `object`[T] = copy(
fields = fields collect {
case f if pf isDefinedAt f => pf(f)
case f => f
}
)
).withExtraFrom(this)
override def jsonType: String = "object"
override def toString: String = ToString { sb =>
sb append "object("
Expand Down Expand Up @@ -367,6 +368,7 @@ object Schema {

def apply[T](name: String, tpe: Schema[T]): Field[T] =
new Field(name, tpe, required = true, default = None, description = None, RWMode.ReadWrite)

def apply[T](name: String, tpe: Schema[T], required: Boolean): Field[T] =
new Field(name, tpe, required, default = None, description = None, RWMode.ReadWrite)

Expand Down Expand Up @@ -526,7 +528,7 @@ object Schema {
}
override def withValidation[TT >: T, B](v: V.Def[B, _], vs: V.Def[B, _]*)(implicit
bound: V.Magnet[TT, B]
): `def`[T] = copy(tpe = tpe.asInstanceOf[Schema[TT]].withValidation(v, vs: _*))
): `def`[T] = copy(tpe = tpe.asInstanceOf[Schema[TT]].withValidation(v, vs: _*)).withExtraFrom(this)
override def toDefinition[TT >: T](sig: String): `def`[TT] = {
def deepCopy(x: Schema[_]): Schema[_] = {
val y = x match {
Expand All @@ -543,7 +545,7 @@ object Schema {
y withExtraFrom x
}

copy(sig = sig, tpe = deepCopy(tpe))
copy(sig = sig, tpe = deepCopy(tpe)).withExtraFrom(this)
}
}

Expand Down
56 changes: 56 additions & 0 deletions core/src/test/scala/json/SchemaSpec.scala
Original file line number Diff line number Diff line change
@@ -0,0 +1,56 @@
package json

import org.scalatest.matchers.should.Matchers._
import org.scalatest.OptionValues._
import org.scalatest.wordspec.AnyWordSpec
import Schema._
import `object`._
import json.schema.validation.Instance._
import org.scalactic.source.Position

class SchemaSpec extends AnyWordSpec {
import SchemaSpec._

"Schema" should {
// check all places where `copy` method call is observed
"copy extra" when {
"def.withValidation" in { checkExtraGotCopied(_def) { _.withValidation(`maxLength` := 200) } }
"def.toDefinition" in { checkExtraGotCopied(_def) { _.toDefinition("new-ref") } }
"object.withField" in { checkExtraGotCopied(_obj) { _.withField("bar", `integer`) } }
"object.dropField" in { checkExtraGotCopied(_obj) { _ dropField { _.name == "foo" } } }
"object.withFieldsUpdated" in {
checkExtraGotCopied(_obj) {
_.withFieldsUpdated {
case f if f.name == "foo" => f.copy(tpe = `boolean`)
}
}
}
}
}
}

object SchemaSpec {
import `string`.Format._

private val _obj = `object`[Any](
Field("foo", `string`)
)

private val _def = `def`[String](
"some-ref",
`string`(`date-time`)
)

private def checkExtraGotCopied[T, S[_] <: Schema[_]](schema: S[T])(mod: S[T] => S[T])(implicit pos: Position): Unit = {
val schemaWithExtra = schema
.withTitle("some title")
.withDescription("some description")
.withDiscriminationKey("_key")

val resultingSchema = mod(schemaWithExtra.asInstanceOf[S[T]])

resultingSchema.title.value shouldBe "some title"
resultingSchema.description.value shouldBe "some description"
resultingSchema.discriminationKey.value shouldBe "_key"
}
}

0 comments on commit e12aee0

Please sign in to comment.