packages feed

hspec-effectful 1.1.0 → 1.1.1

raw patch · 4 files changed

+84/−20 lines, 4 filesdep +quickcheck-effectfuldep ~QuickCheckPVP: major bump suggested

API removals or changes: PVP suggests a major version bump

Dependencies added: quickcheck-effectful

Dependency ranges changed: QuickCheck

API changes (from Hackage documentation)

+ Effectful.Hspec: modifyArgs :: forall (es :: [Effect]) a. (HasCallStack, Hspec :> es) => (Args -> Args) -> Eff es a -> Eff es a
+ Effectful.Hspec: modifyMaxDiscardRatio :: forall (es :: [Effect]) a. (HasCallStack, Hspec :> es) => (Int -> Int) -> Eff es a -> Eff es a
+ Effectful.Hspec: modifyMaxShrinks :: forall (es :: [Effect]) a. (HasCallStack, Hspec :> es) => (Int -> Int) -> Eff es a -> Eff es a
+ Effectful.Hspec: modifyMaxSize :: forall (es :: [Effect]) a. (HasCallStack, Hspec :> es) => (Int -> Int) -> Eff es a -> Eff es a
+ Effectful.Hspec: modifyMaxSuccess :: forall (es :: [Effect]) a. (HasCallStack, Hspec :> es) => (Int -> Int) -> Eff es a -> Eff es a
- Effectful.Hspec: fprop :: forall prop (es :: [Effect]). (HasCallStack, Testable prop, Hspec :> es) => String -> prop -> Eff es ()
+ Effectful.Hspec: fprop :: forall prop (es :: [Effect]). (HasCallStack, Testable prop es, Hspec :> es) => String -> prop -> Eff es ()
- Effectful.Hspec: prop :: forall prop (es :: [Effect]). (HasCallStack, Testable prop, Hspec :> es) => String -> prop -> Eff es ()
+ Effectful.Hspec: prop :: forall prop (es :: [Effect]). (HasCallStack, Testable prop es, Hspec :> es) => String -> prop -> Eff es ()
- Effectful.Hspec: xprop :: forall prop (es :: [Effect]). (HasCallStack, Testable prop, Hspec :> es) => String -> prop -> Eff es ()
+ Effectful.Hspec: xprop :: forall prop (es :: [Effect]). (HasCallStack, Testable prop es, Hspec :> es) => String -> prop -> Eff es ()

Files

