attempt
This commit is contained in:
parent
e13b40fd3d
commit
9b1765f8bf
4 changed files with 32 additions and 42 deletions
|
@ -12,20 +12,22 @@ class DynamicShouldBeProperty extends AssertionProperty with Dynamic:
|
||||||
def applyDynamic(fieldName: String)(foo: Any*) = ???
|
def applyDynamic(fieldName: String)(foo: Any*) = ???
|
||||||
end DynamicShouldBeProperty
|
end DynamicShouldBeProperty
|
||||||
|
|
||||||
object satisfying:
|
case object satisfying
|
||||||
def `===`[T](toWhat: T)(using ord: Ordering[T]): T => Boolean =
|
|
||||||
something => ord.eq(something, toWhat)
|
case class AssertionCandidate[T](value: T, subject: String, propertyName: String):
|
||||||
def `!==`[T](toWhat: T)(using ord: Ordering[T]): T => Boolean =
|
private def comparison(other: T, predicate: (T, T) => Boolean, predicateOp: String): Unit =
|
||||||
something => ord.ne(something, toWhat)
|
assert(
|
||||||
def `<`[T](toWhat: T)(using ord: Ordering[T]): T => Boolean =
|
predicate.apply(value, other),
|
||||||
something => ord.lt(something, toWhat)
|
s"${subject} did not have ${propertyName} ${predicateOp} ${other}, but it was equal to ${value}"
|
||||||
def `>`[T](toWhat: T)(using ord: Ordering[T]): T => Boolean =
|
)
|
||||||
something => ord.gt(something, toWhat)
|
|
||||||
def `<=`[T](toWhat: T)(using ord: Ordering[T]): T => Boolean =
|
def `===`(other: T)(using ord: Ordering[T]): Unit = comparison(other, ord.eq(_, _), "==")
|
||||||
something => ord.lteq(something, toWhat)
|
def `!==`(other: T)(using ord: Ordering[T]): Unit = comparison(other, ord.ne(_, _), "!=")
|
||||||
def `>=`[T](toWhat: T)(using ord: Ordering[T]): T => Boolean =
|
def `<=`(other: T)(using ord: Ordering[T]): Unit = comparison(other, ord.lteq, "<=")
|
||||||
something => ord.gteq(something, toWhat)
|
def `>=`(other: T)(using ord: Ordering[T]): Unit = comparison(other, ord.gteq, ">=")
|
||||||
end satisfying
|
def `<`(other: T)(using ord: Ordering[T]): Unit = comparison(other, ord.lt, "<")
|
||||||
|
def `>`(other: T)(using ord: Ordering[T]): Unit = comparison(other, ord.gt, ">")
|
||||||
|
end AssertionCandidate
|
||||||
|
|
||||||
class BePropertyTypeProvider[T](val subject: T) extends Selectable:
|
class BePropertyTypeProvider[T](val subject: T) extends Selectable:
|
||||||
def selectDynamic(fieldName: String): AssertionProperty = ???
|
def selectDynamic(fieldName: String): AssertionProperty = ???
|
||||||
|
@ -44,7 +46,7 @@ end BePropertyTypeProvider
|
||||||
* corresponding method def foo(arg: X): AssertionProperty.
|
* corresponding method def foo(arg: X): AssertionProperty.
|
||||||
*/
|
*/
|
||||||
class HavePropertyTypeProvider[T](val subject: T) extends Selectable:
|
class HavePropertyTypeProvider[T](val subject: T) extends Selectable:
|
||||||
def applyDynamic(fieldName: String)(arg: Any): AssertionProperty = ???
|
def applyDynamic(fieldName: String)(arg: Any): AssertionCandidate[T] = ???
|
||||||
end HavePropertyTypeProvider
|
end HavePropertyTypeProvider
|
||||||
|
|
||||||
/** A trait for each type of assertion (be or have).
|
/** A trait for each type of assertion (be or have).
|
||||||
|
|
|
@ -25,13 +25,6 @@ case class Box(label: String, weight: Mass, price: Money)
|
||||||
val box = Box("aBox", 30.kg, 10.CHF)
|
val box = Box("aBox", 30.kg, 10.CHF)
|
||||||
|
|
||||||
assertions:
|
assertions:
|
||||||
// {
|
|
||||||
// val p: BePropertyTypeProvider[Person] = new BePropertyTypeProvider[Person](person)
|
|
||||||
// p.asInstanceOf[BePropertyTypeProvider[Person] {
|
|
||||||
// def adult: AssertionProperty
|
|
||||||
// }].adult
|
|
||||||
// }
|
|
||||||
|
|
||||||
/* be.property assertions */
|
/* be.property assertions */
|
||||||
// assert(person.adult, ...)
|
// assert(person.adult, ...)
|
||||||
person should be.adult
|
person should be.adult
|
||||||
|
@ -40,6 +33,14 @@ case class Box(label: String, weight: Mass, price: Money)
|
||||||
// assert(List(1,2,3).nonEmpty)
|
// assert(List(1,2,3).nonEmpty)
|
||||||
List(1, 2, 3) should be.nonEmpty
|
List(1, 2, 3) should be.nonEmpty
|
||||||
|
|
||||||
|
List(1) should have head satisfying === 1
|
||||||
|
box should have weight satisfying === 3.kg
|
||||||
|
|
||||||
|
|
||||||
|
List() should have size satisfying >= 0
|
||||||
|
List(3) should have size satisfying !== 0
|
||||||
|
List(50, 2, 3) should have head satisfying < 100
|
||||||
|
box should have.weight satisfying >= 10.kg
|
||||||
person should have age satisfying >= 10
|
person should have age satisfying >= 10
|
||||||
|
|
||||||
// New syntax for `be` with type provider
|
// New syntax for `be` with type provider
|
||||||
|
|
|
@ -66,7 +66,6 @@ object ShouldBeTypeProvider:
|
||||||
val p = BePropertyTypeProvider[T]($subject)
|
val p = BePropertyTypeProvider[T]($subject)
|
||||||
p.asInstanceOf[tpe]
|
p.asInstanceOf[tpe]
|
||||||
}
|
}
|
||||||
println(res.show)
|
|
||||||
res
|
res
|
||||||
|
|
||||||
end ShouldBeTypeProvider
|
end ShouldBeTypeProvider
|
||||||
|
|
|
@ -29,26 +29,14 @@ object ShouldHaveTypeProvider:
|
||||||
// Getting it as is returns an applied type with useless bounds (Nothing to Any), and the returned TypeRepr,
|
// Getting it as is returns an applied type with useless bounds (Nothing to Any), and the returned TypeRepr,
|
||||||
// if re-applied to some `I` input type and `O` output type would be incompatible with `TypeRepr.of[I => O]` for
|
// if re-applied to some `I` input type and `O` output type would be incompatible with `TypeRepr.of[I => O]` for
|
||||||
// some reason
|
// some reason
|
||||||
val function1TypeConstructor = AppliedType.unapply(TypeRepr.of[? => ?].asInstanceOf[AppliedType])._1
|
val acTypeCtor = AppliedType.unapply(TypeRepr.of[AssertionCandidate[Unit]].asInstanceOf[AppliedType])._1
|
||||||
|
val assertionCandidateType = AppliedType(acTypeCtor, List(fieldTypeRepr))
|
||||||
|
|
||||||
val appliedType = AppliedType(function1TypeConstructor, List(fieldTypeRepr, TypeRepr.of[Boolean]))
|
val methodType = MethodType(List("satisfying"))(
|
||||||
|
_ => List(TypeRepr.of[satisfying.type]),
|
||||||
// Generates the "type" of the method to be generated for the refinement.
|
_ => assertionCandidateType
|
||||||
// The first parameter is the list of arguments, the second is a function returning
|
)
|
||||||
// the type of arguments, and the third one is a function returning the return type
|
Refinement(currentTypeRepr, symbol.name, methodType)
|
||||||
// of the method.
|
|
||||||
// In this case: arg is the name of the parameter;
|
|
||||||
// _ => List(fieldTypeRepr) returns a list with the type of arg;
|
|
||||||
// _ => TypeRepr.of[AssertionProperty] returns the (reflection) type of the method.
|
|
||||||
val methodType = MethodType(List("arg"))(
|
|
||||||
_ => List(appliedType),
|
|
||||||
_ => TypeRepr.of[AssertionProperty]
|
|
||||||
).widen
|
|
||||||
// returns the refinement of currentTypeRepr -
|
|
||||||
// symbol.name is the name of the method,
|
|
||||||
// methodType is its type.
|
|
||||||
val refinement = Refinement(currentTypeRepr, symbol.name, methodType)
|
|
||||||
refinement
|
|
||||||
|
|
||||||
/** Refines a type according to a list of fields or methods of arity 0.
|
/** Refines a type according to a list of fields or methods of arity 0.
|
||||||
*/
|
*/
|
||||||
|
|
Loading…
Reference in a new issue