diff --git a/chimney/src/main/scala-2/io/scalaland/chimney/internal/compiletime/ChimneyExprsPlatform.scala b/chimney/src/main/scala-2/io/scalaland/chimney/internal/compiletime/ChimneyExprsPlatform.scala index 2a5b1b253..aef12ae19 100644 --- a/chimney/src/main/scala-2/io/scalaland/chimney/internal/compiletime/ChimneyExprsPlatform.scala +++ b/chimney/src/main/scala-2/io/scalaland/chimney/internal/compiletime/ChimneyExprsPlatform.scala @@ -289,7 +289,7 @@ private[compiletime] trait ChimneyExprsPlatform extends ChimneyExprs { this: Chi optionalValue: Expr[integrations.OptionalValue[Optional, Value]], optional: Expr[Optional], optional2: Expr[Optional] - ): Expr[Optional] = c.Expr[Optional](q"$optionalValue.fold($optional, $optional2)") + ): Expr[Optional] = c.Expr[Optional](q"$optionalValue.orElse($optional, $optional2)") } object PartiallyBuildIterable extends PartiallyBuildIterableModule { diff --git a/chimney/src/test/scala/io/scalaland/chimney/PartialMergingIntegrationsSpec.scala b/chimney/src/test/scala/io/scalaland/chimney/PartialMergingIntegrationsSpec.scala new file mode 100644 index 000000000..ead91c3f1 --- /dev/null +++ b/chimney/src/test/scala/io/scalaland/chimney/PartialMergingIntegrationsSpec.scala @@ -0,0 +1,270 @@ +package io.scalaland.chimney + +import io.scalaland.chimney.dsl.* +import io.scalaland.chimney.fixtures.* + +class PartialMergingIntegrationsSpec extends ChimneySpec { + + import TotalTransformerIntegrationsSpec.* + + group("setting .withFallback(fallbackValue)") { + + test("should use only source Possible when no merging strategy is enabled") { + import merges.Nested + + implicit val s2i: PartialTransformer[String, Int] = PartialTransformer.fromFunction[String, Int](_.toInt) + + "10" + .intoPartial[Possible[Int]] + .withFallback(20) + .transform + .asOption ==> Some(Possible.Present(10)) + Possible("10") + .intoPartial[Possible[Int]] + .withFallback(Possible(20)) + .transform + .asOption ==> Some(Possible.Present(10)) + Possible("10") + .intoPartial[Possible[Int]] + .withFallback(Possible.Nope: Possible[Int]) + .transform + .asOption ==> Some(Possible.Present(10)) + (Possible.Nope: Possible[String]) + .intoPartial[Possible[Int]] + .withFallback(Possible(20)) + .transform + .asOption ==> Some(Possible.Nope) + (Possible.Nope: Possible[String]) + .intoPartial[Possible[Int]] + .withFallback(Possible.Nope: Possible[Int]) + .transform + .asOption ==> Some(Possible.Nope) + + Nested("10") + .intoPartial[Nested[Possible[Int]]] + .withFallback(Nested(20)) + .transform + .asOption ==> Some(Nested(Possible.Present(10))) + Nested(Possible("10")) + .intoPartial[Nested[Possible[Int]]] + .withFallback(Nested(Possible(20))) + .transform + .asOption ==> Some(Nested(Possible.Present(10))) + Nested(Possible("10")) + .intoPartial[Nested[Possible[Int]]] + .withFallback(Nested(Possible.Nope: Possible[String])) + .transform + .asOption ==> Some(Nested(Possible.Present(10))) + Nested(Possible.Nope: Possible[String]) + .intoPartial[Nested[Possible[Int]]] + .withFallback(Nested(Possible(20))) + .transform + .asOption ==> Some(Nested(Possible.Nope)) + Nested(Possible.Nope: Possible[String]) + .intoPartial[Nested[Possible[Int]]] + .withFallback(Nested(Possible.Nope: Possible[Int])) + .transform + .asOption ==> Some(Nested(Possible.Nope)) + } + } + + group("setting .withFallbackFrom(selectorFrom)(fallbackValue)") { + + test("should use only source Possible when no merging strategy is enabled") { + import merges.Nested + + implicit val s2i: PartialTransformer[String, Int] = PartialTransformer.fromFunction[String, Int](_.toInt) + + Nested("10") + .intoPartial[Nested[Possible[Int]]] + .withFallbackFrom(_.value)(20) + .transform + .asOption ==> Some(Nested(Possible.Present(10))) + Nested(Possible("10")) + .intoPartial[Nested[Possible[Int]]] + .withFallbackFrom(_.value)(Possible(20)) + .transform + .asOption ==> Some(Nested(Possible.Present(10))) + Nested(Possible("10")) + .intoPartial[Nested[Possible[Int]]] + .withFallbackFrom(_.value)(Possible.Nope: Possible[String]) + .transform + .asOption ==> Some(Nested(Possible.Present(10))) + Nested(Possible.Nope: Possible[String]) + .intoPartial[Nested[Possible[Int]]] + .withFallbackFrom(_.value)(Possible(20)) + .transform + .asOption ==> Some(Nested(Possible.Nope)) + Nested(Possible.Nope: Possible[String]) + .intoPartial[Nested[Possible[Int]]] + .withFallbackFrom(_.value)(Possible.Nope: Possible[Int]) + .transform + .asOption ==> Some(Nested(Possible.Nope)) + + Nested(Nested("10")) + .intoPartial[Nested[Nested[Possible[Int]]]] + .withFallbackFrom(_.value)(Nested(20)) + .transform + .asOption ==> Some(Nested(Nested(Possible.Present(10)))) + Nested(Nested(Possible("10"))) + .intoPartial[Nested[Nested[Possible[Int]]]] + .withFallbackFrom(_.value)(Nested(Possible(20))) + .transform + .asOption ==> Some(Nested(Nested(Possible.Present(10)))) + Nested(Nested(Possible("10"))) + .intoPartial[Nested[Nested[Possible[Int]]]] + .withFallbackFrom(_.value)(Nested(Possible.Nope: Possible[Int])) + .transform + .asOption ==> Some(Nested(Nested(Possible.Present(10)))) + Nested(Nested(Possible.Nope: Possible[String])) + .intoPartial[Nested[Nested[Possible[Int]]]] + .withFallbackFrom(_.value)(Nested(Possible(20))) + .transform + .asOption ==> Some(Nested(Nested(Possible.Nope))) + Nested(Nested(Possible.Nope: Possible[String])) + .intoPartial[Nested[Nested[Possible[Int]]]] + .withFallbackFrom(_.value)(Nested(Possible.Nope: Possible[Int])) + .transform + .asOption ==> Some(Nested(Nested(Possible.Nope))) + } + } + + group("flag .enableOptionFallbackMerge(SourceOrElseFallback)") { + + test("should merge Possibles from source to fallback when SourceOrElseFallback strategy is enabled") { + import merges.Nested + + implicit val s2i: PartialTransformer[String, Int] = PartialTransformer.fromFunction[String, Int](_.toInt) + + "10" + .intoPartial[Possible[Int]] + .withFallback(20) + .enableOptionFallbackMerge(SourceOrElseFallback) + .transform + .asOption ==> Some(Possible.Present(10)) + Possible("10") + .intoPartial[Possible[Int]] + .withFallback(Possible(20)) + .enableOptionFallbackMerge(SourceOrElseFallback) + .transform + .asOption ==> Some(Possible.Present(10)) + Possible("10") + .intoPartial[Possible[Int]] + .withFallback(Possible.Nope: Possible[String]) + .enableOptionFallbackMerge(SourceOrElseFallback) + .transform + .asOption ==> Some(Possible.Present(10)) + (Possible.Nope: Possible[String]) + .intoPartial[Possible[Int]] + .withFallback(Possible(20)) + .enableOptionFallbackMerge(SourceOrElseFallback) + .transform + .asOption ==> Some(Possible.Present(20)) + (Possible.Nope: Possible[String]) + .intoPartial[Possible[Int]] + .withFallback(Possible.Nope: Possible[Int]) + .enableOptionFallbackMerge(SourceOrElseFallback) + .transform + .asOption ==> Some(Possible.Nope) + + Nested("10") + .intoPartial[Nested[Possible[Int]]] + .withFallback(Nested(20)) + .enableOptionFallbackMerge(SourceOrElseFallback) + .transform + .asOption ==> Some(Nested(Possible.Present(10))) + Nested(Possible("10")) + .intoPartial[Nested[Possible[Int]]] + .withFallback(Nested(Possible(20))) + .enableOptionFallbackMerge(SourceOrElseFallback) + .transform + .asOption ==> Some(Nested(Possible.Present(10))) + Nested(Possible("10")) + .intoPartial[Nested[Possible[Int]]] + .withFallback(Nested(Possible.Nope: Possible[Int])) + .enableOptionFallbackMerge(SourceOrElseFallback) + .transform + .asOption ==> Some(Nested(Possible.Present(10))) + Nested(Possible.Nope: Possible[String]) + .intoPartial[Nested[Possible[Int]]] + .withFallback(Nested(Possible(20))) + .enableOptionFallbackMerge(SourceOrElseFallback) + .transform + .asOption ==> Some(Nested(Possible.Present(20))) + Nested(Possible.Nope: Possible[String]) + .intoPartial[Nested[Possible[Int]]] + .withFallback(Nested(Possible.Nope: Possible[Int])) + .enableOptionFallbackMerge(SourceOrElseFallback) + .transform + .asOption ==> Some(Nested(Possible.Nope)) + } + + test("should merge Possibles from fallback to source when FallbackOrElseSource strategy is enabled") { + import merges.Nested + + implicit val s2i: PartialTransformer[String, Int] = PartialTransformer.fromFunction[String, Int](_.toInt) + + "10" + .intoPartial[Possible[Int]] + .withFallback(20) + .enableOptionFallbackMerge(FallbackOrElseSource) + .transform + .asOption ==> Some(Possible.Present(20)) + Possible("10") + .intoPartial[Possible[Int]] + .withFallback(Possible(20)) + .enableOptionFallbackMerge(FallbackOrElseSource) + .transform + .asOption ==> Some(Possible.Present(20)) + Possible("10") + .intoPartial[Possible[Int]] + .withFallback(Possible.Nope: Possible[Int]) + .enableOptionFallbackMerge(FallbackOrElseSource) + .transform + .asOption ==> Some(Possible.Present(10)) + (Possible.Nope: Possible[String]) + .intoPartial[Possible[Int]] + .withFallback(Possible(20)) + .enableOptionFallbackMerge(FallbackOrElseSource) + .transform + .asOption ==> Some(Possible.Present(20)) + (Possible.Nope: Possible[String]) + .intoPartial[Possible[Int]] + .withFallback(Possible.Nope: Possible[Int]) + .enableOptionFallbackMerge(FallbackOrElseSource) + .transform + .asOption ==> Some(Possible.Nope) + + Nested("10") + .intoPartial[Nested[Possible[Int]]] + .withFallback(Nested(20)) + .enableOptionFallbackMerge(FallbackOrElseSource) + .transform + .asOption ==> Some(Nested(Possible.Present(20))) + Nested(Possible("10")) + .intoPartial[Nested[Possible[Int]]] + .withFallback(Nested(Possible(20))) + .enableOptionFallbackMerge(FallbackOrElseSource) + .transform + .asOption ==> Some(Nested(Possible.Present(20))) + Nested(Possible("10")) + .intoPartial[Nested[Possible[Int]]] + .withFallback(Nested(Possible.Nope: Possible[Int])) + .enableOptionFallbackMerge(FallbackOrElseSource) + .transform + .asOption ==> Some(Nested(Possible.Present(10))) + Nested(Possible.Nope: Possible[String]) + .intoPartial[Nested[Possible[Int]]] + .withFallback(Nested(Possible(20))) + .enableOptionFallbackMerge(FallbackOrElseSource) + .transform + .asOption ==> Some(Nested(Possible.Present(20))) + Nested(Possible.Nope: Possible[String]) + .intoPartial[Nested[Possible[Int]]] + .withFallback(Nested(Possible.Nope: Possible[Int])) + .enableOptionFallbackMerge(FallbackOrElseSource) + .transform + .asOption ==> Some(Nested(Possible.Nope)) + } + } +} diff --git a/chimney/src/test/scala/io/scalaland/chimney/PatcherIntegrationsSpec.scala b/chimney/src/test/scala/io/scalaland/chimney/PatcherIntegrationsSpec.scala new file mode 100644 index 000000000..2a4d268bb --- /dev/null +++ b/chimney/src/test/scala/io/scalaland/chimney/PatcherIntegrationsSpec.scala @@ -0,0 +1,42 @@ +package io.scalaland.chimney + +import io.scalaland.chimney.dsl.* + +class PatcherIntegrationsSpec extends ChimneySpec { + + import TotalTransformerIntegrationsSpec.* + import PatcherStdLibSpec.* + + test("patch Option-type with Option-type of the same type, replacing the value") { + Possible(Bar("a")).patchUsing(Possible(Bar("b"))) ==> Possible(Bar("b")) + Possible(Bar("a")).using(Possible(Bar("b"))).patch ==> Possible(Bar("b")) + + Possible(Bar("a")).patchUsing(Possible.Nope: Possible[Bar]) ==> Possible.Nope + Possible(Bar("a")).using(Possible.Nope: Possible[Bar]).patch ==> Possible.Nope + + (Possible.Nope: Possible[Bar]).patchUsing(Possible(Bar("b"))) ==> Possible(Bar("b")) + (Possible.Nope: Possible[Bar]).using(Possible(Bar("b"))).patch ==> Possible(Bar("b")) + + (Possible.Nope: Possible[Bar]).patchUsing(Possible.Nope: Possible[Bar]) ==> Possible.Nope + (Possible.Nope: Possible[Bar]).using(Possible.Nope: Possible[Bar]).patch ==> Possible.Nope + } + + group("flag .ignoreNoneInPatch") { + + test("should patch Option-type with Option-type of the same type, with patch.orElse(obj)") { + Possible(Bar("a")).using(Possible.Nope: Possible[Bar]).ignoreNoneInPatch.patch ==> Possible(Bar("a")) + Possible(Bar("a")).using(Possible(Bar("b"))).ignoreNoneInPatch.patch ==> Possible(Bar("b")) + (Possible.Nope: Possible[Bar]).using(Possible(Bar("b"))).ignoreNoneInPatch.patch ==> Possible(Bar("b")) + (Possible.Nope: Possible[Bar]).using(Possible.Nope: Possible[Bar]).ignoreNoneInPatch.patch ==> Possible.Nope + + locally { + implicit val ctx = PatcherConfiguration.default.ignoreNoneInPatch + + Possible(Bar("a")).patchUsing(Possible(Bar("b"))) ==> Possible(Bar("b")) + Possible(Bar("a")).patchUsing(Possible.Nope: Possible[Bar]) ==> Possible(Bar("a")) + (Possible.Nope: Possible[Bar]).patchUsing(Possible(Bar("b"))) ==> Possible(Bar("b")) + (Possible.Nope: Possible[Bar]).patchUsing(Possible.Nope: Possible[Bar]) ==> Possible.Nope + } + } + } +} diff --git a/chimney/src/test/scala/io/scalaland/chimney/PatcherStdLibSpec.scala b/chimney/src/test/scala/io/scalaland/chimney/PatcherStdLibSpec.scala new file mode 100644 index 000000000..885b173b9 --- /dev/null +++ b/chimney/src/test/scala/io/scalaland/chimney/PatcherStdLibSpec.scala @@ -0,0 +1,46 @@ +package io.scalaland.chimney + +import io.scalaland.chimney.dsl.* + +class PatcherStdLibSpec extends ChimneySpec { + + import PatcherStdLibSpec.* + + test("patch Option-type with Option-type of the same type, replacing the value") { + Option(Bar("a")).patchUsing(Option(Bar("b"))) ==> Option(Bar("b")) + Option(Bar("a")).using(Option(Bar("b"))).patch ==> Option(Bar("b")) + + Option(Bar("a")).patchUsing(None: Option[Bar]) ==> None + Option(Bar("a")).using(None: Option[Bar]).patch ==> None + + (None: Option[Bar]).patchUsing(Option(Bar("b"))) ==> Option(Bar("b")) + (None: Option[Bar]).using(Option(Bar("b"))).patch ==> Option(Bar("b")) + + (None: Option[Bar]).patchUsing(None: Option[Bar]) ==> None + (None: Option[Bar]).using(None: Option[Bar]).patch ==> None + } + + group("flag .ignoreNoneInPatch") { + + test("should patch Option-type with Option-type of the same type, with patch.orElse(obj)") { + Option(Bar("a")).using(None: Option[Bar]).ignoreNoneInPatch.patch ==> Option(Bar("a")) + Option(Bar("a")).using(Option(Bar("b"))).ignoreNoneInPatch.patch ==> Option(Bar("b")) + (None: Option[Bar]).using(Option(Bar("b"))).ignoreNoneInPatch.patch ==> Option(Bar("b")) + (None: Option[Bar]).using(None: Option[Bar]).ignoreNoneInPatch.patch ==> None + + locally { + implicit val ctx = PatcherConfiguration.default.ignoreNoneInPatch + + Option(Bar("a")).patchUsing(Option(Bar("b"))) ==> Option(Bar("b")) + Option(Bar("a")).patchUsing(None: Option[Bar]) ==> Option(Bar("a")) + (None: Option[Bar]).patchUsing(Option(Bar("b"))) ==> Option(Bar("b")) + (None: Option[Bar]).patchUsing(None: Option[Bar]) ==> None + } + } + } +} +object PatcherStdLibSpec { + + case class Foo(value: String, extra: Int) + case class Bar(value: String) +} diff --git a/chimney/src/test/scala/io/scalaland/chimney/TotalMergingIntegrationsSpec.scala b/chimney/src/test/scala/io/scalaland/chimney/TotalMergingIntegrationsSpec.scala new file mode 100644 index 000000000..46da14d4c --- /dev/null +++ b/chimney/src/test/scala/io/scalaland/chimney/TotalMergingIntegrationsSpec.scala @@ -0,0 +1,228 @@ +package io.scalaland.chimney + +import io.scalaland.chimney.dsl.* +import io.scalaland.chimney.fixtures.* + +class TotalMergingIntegrationsSpec extends ChimneySpec { + + import TotalTransformerIntegrationsSpec.* + + group("setting .withFallback(fallbackValue)") { + + test("should use only source Possible when no merging strategy is enabled") { + import merges.Nested + + implicit val i2s: Transformer[Int, String] = _.toString + + 10 + .into[Possible[String]] + .withFallback("fallback") + .transform ==> Possible.Present("10") + Possible(10) + .into[Possible[String]] + .withFallback(Possible("fallback")) + .transform ==> Possible.Present("10") + Possible(10) + .into[Possible[String]] + .withFallback(Possible.Nope: Possible[String]) + .transform ==> Possible.Present("10") + (Possible.Nope: Possible[Int]) + .into[Possible[String]] + .withFallback(Possible("fallback")) + .transform ==> Possible.Nope + (Possible.Nope: Possible[Int]) + .into[Possible[String]] + .withFallback(Possible.Nope: Possible[String]) + .transform ==> Possible.Nope + + Nested(10) + .into[Nested[Possible[String]]] + .withFallback(Nested("fallback")) + .transform ==> Nested(Possible.Present("10")) + Nested(Possible(10)) + .into[Nested[Possible[String]]] + .withFallback(Nested(Possible("fallback"))) + .transform ==> Nested(Possible.Present("10")) + Nested(Possible(10)) + .into[Nested[Possible[String]]] + .withFallback(Nested(Possible.Nope: Possible[String])) + .transform ==> Nested(Possible.Present("10")) + Nested(Possible.Nope: Possible[Int]) + .into[Nested[Possible[String]]] + .withFallback(Nested(Possible("fallback"))) + .transform ==> Nested(Possible.Nope) + Nested(Possible.Nope: Possible[Int]) + .into[Nested[Possible[String]]] + .withFallback(Nested(Possible.Nope: Possible[String])) + .transform ==> Nested(Possible.Nope) + } + } + + group("setting .withFallbackFrom(selectorFrom)(fallbackValue)") { + + test("should use only source Possible when no merging strategy is enabled") { + import merges.Nested + + implicit val i2s: Transformer[Int, String] = _.toString + + Nested(10) + .into[Nested[Possible[String]]] + .withFallbackFrom(_.value)("fallback") + .transform ==> Nested(Possible.Present("10")) + Nested(Possible(10)) + .into[Nested[Possible[String]]] + .withFallbackFrom(_.value)(Possible("fallback")) + .transform ==> Nested(Possible.Present("10")) + Nested(Possible(10)) + .into[Nested[Possible[String]]] + .withFallbackFrom(_.value)(Possible.Nope: Possible[String]) + .transform ==> Nested(Possible.Present("10")) + Nested(Possible.Nope: Possible[Int]) + .into[Nested[Possible[String]]] + .withFallbackFrom(_.value)(Possible("fallback")) + .transform ==> Nested(Possible.Nope) + Nested(Possible.Nope: Possible[Int]) + .into[Nested[Possible[String]]] + .withFallbackFrom(_.value)(Possible.Nope: Possible[String]) + .transform ==> Nested(Possible.Nope) + + Nested(Nested(10)) + .into[Nested[Nested[Possible[String]]]] + .withFallbackFrom(_.value)(Nested("fallback")) + .transform ==> Nested(Nested(Possible.Present("10"))) + Nested(Nested(Possible(10))) + .into[Nested[Nested[Possible[String]]]] + .withFallbackFrom(_.value)(Nested(Possible("fallback"))) + .transform ==> Nested(Nested(Possible.Present("10"))) + Nested(Nested(Possible(10))) + .into[Nested[Nested[Possible[String]]]] + .withFallbackFrom(_.value)(Nested(Possible.Nope: Possible[String])) + .transform ==> Nested(Nested(Possible.Present("10"))) + Nested(Nested(Possible.Nope: Possible[Int])) + .into[Nested[Nested[Possible[String]]]] + .withFallbackFrom(_.value)(Nested(Possible("fallback"))) + .transform ==> Nested(Nested(Possible.Nope)) + Nested(Nested(Possible.Nope: Possible[Int])) + .into[Nested[Nested[Possible[String]]]] + .withFallbackFrom(_.value)(Nested(Possible.Nope: Possible[String])) + .transform ==> Nested(Nested(Possible.Nope)) + } + } + + group("flag .enableOptionFallbackMerge(SourceOrElseFallback)") { + + test("should merge Possibles from source to fallback when SourceOrElseFallback strategy is enabled") { + import merges.Nested + + implicit val i2s: Transformer[Int, String] = _.toString + + 10.into[Possible[String]] + .withFallback("fallback") + .enableOptionFallbackMerge(SourceOrElseFallback) + .transform ==> Possible.Present("10") + Possible(10) + .into[Possible[String]] + .withFallback(Possible("fallback")) + .enableOptionFallbackMerge(SourceOrElseFallback) + .transform ==> Possible.Present("10") + Possible(10) + .into[Possible[String]] + .withFallback(Possible.Nope: Possible[String]) + .enableOptionFallbackMerge(SourceOrElseFallback) + .transform ==> Possible.Present("10") + (Possible.Nope: Possible[Int]) + .into[Possible[String]] + .withFallback(Possible("fallback")) + .enableOptionFallbackMerge(SourceOrElseFallback) + .transform ==> Possible.Present("fallback") + (Possible.Nope: Possible[Int]) + .into[Possible[String]] + .withFallback(Possible.Nope: Possible[String]) + .enableOptionFallbackMerge(SourceOrElseFallback) + .transform ==> Possible.Nope + + Nested(10) + .into[Nested[Possible[String]]] + .withFallback(Nested("fallback")) + .enableOptionFallbackMerge(SourceOrElseFallback) + .transform ==> Nested(Possible.Present("10")) + Nested(Possible(10)) + .into[Nested[Possible[String]]] + .withFallback(Nested(Possible("fallback"))) + .enableOptionFallbackMerge(SourceOrElseFallback) + .transform ==> Nested(Possible.Present("10")) + Nested(Possible(10)) + .into[Nested[Possible[String]]] + .withFallback(Nested(Possible.Nope: Possible[String])) + .enableOptionFallbackMerge(SourceOrElseFallback) + .transform ==> Nested(Possible.Present("10")) + Nested(Possible.Nope: Possible[Int]) + .into[Nested[Possible[String]]] + .withFallback(Nested(Possible("fallback"))) + .enableOptionFallbackMerge(SourceOrElseFallback) + .transform ==> Nested(Possible.Present("fallback")) + Nested(Possible.Nope: Possible[Int]) + .into[Nested[Possible[String]]] + .withFallback(Nested(Possible.Nope: Possible[String])) + .enableOptionFallbackMerge(SourceOrElseFallback) + .transform ==> Nested(Possible.Nope) + } + + test("should merge Possibles from fallback to source when FallbackOrElseSource strategy is enabled") { + import merges.Nested + + implicit val i2s: Transformer[Int, String] = _.toString + + 10.into[Possible[String]] + .withFallback("fallback") + .enableOptionFallbackMerge(FallbackOrElseSource) + .transform ==> Possible.Present("fallback") + Possible(10) + .into[Possible[String]] + .withFallback(Possible("fallback")) + .enableOptionFallbackMerge(FallbackOrElseSource) + .transform ==> Possible.Present("fallback") + Possible(10) + .into[Possible[String]] + .withFallback(Possible.Nope: Possible[String]) + .enableOptionFallbackMerge(FallbackOrElseSource) + .transform ==> Possible.Present("10") + (Possible.Nope: Possible[Int]) + .into[Possible[String]] + .withFallback(Possible("fallback")) + .enableOptionFallbackMerge(FallbackOrElseSource) + .transform ==> Possible.Present("fallback") + (Possible.Nope: Possible[Int]) + .into[Possible[String]] + .withFallback(Possible.Nope: Possible[String]) + .enableOptionFallbackMerge(FallbackOrElseSource) + .transform ==> Possible.Nope + + Nested(10) + .into[Nested[Possible[String]]] + .withFallback(Nested("fallback")) + .enableOptionFallbackMerge(FallbackOrElseSource) + .transform ==> Nested(Possible.Present("fallback")) + Nested(Possible(10)) + .into[Nested[Possible[String]]] + .withFallback(Nested(Possible("fallback"))) + .enableOptionFallbackMerge(FallbackOrElseSource) + .transform ==> Nested(Possible.Present("fallback")) + Nested(Possible(10)) + .into[Nested[Possible[String]]] + .withFallback(Nested(Possible.Nope: Possible[String])) + .enableOptionFallbackMerge(FallbackOrElseSource) + .transform ==> Nested(Possible.Present("10")) + Nested(Possible.Nope: Possible[Int]) + .into[Nested[Possible[String]]] + .withFallback(Nested(Possible("fallback"))) + .enableOptionFallbackMerge(FallbackOrElseSource) + .transform ==> Nested(Possible.Present("fallback")) + Nested(Possible.Nope: Possible[Int]) + .into[Nested[Possible[String]]] + .withFallback(Nested(Possible.Nope: Possible[String])) + .enableOptionFallbackMerge(FallbackOrElseSource) + .transform ==> Nested(Possible.Nope) + } + } +}