diff --git a/modules/core/shared/src/main/scala/weaver/Comparison.scala b/modules/core/shared/src/main/scala/weaver/Comparison.scala index fe65084e..d67ebff7 100644 --- a/modules/core/shared/src/main/scala/weaver/Comparison.scala +++ b/modules/core/shared/src/main/scala/weaver/Comparison.scala @@ -7,18 +7,28 @@ import scala.annotation.implicitNotFound @implicitNotFound("Could not find an implicit Comparison[${A}]. Does ${A} have an associated cats.Eq[${A}] instance?") trait Comparison[A] { - def diff(expected: A, found: A): Option[String] + def diff(expected: A, found: A): Comparison.Result } object Comparison { - implicit def fromEqAndShow[A]( + sealed trait Result + object Result { + case object Success extends Result + case class Failure(diff: String) extends Result + } + + /** + * Create a `Comparison` instance from an `Eq` implementation. Uses the + * default `Show.fromToString` when no implicit `Show` instance is found. + */ + implicit def fromEq[A]( implicit eqv: Eq[A], showA: Show[A] = Show.fromToString[A] ): Comparison[A] = { new Comparison[A] { - def diff(expected: A, found: A): Option[String] = { + def diff(expected: A, found: A): Result = { if (eqv.eqv(found, expected)) { - None + Result.Success } else { val expectedLines = showA.show(expected).linesIterator.toSeq val foundLines = showA.show(found).linesIterator.toSeq @@ -28,9 +38,26 @@ object Comparison { .toSeq .map(str => Console.RESET.toString + str) .mkString("\n") - Some(diff) + Result.Failure(diff) } } } } + + /** + * Create a `Comparison` instance from an `diff` implementation. + */ + def instance[A](f: (A, A) => Option[String]): Comparison[A] = + new Comparison[A] { + def diff(expected: A, found: A): Result = f(expected, found) match { + case None => Result.Success + case Some(diff) => Result.Failure(diff) + } + } + + /** + * Create a `Comparison` instance from an `diff` implementation. + */ + def instance[A](f: PartialFunction[(A, A), String]): Comparison[A] = + instance((expected, found) => f.lift((expected, found))) } diff --git a/modules/core/shared/src/main/scala/weaver/internals/ExpectSame.scala b/modules/core/shared/src/main/scala/weaver/internals/ExpectSame.scala index e0a79eb5..5f29e7ed 100644 --- a/modules/core/shared/src/main/scala/weaver/internals/ExpectSame.scala +++ b/modules/core/shared/src/main/scala/weaver/internals/ExpectSame.scala @@ -13,8 +13,8 @@ private[weaver] trait ExpectSame { implicit comparisonA: Comparison[A], loc: SourceLocation): Expectations = { comparisonA.diff(expected, found) match { - case None => Expectations(Validated.validNel(())) - case Some(diff) => + case Comparison.Result.Success => Expectations(Validated.validNel(())) + case Comparison.Result.Failure(diff) => val header = "Values not equal:" val sourceLocs = NonEmptyList.of(loc) Expectations( @@ -30,6 +30,6 @@ private[weaver] trait ExpectSame { expected: A, found: A)( implicit loc: SourceLocation): Expectations = eql(expected, found)( - Comparison.fromEqAndShow(Eq.fromUniversalEquals, Show.fromToString), + Comparison.fromEq(Eq.fromUniversalEquals, Show.fromToString), loc) } diff --git a/modules/framework-cats/shared/src/test/scala/ExpectationsTests.scala b/modules/framework-cats/shared/src/test/scala/ExpectationsTests.scala index a7c029fb..fa694cb6 100644 --- a/modules/framework-cats/shared/src/test/scala/ExpectationsTests.scala +++ b/modules/framework-cats/shared/src/test/scala/ExpectationsTests.scala @@ -67,8 +67,7 @@ object ExpectationsTests extends SimpleIOSuite { } pureTest("expect.eql respects weaver.Comparison") { - implicit val comparison: Comparison[Int] = - Comparison.fromEqAndShow(Eq.allEqual) + implicit val comparison: Comparison[Int] = Comparison.fromEq(Eq.allEqual) expect.eql(0, 1) } diff --git a/modules/framework-cats/shared/src/test/scala/Meta.scala b/modules/framework-cats/shared/src/test/scala/Meta.scala index eddeeead..f5ea1d2f 100644 --- a/modules/framework-cats/shared/src/test/scala/Meta.scala +++ b/modules/framework-cats/shared/src/test/scala/Meta.scala @@ -53,8 +53,8 @@ object Meta { |} """.stripMargin.trim() } - implicit val cmp: Comparison[Foo] = - Comparison.fromEqAndShow[Foo](cats.Eq.fromUniversalEquals, show) + implicit val comparison: Comparison[Foo] = + Comparison.fromEq[Foo](cats.Eq.fromUniversalEquals, show) } expect.eql(Foo("foo", 1), Foo("foo", 2))