diff --git a/scalatest/shared/src/main/scala/cats/effect/testing/scalatest/GivenWhenThen.scala b/scalatest/shared/src/main/scala/cats/effect/testing/scalatest/GivenWhenThen.scala new file mode 100644 index 00000000..6886e055 --- /dev/null +++ b/scalatest/shared/src/main/scala/cats/effect/testing/scalatest/GivenWhenThen.scala @@ -0,0 +1,53 @@ +/* + * Copyright 2020-2021 Typelevel + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package cats.effect.testing.scalatest + +import cats.effect.Sync +import org.scalactic.source +import org.scalatest.{Informing, GivenWhenThen => ScalaTestGivenWhenThen} + +trait GivenWhenThen[F[_]] extends ScalaTestGivenWhenThen { this: Informing => + + /** + * Forwards a message to an implicit Informer, preceded by "Given." + * + * @param message the message to forward to the passed informer + */ + def Given(message: String)(implicit F: Sync[F], pos: source.Position): F[Unit] = F.delay(super.Given(message)) + + /** + * Forwards a message to an implicit Informer, preceded by "When ". + * + * @param message the message to forward to the passed informer + */ + def When(message: String)(implicit F: Sync[F], pos: source.Position): F[Unit] = F.delay(super.When(message)) + + /** + * Forwards a message to an implicit Informer, preceded by "Then ". + * + * @param message the message to forward to the passed informer + */ + def Then(message: String)(implicit F: Sync[F], pos: source.Position): F[Unit] = F.delay(super.Then(message)) + + + /** + * Forwards a message to an implicit Informer, preceded by "And ". + * + * @param message the message to forward to the passed informer + */ + def And(message: String)(implicit F: Sync[F], pos: source.Position): F[Unit] = F.delay(super.And(message)) +} diff --git a/scalatest/shared/src/test/scala/cats/effect/testing/scalatest/FeatureEffectSpec.scala b/scalatest/shared/src/test/scala/cats/effect/testing/scalatest/FeatureEffectSpec.scala new file mode 100644 index 00000000..8ecc6ad7 --- /dev/null +++ b/scalatest/shared/src/test/scala/cats/effect/testing/scalatest/FeatureEffectSpec.scala @@ -0,0 +1,51 @@ +/* + * Copyright 2020-2021 Typelevel + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package cats.effect.testing.scalatest + +import cats.effect.IO +import org.scalatest.featurespec.AsyncFeatureSpec +import org.scalatest.matchers.should.Matchers + +class FeatureEffectSpec extends AsyncFeatureSpec with AsyncIOSpec with GivenWhenThen[IO] with Matchers { + + Feature("GivenWhenThen Syntax") { + Scenario("For comprehension") { + for { + _ <- Given("a precondition") + _ <- IO.println("test setup") + _ <- When("an action happens") + result <- IO.pure(1) + _ <- Then("assert something") + _ <- IO(result should be > 0) + _ <- And("assert something else") + _ <- IO(result should be < 10) + } yield () + } + + Scenario("Individual statements") { + val precondition = Given("a precondition") >> IO.println("test setup") + val action = When("an action happens") >> IO.pure(1) + + def assertions(result: Int) = + Then("assert something") >> IO(result should be > 0) >> + And("assert something else") >> IO(result should be < 10) + + precondition >> action.flatMap(assertions) + } + } + +}