CHANGELOG.md view
@@ -5,6 +5,14 @@ The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.1.0/), and this project adheres to the [Haskell Package Versioning Policy](https://pvp.haskell.org/). +## [1.1.1] - 2026-07-26++### Added++- `modify*` QuickCheck combinators+- Dependency on `quickcheck-effectful`+- Ability to run effectful computation in QuickCheck props+ ## [1.1.0] - 2026-07-21  ### Added
hspec-effectful.cabal view
@@ -1,6 +1,6 @@ cabal-version: 3.0 name: hspec-effectful-version: 1.1.0+version: 1.1.1 synopsis: Effectful driver for Hspec category: Test description:@@ -26,6 +26,8 @@     -Wno-missing-import-lists     -Wno-missing-kind-signatures     -Wno-all-missed-specialisations+    -Wno-missing-role-annotations+    -Wno-term-variable-capture    default-extensions:     ApplicativeDo@@ -40,6 +42,7 @@     FlexibleContexts     GeneralizedNewtypeDeriving     ImportQualifiedPost+    ImpredicativeTypes     LambdaCase     NamedFieldPuns     NoImplicitPrelude@@ -48,6 +51,7 @@     OverloadedStrings     RecordWildCards     RecursiveDo+    ScopedTypeVariables     TypeApplications     TypeFamilies     TypeOperators@@ -56,12 +60,13 @@   build-depends:     base >=4.16 && <5,     effectful >=2.6 && <2.7,+    quickcheck-effectful >=1.0 && <1.1,  library   import: common   hs-source-dirs: src   build-depends:-    QuickCheck >=2.12 && <3,+    QuickCheck >=2.15 && <3,     hspec >=2.11 && <2.12,     hspec-core >=2.11 && <2.12,     hspec-expectations >=0.8 && <0.9,@@ -78,4 +83,5 @@   hs-source-dirs: test   main-is: Main.hs   build-depends:-    hspec-effectful+    hspec-effectful,+    quickcheck-effectful,
src/Effectful/Hspec.hs view
@@ -1,8 +1,4 @@-{-# LANGUAGE ImpredicativeTypes #-} {-# LANGUAGE Trustworthy #-}-{-# OPTIONS_GHC -Wno-missing-role-annotations #-}-{-# OPTIONS_GHC -Wno-orphans #-}-{-# OPTIONS_GHC -Wno-term-variable-capture #-}  -- | -- Module      : Effectful.Hspec@@ -37,16 +33,16 @@ -- >             put $ funds - amount -- >             pure True ----- Use 'describe' to group related examples, 'it' to state individual expectations--- and setup/teardown combinators such as 'before_', 'after_', or 'around_' to+-- Use 'describe' to group related examples, 'prop' and 'it' to state individual properties or+-- expectations ,and setup/teardown combinators such as 'before_', 'after_', or 'around_' to -- run the examples from a known initial state: -- -- > accountSpec :: (State Int :> es, Hspec :> es) => Eff es () -- > accountSpec = describe "account" . before_ (put @Int 0) $ do--- >     it "accumulates deposits" $ do--- >         deposit 100--- >         deposit 50--- >         balance `shouldReturn` 150+-- >     prop "accumulates deposits" \(Positive a) (Positive b) -> do+-- >         deposit a+-- >         deposit b+-- >         balance `shouldReturn` a + b -- > -- >     it "checks for sufficient funds before withdrawing" $ do -- >         deposit 100@@ -116,6 +112,11 @@     , anyException        -- * Properties+    , modifyArgs+    , modifyMaxSuccess+    , modifyMaxDiscardRatio+    , modifyMaxSize+    , modifyMaxShrinks     , prop     , xprop     , fprop@@ -133,7 +134,9 @@ import Effectful.Dispatch.Static import Effectful.Environment (runEnvironment, withArgs) import Effectful.Exception (Exception, throwIO, try)-import Effectful.HUnit as HUnit+import Effectful.HUnit (Assertion, HUnit, runHUnit, (@?=))+import Effectful.HUnit qualified as HUnit+import Effectful.QuickCheck (Testable, property, unliftProperty) import Test.Hspec qualified as Hspec import Test.Hspec.Core.Spec (ResultStatus (..)) import Test.Hspec.Expectations (Selector, anyException)@@ -430,14 +433,47 @@         instanceOf :: Selector a -> a         instanceOf _ = error "Effectful.Hspec.shouldThrow: broken Typeable instance" +-- | Lifted 'Hspec.modifyArgs'.+modifyArgs+    :: (HasCallStack, Hspec :> es)+    => (QuickCheck.Args -> QuickCheck.Args)+    -> Eff es a+    -> Eff es a+modifyArgs = mapSpec . Hspec.modifyArgs++-- | Lifted 'Hspec.modifyMaxSuccess'.+modifyMaxSuccess :: (HasCallStack, Hspec :> es) => (Int -> Int) -> Eff es a -> Eff es a+modifyMaxSuccess = mapSpec . Hspec.modifyMaxSuccess++-- | Lifted 'Hspec.modifyMaxDiscardRatio'.+modifyMaxDiscardRatio :: (HasCallStack, Hspec :> es) => (Int -> Int) -> Eff es a -> Eff es a+modifyMaxDiscardRatio = mapSpec . Hspec.modifyMaxDiscardRatio++-- | Lifted 'Hspec.modifyMaxSize'.+modifyMaxSize :: (HasCallStack, Hspec :> es) => (Int -> Int) -> Eff es a -> Eff es a+modifyMaxSize = mapSpec . Hspec.modifyMaxSize++-- | Lifted 'Hspec.modifyMaxSize'.+modifyMaxShrinks :: (HasCallStack, Hspec :> es) => (Int -> Int) -> Eff es a -> Eff es a+modifyMaxShrinks = mapSpec . Hspec.modifyMaxShrinks++appendProp+    :: (HasCallStack, Testable prop es, Hspec :> es)+    => (QuickCheck.Property -> Hspec.Spec)+    -> prop+    -> Eff es ()+appendProp f p =+    appendSpec . f =<< unsafeConcUnliftIO Ephemeral Unlimited \unlift ->+        pure . unliftProperty unlift . property $ p+ -- | Lifted 'Hspec.prop'.-prop :: (HasCallStack, QuickCheck.Testable prop, Hspec :> es) => String -> prop -> Eff es ()-prop = (appendSpec .) . Hspec.prop+prop :: (HasCallStack, Testable prop es, Hspec :> es) => String -> prop -> Eff es ()+prop = appendProp . Hspec.prop  -- | Lifted 'Hspec.xprop'.-xprop :: (HasCallStack, QuickCheck.Testable prop, Hspec :> es) => String -> prop -> Eff es ()-xprop = (appendSpec .) . Hspec.xprop+xprop :: (HasCallStack, Testable prop es, Hspec :> es) => String -> prop -> Eff es ()+xprop = appendProp . Hspec.xprop  -- | Lifted 'Hspec.fprop'.-fprop :: (HasCallStack, QuickCheck.Testable prop, Hspec :> es) => String -> prop -> Eff es ()-fprop = (appendSpec .) . Hspec.fprop+fprop :: (HasCallStack, Testable prop es, Hspec :> es) => String -> prop -> Eff es ()+fprop = appendProp . Hspec.fprop
test/Main.hs view
@@ -1,11 +1,16 @@ {-# OPTIONS_GHC -Wno-missing-local-signatures #-} {-# OPTIONS_GHC -Wno-monomorphism-restriction #-}+{-# OPTIONS_GHC -Wno-name-shadowing #-} {-# OPTIONS_GHC -Wno-type-defaults #-} +{- HLINT ignore "Redundant reverse" -}+ module Main where  import Effectful import Effectful.Hspec+import Effectful.QuickCheck ((.&&.), (===))+import Effectful.State.Static.Local (evalState, get, modify) import Prelude  main :: IO ()@@ -49,3 +54,12 @@     it "handles shouldNotReturn" $ do         let action = pure (1 :: Int) :: Eff es Int         action `shouldNotReturn` 2++    prop "pure prop" \(xs :: [Int]) ->+        (reverse . reverse) xs == xs++    prop "eff prop" \(n :: Int) ->+        evalState n do+            modify @Int (+ 1)+            x <- get+            pure $ (x === n + 1) .&&. (x > n)