Skip to content

Commit

Permalink
Adds improved syntax
Browse files Browse the repository at this point in the history
  • Loading branch information
fedefernandez committed Jul 28, 2023
1 parent 8d2ecf4 commit 6f5e31c
Show file tree
Hide file tree
Showing 7 changed files with 49 additions and 28 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,7 @@ import cats.syntax.all._
import org.scalacheck.Prop
import org.scalacheck.effect.PropF

object instances {
object syntax {

implicit class PropFOps[F[_]](effectProp: F[Prop.Result]) {
def toPropF(implicit F: MonadThrow[F]): PropF[F] =
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,7 @@ import cats.syntax.all.*
import org.scalacheck.Prop
import org.scalacheck.effect.PropF

object instances:
object syntax:

extension [F[_]: MonadThrow](effectProp: F[Prop.Result])
def toPropF: PropF[F] =
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -19,11 +19,11 @@ package karat.scalacheck.http4s
import cats.data.Kleisli
import cats.effect.IO
import cats.syntax.all.*
import karat.concrete.FormulaKt.*
import karat.concrete.progression.{Info, Step}
import karat.scalacheck.ArbModel
import karat.scalacheck.Scalacheck.{checkFormula, Formula}
import karat.scalacheck.effect.instances.*
import karat.scalacheck.syntax.*
import karat.scalacheck.effect.syntax.*
import munit.{CatsEffectSuite, ScalaCheckEffectSuite}
import org.http4s.*
import org.http4s.client.Client
Expand Down Expand Up @@ -98,36 +98,24 @@ class Http4sSMSpec extends CatsEffectSuite with ScalaCheckEffectSuite:
case Action.UpdateProduct(_) => Set(200, 404)
case Action.DeleteProduct(_) => Set(204, 404)
}
always {
predicate { (item: Info[Action, Client[IO], Response[IO]]) =>
val responseCode = item.getResponse.status.code
if validCodes(item.getAction).contains(responseCode) then Prop.Result(Prop.True)
else Prop.Result(Prop.False).label(s"Invalid status code $responseCode for action ${item.getAction}")
}
}
always(should(item => validCodes(item.getAction).contains(item.getResponse.status.code)))

val getFormula: Formula[Info[Action, Client[IO], Response[IO]]] =
always {
implies(
predicate { (item: Info[Action, Client[IO], Response[IO]]) =>
if item.getAction.isCreate then Prop.Result(Prop.True) else Prop.Result(Prop.False)
},
should(_.getAction.isCreate),
remember { (current: Info[Action, Client[IO], Response[IO]]) =>
val rememberedId: Option[String] = current.getAction.getId
next {
always {
implies(
predicate { (item: Info[Action, Client[IO], Response[IO]]) =>
item.getAction match
case Action.GetProduct(id) if rememberedId.contains(id) => Prop.Result(Prop.True)
case _ => Prop.Result(Prop.False)
},
predicate { (item: Info[Action, Client[IO], Response[IO]]) =>
if item.getResponse.status.code == 200 then Prop.Result(Prop.True) else Prop.Result(Prop.False)
}
)
}
}
afterwards(
implies(
predicate { (item: Info[Action, Client[IO], Response[IO]]) =>
item.getAction match
case Action.GetProduct(id) if rememberedId.contains(id) => Prop.Result(Prop.True)
case _ => Prop.Result(Prop.False)
},
should(_.getResponse.status.code == 200)
)
)
}
)
}
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
package karat.scalacheck

object syntax extends CommonSyntax
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
package karat.scalacheck

object syntax extends CommonSyntax
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
package karat.scalacheck

import karat.concrete.FormulaKt
import karat.scalacheck.Scalacheck.{Atomic, Formula, Predicate, Remember}
import org.scalacheck.Prop

trait CommonSyntax {

def should[A](test: A => Boolean): Predicate[A] = FormulaKt.predicate { (a: A) =>
if (test(a)) Prop.Result(Prop.True) else Prop.Result(Prop.False)
}
def predicate[A](test: A => Prop.Result): Predicate[A] = FormulaKt.predicate { (a: A) =>
test(a)
}
def always[A](value: Formula[A]): Formula[A] = FormulaKt.always(value)
def next[A](value: Formula[A]): Formula[A] = FormulaKt.next(value)
def eventually[A](value: Formula[A]): Formula[A] = FormulaKt.eventually(value)
def implies[A](condition: Atomic[A], `then`: Formula[A]): Formula[A] = FormulaKt.implies(condition, `then`)
def remember[A](block: A => Formula[A]): Remember[A] = FormulaKt.remember { (a: A) =>
block(a)
}

def afterwards[A](formula: Formula[A]): Formula[A] = next(always(formula))

}
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,8 @@ import scala.jdk.CollectionConverters._
object Scalacheck {
type Atomic[A] = karat.concrete.Atomic[A, Prop.Result]
type Formula[A] = karat.concrete.Formula[A, Prop.Result]
type Predicate[A] = karat.concrete.Predicate[A, Prop.Result]
type Remember[A] = karat.concrete.Remember[A, Prop.Result]

class ScalacheckStepResultManager[A] extends RegularStepResultManager[A, Prop.Result, Prop.Result] {
override def getEverythingOk: Prop.Result = Prop.Result(Prop.True)
Expand Down

0 comments on commit 6f5e31c

Please sign in to comment.