packages feed

hspec-core 2.11.9 → 2.11.10

raw patch · 21 files changed

+468/−48 lines, 21 filesdep +containersdep ~hspec-metaPVP: major bump suggested

API removals or changes: PVP suggests a major version bump

Dependencies added: containers

Dependency ranges changed: hspec-meta

API changes (from Hackage documentation)

+ Test.Hspec.Core.Extension: data Config
+ Test.Hspec.Core.Extension: data Item a
+ Test.Hspec.Core.Extension: data Option
+ Test.Hspec.Core.Extension: data SpecM a r
+ Test.Hspec.Core.Extension: modifyConfig :: (Config -> Config) -> SpecWith a
+ Test.Hspec.Core.Extension: registerOptions :: HasCallStack => [Option] -> SpecWith a
+ Test.Hspec.Core.Extension: registerTransformation :: (Config -> [SpecTree] -> [SpecTree]) -> SpecWith a
+ Test.Hspec.Core.Extension: runIO :: IO r -> SpecM a r
+ Test.Hspec.Core.Extension: type SpecTree = SpecTree ()
+ Test.Hspec.Core.Extension: type SpecWith a = SpecM a ()
+ Test.Hspec.Core.Extension.Config: ColorAlways :: ColorMode
+ Test.Hspec.Core.Extension.Config: ColorAuto :: ColorMode
+ Test.Hspec.Core.Extension.Config: ColorNever :: ColorMode
+ Test.Hspec.Core.Extension.Config: Config :: Bool -> Bool -> Bool -> Bool -> Bool -> Bool -> Bool -> Maybe Int -> Bool -> Bool -> Bool -> Maybe Integer -> Maybe Integer -> Maybe FilePath -> Bool -> Bool -> Maybe (Path -> Bool) -> Maybe (Path -> Bool) -> Maybe Int -> Maybe Int -> Maybe Int -> Maybe Int -> Maybe Int -> ColorMode -> UnicodeMode -> Bool -> Maybe Int -> Maybe (Maybe Int -> String -> String -> IO ()) -> Bool -> (Bool -> String -> String -> (String, String)) -> (SomeException -> String) -> Bool -> Bool -> [(String, FormatConfig -> IO Format)] -> Maybe (FormatConfig -> IO Format) -> Maybe Formatter -> Bool -> Maybe Int -> Annotations -> Config
+ Test.Hspec.Core.Extension.Config: UnicodeAlways :: UnicodeMode
+ Test.Hspec.Core.Extension.Config: UnicodeAuto :: UnicodeMode
+ Test.Hspec.Core.Extension.Config: UnicodeNever :: UnicodeMode
+ Test.Hspec.Core.Extension.Config: [configAnnotations] :: Config -> Annotations
+ Test.Hspec.Core.Extension.Config: [configAvailableFormatters] :: Config -> [(String, FormatConfig -> IO Format)]
+ Test.Hspec.Core.Extension.Config: [configColorMode] :: Config -> ColorMode
+ Test.Hspec.Core.Extension.Config: [configConcurrentJobs] :: Config -> Maybe Int
+ Test.Hspec.Core.Extension.Config: [configDiffContext] :: Config -> Maybe Int
+ Test.Hspec.Core.Extension.Config: [configDiff] :: Config -> Bool
+ Test.Hspec.Core.Extension.Config: [configDryRun] :: Config -> Bool
+ Test.Hspec.Core.Extension.Config: [configExpertMode] :: Config -> Bool
+ Test.Hspec.Core.Extension.Config: [configExternalDiff] :: Config -> Maybe (Maybe Int -> String -> String -> IO ())
+ Test.Hspec.Core.Extension.Config: [configFailFast] :: Config -> Bool
+ Test.Hspec.Core.Extension.Config: [configFailOnEmptyDescription] :: Config -> Bool
+ Test.Hspec.Core.Extension.Config: [configFailOnEmpty] :: Config -> Bool
+ Test.Hspec.Core.Extension.Config: [configFailOnFocused] :: Config -> Bool
+ Test.Hspec.Core.Extension.Config: [configFailOnPending] :: Config -> Bool
+ Test.Hspec.Core.Extension.Config: [configFailureReport] :: Config -> Maybe FilePath
+ Test.Hspec.Core.Extension.Config: [configFilterPredicate] :: Config -> Maybe (Path -> Bool)
+ Test.Hspec.Core.Extension.Config: [configFocusedOnly] :: Config -> Bool
+ Test.Hspec.Core.Extension.Config: [configFormatException] :: Config -> SomeException -> String
+ Test.Hspec.Core.Extension.Config: [configFormat] :: Config -> Maybe (FormatConfig -> IO Format)
+ Test.Hspec.Core.Extension.Config: [configFormatter] :: Config -> Maybe Formatter
+ Test.Hspec.Core.Extension.Config: [configHtmlOutput] :: Config -> Bool
+ Test.Hspec.Core.Extension.Config: [configIgnoreConfigFile] :: Config -> Bool
+ Test.Hspec.Core.Extension.Config: [configPrettyPrintFunction] :: Config -> Bool -> String -> String -> (String, String)
+ Test.Hspec.Core.Extension.Config: [configPrettyPrint] :: Config -> Bool
+ Test.Hspec.Core.Extension.Config: [configPrintCpuTime] :: Config -> Bool
+ Test.Hspec.Core.Extension.Config: [configPrintSlowItems] :: Config -> Maybe Int
+ Test.Hspec.Core.Extension.Config: [configQuickCheckMaxDiscardRatio] :: Config -> Maybe Int
+ Test.Hspec.Core.Extension.Config: [configQuickCheckMaxShrinks] :: Config -> Maybe Int
+ Test.Hspec.Core.Extension.Config: [configQuickCheckMaxSize] :: Config -> Maybe Int
+ Test.Hspec.Core.Extension.Config: [configQuickCheckMaxSuccess] :: Config -> Maybe Int
+ Test.Hspec.Core.Extension.Config: [configQuickCheckSeed] :: Config -> Maybe Integer
+ Test.Hspec.Core.Extension.Config: [configRandomize] :: Config -> Bool
+ Test.Hspec.Core.Extension.Config: [configRerunAllOnSuccess] :: Config -> Bool
+ Test.Hspec.Core.Extension.Config: [configRerun] :: Config -> Bool
+ Test.Hspec.Core.Extension.Config: [configSeed] :: Config -> Maybe Integer
+ Test.Hspec.Core.Extension.Config: [configSkipPredicate] :: Config -> Maybe (Path -> Bool)
+ Test.Hspec.Core.Extension.Config: [configSmallCheckDepth] :: Config -> Maybe Int
+ Test.Hspec.Core.Extension.Config: [configTimes] :: Config -> Bool
+ Test.Hspec.Core.Extension.Config: [configUnicodeMode] :: Config -> UnicodeMode
+ Test.Hspec.Core.Extension.Config: data ColorMode
+ Test.Hspec.Core.Extension.Config: data Config
+ Test.Hspec.Core.Extension.Config: data UnicodeMode
+ Test.Hspec.Core.Extension.Config: getAnnotation :: Typeable value => Config -> Maybe value
+ Test.Hspec.Core.Extension.Config: setAnnotation :: Typeable value => value -> Config -> Config
+ Test.Hspec.Core.Extension.Config: type Path = ([String], String)
+ Test.Hspec.Core.Extension.Item: ColorizedReason :: String -> FailureReason
+ Test.Hspec.Core.Extension.Item: Error :: Maybe String -> SomeException -> FailureReason
+ Test.Hspec.Core.Extension.Item: ExpectedButGot :: Maybe String -> String -> String -> FailureReason
+ Test.Hspec.Core.Extension.Item: Failure :: Maybe Location -> FailureReason -> ResultStatus
+ Test.Hspec.Core.Extension.Item: Item :: String -> Maybe Location -> Maybe Bool -> Bool -> Annotations -> (Params -> (ActionWith a -> IO ()) -> ProgressCallback -> IO Result) -> Item a
+ Test.Hspec.Core.Extension.Item: Location :: FilePath -> Int -> Int -> Location
+ Test.Hspec.Core.Extension.Item: NoReason :: FailureReason
+ Test.Hspec.Core.Extension.Item: Params :: Args -> Maybe Int -> Params
+ Test.Hspec.Core.Extension.Item: Pending :: Maybe Location -> Maybe String -> ResultStatus
+ Test.Hspec.Core.Extension.Item: Reason :: String -> FailureReason
+ Test.Hspec.Core.Extension.Item: Result :: String -> ResultStatus -> Result
+ Test.Hspec.Core.Extension.Item: Success :: ResultStatus
+ Test.Hspec.Core.Extension.Item: [itemAnnotations] :: Item a -> Annotations
+ Test.Hspec.Core.Extension.Item: [itemExample] :: Item a -> Params -> (ActionWith a -> IO ()) -> ProgressCallback -> IO Result
+ Test.Hspec.Core.Extension.Item: [itemIsFocused] :: Item a -> Bool
+ Test.Hspec.Core.Extension.Item: [itemIsParallelizable] :: Item a -> Maybe Bool
+ Test.Hspec.Core.Extension.Item: [itemLocation] :: Item a -> Maybe Location
+ Test.Hspec.Core.Extension.Item: [itemRequirement] :: Item a -> String
+ Test.Hspec.Core.Extension.Item: [locationColumn] :: Location -> Int
+ Test.Hspec.Core.Extension.Item: [locationFile] :: Location -> FilePath
+ Test.Hspec.Core.Extension.Item: [locationLine] :: Location -> Int
+ Test.Hspec.Core.Extension.Item: [paramsQuickCheckArgs] :: Params -> Args
+ Test.Hspec.Core.Extension.Item: [paramsSmallCheckDepth] :: Params -> Maybe Int
+ Test.Hspec.Core.Extension.Item: [resultInfo] :: Result -> String
+ Test.Hspec.Core.Extension.Item: [resultStatus] :: Result -> ResultStatus
+ Test.Hspec.Core.Extension.Item: data FailureReason
+ Test.Hspec.Core.Extension.Item: data Item a
+ Test.Hspec.Core.Extension.Item: data Location
+ Test.Hspec.Core.Extension.Item: data Params
+ Test.Hspec.Core.Extension.Item: data Result
+ Test.Hspec.Core.Extension.Item: data ResultStatus
+ Test.Hspec.Core.Extension.Item: getAnnotation :: Typeable value => Item a -> Maybe value
+ Test.Hspec.Core.Extension.Item: isFocused :: Item a -> Bool
+ Test.Hspec.Core.Extension.Item: pending :: Item a -> Item a
+ Test.Hspec.Core.Extension.Item: pendingWith :: String -> Item a -> Item a
+ Test.Hspec.Core.Extension.Item: setAnnotation :: Typeable value => value -> Item a -> Item a
+ Test.Hspec.Core.Extension.Item: type ActionWith a = a -> IO ()
+ Test.Hspec.Core.Extension.Item: type Progress = (Int, Int)
+ Test.Hspec.Core.Extension.Item: type ProgressCallback = Progress -> IO ()
+ Test.Hspec.Core.Extension.Option: argument :: String -> String -> (String -> Config -> Maybe Config) -> String -> Option
+ Test.Hspec.Core.Extension.Option: data Option
+ Test.Hspec.Core.Extension.Option: flag :: String -> (Bool -> Config -> Config) -> String -> Option
+ Test.Hspec.Core.Extension.Option: noArgument :: String -> (Config -> Config) -> String -> Option
+ Test.Hspec.Core.Extension.Option: optionalArgument :: String -> String -> (Maybe String -> Config -> Maybe Config) -> String -> Option
+ Test.Hspec.Core.Extension.Spec: mapItems :: (Item a -> Item b) -> SpecWith a -> SpecWith b
+ Test.Hspec.Core.Extension.Tree: filterItems :: (Item () -> Bool) -> [SpecTree] -> [SpecTree]
+ Test.Hspec.Core.Extension.Tree: mapItems :: (Item () -> Item ()) -> [SpecTree] -> [SpecTree]
+ Test.Hspec.Core.Extension.Tree: type SpecTree = SpecTree ()
+ Test.Hspec.Core.Runner: [configAnnotations] :: Config -> Annotations
+ Test.Hspec.Core.Spec: [itemAnnotations] :: Item a -> Annotations
- Test.Hspec.Core.Runner: Config :: Bool -> Bool -> Bool -> Bool -> Bool -> Bool -> Bool -> Maybe Int -> Bool -> Bool -> Bool -> Maybe Integer -> Maybe Integer -> Maybe FilePath -> Bool -> Bool -> Maybe (Path -> Bool) -> Maybe (Path -> Bool) -> Maybe Int -> Maybe Int -> Maybe Int -> Maybe Int -> Maybe Int -> ColorMode -> UnicodeMode -> Bool -> Maybe Int -> Maybe (Maybe Int -> String -> String -> IO ()) -> Bool -> (Bool -> String -> String -> (String, String)) -> (SomeException -> String) -> Bool -> Bool -> [(String, FormatConfig -> IO Format)] -> Maybe (FormatConfig -> IO Format) -> Maybe Formatter -> Bool -> Maybe Int -> Config
+ Test.Hspec.Core.Runner: Config :: Bool -> Bool -> Bool -> Bool -> Bool -> Bool -> Bool -> Maybe Int -> Bool -> Bool -> Bool -> Maybe Integer -> Maybe Integer -> Maybe FilePath -> Bool -> Bool -> Maybe (Path -> Bool) -> Maybe (Path -> Bool) -> Maybe Int -> Maybe Int -> Maybe Int -> Maybe Int -> Maybe Int -> ColorMode -> UnicodeMode -> Bool -> Maybe Int -> Maybe (Maybe Int -> String -> String -> IO ()) -> Bool -> (Bool -> String -> String -> (String, String)) -> (SomeException -> String) -> Bool -> Bool -> [(String, FormatConfig -> IO Format)] -> Maybe (FormatConfig -> IO Format) -> Maybe Formatter -> Bool -> Maybe Int -> Annotations -> Config
- Test.Hspec.Core.Spec: Item :: String -> Maybe Location -> Maybe Bool -> Bool -> (Params -> (ActionWith a -> IO ()) -> ProgressCallback -> IO Result) -> Item a
+ Test.Hspec.Core.Spec: Item :: String -> Maybe Location -> Maybe Bool -> Bool -> Annotations -> (Params -> (ActionWith a -> IO ()) -> ProgressCallback -> IO Result) -> Item a

Files

hspec-core.cabal view
@@ -1,11 +1,11 @@ cabal-version: 1.12 --- This file has been generated from package.yaml by hpack version 0.36.0.+-- This file has been generated from package.yaml by hpack version 0.37.0. -- -- see: https://github.com/sol/hpack  name:             hspec-core-version:          2.11.9+version:          2.11.10 license:          MIT license-file:     LICENSE copyright:        (c) 2011-2024 Simon Hengel,@@ -41,6 +41,7 @@     , array     , base >=4.9.0.0 && <5     , call-stack >=0.2.0+    , containers     , deepseq     , directory     , filepath@@ -53,6 +54,12 @@     , time     , transformers >=0.2.2.0   exposed-modules:+      Test.Hspec.Core.Extension+      Test.Hspec.Core.Extension.Item+      Test.Hspec.Core.Extension.Spec+      Test.Hspec.Core.Extension.Tree+      Test.Hspec.Core.Extension.Option+      Test.Hspec.Core.Extension.Config       Test.Hspec.Core.Spec       Test.Hspec.Core.Hooks       Test.Hspec.Core.Runner@@ -69,6 +76,7 @@       GetOpt.Declarative.Types       GetOpt.Declarative.Util       NonEmpty+      Test.Hspec.Core.Annotations       Test.Hspec.Core.Clock       Test.Hspec.Core.Compat       Test.Hspec.Core.Config@@ -76,6 +84,7 @@       Test.Hspec.Core.Config.Options       Test.Hspec.Core.Example       Test.Hspec.Core.Example.Location+      Test.Hspec.Core.Extension.Config.Type       Test.Hspec.Core.FailureReport       Test.Hspec.Core.Formatters.Diff       Test.Hspec.Core.Formatters.Internal@@ -125,12 +134,13 @@     , base >=4.9.0.0 && <5     , base-orphans     , call-stack >=0.2.0+    , containers     , deepseq     , directory     , filepath     , haskell-lexer     , hspec-expectations ==0.8.4.*-    , hspec-meta ==2.11.9+    , hspec-meta ==2.11.10     , process     , quickcheck-io >=0.2.0     , random@@ -148,6 +158,7 @@       GetOpt.Declarative.Types       GetOpt.Declarative.Util       NonEmpty+      Test.Hspec.Core.Annotations       Test.Hspec.Core.Clock       Test.Hspec.Core.Compat       Test.Hspec.Core.Config@@ -155,6 +166,13 @@       Test.Hspec.Core.Config.Options       Test.Hspec.Core.Example       Test.Hspec.Core.Example.Location+      Test.Hspec.Core.Extension+      Test.Hspec.Core.Extension.Config+      Test.Hspec.Core.Extension.Config.Type+      Test.Hspec.Core.Extension.Item+      Test.Hspec.Core.Extension.Option+      Test.Hspec.Core.Extension.Spec+      Test.Hspec.Core.Extension.Tree       Test.Hspec.Core.FailureReport       Test.Hspec.Core.Format       Test.Hspec.Core.Formatters@@ -190,6 +208,7 @@       Helper       Mock       SpecHook+      Test.Hspec.Core.AnnotationsSpec       Test.Hspec.Core.ClockSpec       Test.Hspec.Core.CompatSpec       Test.Hspec.Core.Config.DefinitionSpec
+ src/Test/Hspec/Core/Annotations.hs view
@@ -0,0 +1,29 @@+{-# LANGUAGE CPP #-}+{-# LANGUAGE GeneralizedNewtypeDeriving #-}+{-# LANGUAGE ScopedTypeVariables #-}+module Test.Hspec.Core.Annotations (+  Annotations+, setValue+, getValue+) where++import           Prelude ()+import           Test.Hspec.Core.Compat++import           Data.Typeable+import           Data.Dynamic+import           Data.Map (Map)+import qualified Data.Map as Map++newtype Annotations = Annotations (Map TypeRep Dynamic)+  deriving (+#if MIN_VERSION_base(4,11,0)+  Semigroup,+#endif+  Monoid)++setValue :: Typeable value => value -> Annotations -> Annotations+setValue value (Annotations values) = Annotations $ Map.insert (typeOf value) (toDyn value) values++getValue :: forall value. Typeable value => Annotations -> Maybe value+getValue (Annotations values) = Map.lookup (typeOf (undefined :: value)) values >>= fromDynamic
src/Test/Hspec/Core/Compat.hs view
@@ -19,6 +19,7 @@ import           Data.Maybe as Imports import           Data.Foldable as Imports import           GHC.Stack as Imports (HasCallStack, withFrozenCallStack)+import           Data.Typeable as Imports (Typeable)  import           System.IO import           System.Exit@@ -65,7 +66,7 @@   , sum   ) -import           Data.Typeable (Typeable, typeOf, typeRepTyCon, tyConModule, tyConName)+import           Data.Typeable (typeOf, typeRepTyCon, tyConModule, tyConName) import           Data.IORef as Imports  #if MIN_VERSION_base(4,12,0)
src/Test/Hspec/Core/Config.hs view
@@ -61,7 +61,7 @@   }   where -    mSeed = configSeed config <|> deprecatedQuickCheckSeed config <|> (failureReportSeed <$> mFailureReport)+    mSeed = getSeed config <|> (failureReportSeed <$> mFailureReport)     mMaxSuccess = configQuickCheckMaxSuccess config <|> (failureReportMaxSuccess <$> mFailureReport)     mMaxSize = configQuickCheckMaxSize config <|> (failureReportMaxSize <$> mFailureReport)     mMaxDiscardRatio = configQuickCheckMaxDiscardRatio config <|> (failureReportMaxDiscardRatio <$> mFailureReport)
src/Test/Hspec/Core/Config/Definition.hs view
@@ -3,16 +3,27 @@   Config(..) , ColorMode(..) , UnicodeMode(..)-, filterOr , mkDefaultConfig +, filterOr++, setConfigAnnotation+, getConfigAnnotation++, addExtensionOptions+, getExtensionOptions++, getSeed+, getFormatter+ , commandLineOnlyOptions , formatterOptions , smallCheckOptions , quickCheckOptions , runnerOptions -, deprecatedQuickCheckSeed+, flag+, option  #ifdef TEST , splitOn@@ -26,14 +37,40 @@ import           System.IO (openTempFile, hClose) import           System.Process (system) +import           Test.Hspec.Core.Annotations (Annotations)+import qualified Test.Hspec.Core.Annotations as Annotations+ import           Test.Hspec.Core.Format (Format, FormatConfig) import           Test.Hspec.Core.Formatters.Pretty (pretty2) import qualified Test.Hspec.Core.Formatters.V1.Monad as V1+import qualified Test.Hspec.Core.Formatters.V1.Internal as V1 (formatterToFormat) import           Test.Hspec.Core.Util  import           GetOpt.Declarative +setConfigAnnotation :: Typeable value => value -> Config -> Config+setConfigAnnotation value config = config { configAnnotations = Annotations.setValue value $ configAnnotations config } +getConfigAnnotation :: Typeable value => Config -> Maybe value+getConfigAnnotation = Annotations.getValue . configAnnotations++newtype ExtensionOptions = ExtensionOptions { unExtensionOptions :: [(String, [Option Config])] }++addExtensionOptions :: String -> [Option Config] -> Config -> Config+addExtensionOptions section opts config = setExtensionOptions ((section, opts) : getExtensionOptions config) config++setExtensionOptions :: [(String, [Option Config])] -> Config -> Config+setExtensionOptions = setConfigAnnotation . ExtensionOptions++getExtensionOptions :: Config -> [(String, [Option Config])]+getExtensionOptions = maybe [] unExtensionOptions . getConfigAnnotation++getFormatter :: Config -> Maybe (FormatConfig -> IO Format)+getFormatter config = configFormat config <|> V1.formatterToFormat <$> configFormatter config++getSeed :: Config -> Maybe Integer+getSeed config = configSeed config <|> configQuickCheckSeed config+ data ColorMode = ColorAuto | ColorNever | ColorAlways   deriving (Eq, Show) @@ -91,13 +128,11 @@ , configFormatter :: Maybe V1.Formatter , configHtmlOutput :: Bool , configConcurrentJobs :: Maybe Int+, configAnnotations :: Annotations } {-# DEPRECATED configFormatter "Use [@useFormatter@](https://hackage.haskell.org/package/hspec-api/docs/Test-Hspec-Api-Formatters-V1.html#v:useFormatter) instead." #-} {-# DEPRECATED configQuickCheckSeed "Use `configSeed` instead." #-} -deprecatedQuickCheckSeed :: Config -> Maybe Integer-deprecatedQuickCheckSeed = configQuickCheckSeed- mkDefaultConfig :: [(String, FormatConfig -> IO Format)] -> Config mkDefaultConfig formatters = Config {   configIgnoreConfigFile = False@@ -138,6 +173,7 @@ , configFormatter = Nothing , configHtmlOutput = False , configConcurrentJobs = Nothing+, configAnnotations = mempty }  defaultDiffContext :: Int@@ -160,7 +196,7 @@ option :: String -> OptionSetter config -> String -> Option config option name arg help = Option name Nothing arg help True -flag :: String -> (Bool -> Config -> Config) -> String -> Option Config+flag :: String -> (Bool -> config -> config) -> String -> Option config flag name setter = option name (Flag setter)  mkOptionNoArg :: String -> Maybe Char -> (Config -> Config) -> String -> Option Config@@ -172,7 +208,7 @@ undocumented :: Option config -> Option config undocumented opt = opt {optionDocumented = False} -argument :: String -> (String -> Maybe a) -> (a -> Config -> Config) -> OptionSetter Config+argument :: String -> (String -> Maybe a) -> (a -> config -> config) -> OptionSetter config argument name parser setter = Arg name $ \ input c -> flip setter c <$> parser input  formatterOptions :: [(String, FormatConfig -> IO Format)] -> [Option Config]
src/Test/Hspec/Core/Config/Options.hs view
@@ -11,7 +11,6 @@  import           System.Exit -import           Test.Hspec.Core.Format (Format, FormatConfig) import           Test.Hspec.Core.Config.Definition import qualified GetOpt.Declarative as Declarative import           GetOpt.Declarative.Interpret (parse, interpretOptions, ParseResult(..))@@ -22,18 +21,21 @@ envVarName :: String envVarName = "HSPEC_OPTIONS" -commandLineOptions :: [(String, FormatConfig -> IO Format)] -> [(String, [Declarative.Option Config])]-commandLineOptions formatters =+commandLineOptions :: Config -> [(String, [Declarative.Option Config])]+commandLineOptions config =     ("OPTIONS", commandLineOnlyOptions)-  : otherOptions formatters+  : otherOptions config -otherOptions :: [(String, FormatConfig -> IO Format)] -> [(String, [Declarative.Option Config])]-otherOptions formatters = [+otherOptions :: Config -> [(String, [Declarative.Option Config])]+otherOptions config = [     ("RUNNER OPTIONS", runnerOptions)   , ("FORMATTER OPTIONS", formatterOptions formatters)   , ("OPTIONS FOR QUICKCHECK", quickCheckOptions)   , ("OPTIONS FOR SMALLCHECK", smallCheckOptions)-  ]+  ] ++ extensionOptions+  where+    formatters = configAvailableFormatters config+    extensionOptions = getExtensionOptions config  ignoreConfigFile :: Config -> [String] -> IO Bool ignoreConfigFile config args = do@@ -52,18 +54,15 @@   >>= traverse (parseCommandLineOptions prog args)  parseCommandLineOptions :: String -> [String] -> Config -> Either (ExitCode, String) Config-parseCommandLineOptions prog args config = case Declarative.parseCommandLineOptions (commandLineOptions formatters) prog args config of+parseCommandLineOptions prog args config = case Declarative.parseCommandLineOptions (commandLineOptions config) prog args config of   Success c -> Right c   Help message -> Left (ExitSuccess, message)   Failure message -> Left (ExitFailure 1, message)-  where-    formatters = configAvailableFormatters config  parseEnvironmentOptions :: [(String, String)] -> Config -> Either (ExitCode, String) ([String], Config)-parseEnvironmentOptions env config = case Declarative.parseEnvironmentOptions "HSPEC" env config (concatMap snd $ commandLineOptions formatters) of+parseEnvironmentOptions env config = case Declarative.parseEnvironmentOptions "HSPEC" env config (concatMap snd $ commandLineOptions config) of   (warnings, c) -> Right (map formatWarning warnings, c)   where-    formatters = configAvailableFormatters config     formatWarning (Declarative.InvalidValue name value) = "invalid value `" ++ value ++ "' for environment variable " ++ name  parseFileOptions :: String -> Config -> ConfigFile -> Either (ExitCode, String) Config@@ -80,9 +79,7 @@   Left err -> failure err   where     options :: [Declarative.Option Config]-    options = filter Declarative.optionDocumented $ concatMap snd (otherOptions formatters)--    formatters = configAvailableFormatters config+    options = filter Declarative.optionDocumented $ concatMap snd (otherOptions config)      failure err = Left (ExitFailure 1, prog ++ ": " ++ message)       where
+ src/Test/Hspec/Core/Extension.hs view
@@ -0,0 +1,112 @@+{-# OPTIONS_GHC -fno-warn-deprecations #-}+-- | Stability: unstable+module Test.Hspec.Core.Extension {-# WARNING "This API is experimental." #-} (+-- * Lifecycle of a test run+{- |+A test run goes through four distinct phases:++1. A tree of spec items and a default `Config` are constructed in `SpecM`.+2. Command-line options are parsed.  This transforms the default `Config` that was constructed in phase 1.+3. The tree of spec items is transformed in various ways, depending on specific `Config` values.+4. Each spec item is executed and its result is reported to the user.++An extension can directly influence phase 1, and indirectly influence phases 2-4.++When writing extensions the following imports are recommended:++@+import "Test.Hspec.Core.Extension"+import "Test.Hspec.Core.Extension.Config" qualified as Config+import "Test.Hspec.Core.Extension.Option" qualified as Option+import "Test.Hspec.Core.Extension.Item" qualified as Item+import "Test.Hspec.Core.Extension.Spec" qualified as Spec+import "Test.Hspec.Core.Extension.Tree" qualified as Tree+@+-}++-- ** Phase 1: Constructing a spec tree+{- |+- An extension can use @Spec.`Test.Hspec.Core.Extension.Spec.mapItems`@ to transform spec items in phase 1.++    * @Item.`setAnnotation`@ can be used to add custom metadata to a spec `Item`.++- An extension can use `modifyConfig` to modify the default config.++    * @Config.`Test.Hspec.Core.Extension.Config.setAnnotation`@ can be used to add custom metadata to the default `Config`.+-}+  runIO+, modifyConfig++-- ** Phase 2: Parsing command-line options+{- |+An extension can use `registerOptions` during phase 1 to register custom command-line options, and as a consequence indirectly influence this phase.++* Options can use @Config.`Test.Hspec.Core.Extension.Config.setAnnotation`@ to add custom metadata to the `Config`.+-}+, Option+, registerOptions++-- ** Phase 3: Transforming the spec tree+{- |+An extension can use `registerTransformation` during phase 1 to indirectly influence this phase.+-}+, registerTransformation++-- ** Phase 4: Reporting results+{- |+An extension can register a [custom formatter](https://hspec.github.io/extending-hspec-formatter.html) in phase 1 to indirectly influence this phase.+-}++-- * Types+{- |+Operations on these types are provided by the following modules respectively:++* "Test.Hspec.Core.Extension.Config"+* "Test.Hspec.Core.Extension.Item"+* "Test.Hspec.Core.Extension.Spec"+* "Test.Hspec.Core.Extension.Tree"+-}+, Config+, Item+, SpecM+, SpecWith+, SpecTree+) where++import           Prelude ()+import           Test.Hspec.Core.Compat++import qualified Data.CallStack as CallStack++import qualified GetOpt.Declarative as Declarative+import           Test.Hspec.Core.Spec (SpecM, SpecWith, runIO, modifyConfig)+import qualified Test.Hspec.Core.Spec as Core+import qualified Test.Hspec.Core.Config.Definition as Core++import           Test.Hspec.Core.Extension.Config (Config)+import qualified Test.Hspec.Core.Extension.Config.Type as Config+import           Test.Hspec.Core.Extension.Option+import           Test.Hspec.Core.Extension.Item+import           Test.Hspec.Core.Extension.Tree++registerOptions :: HasCallStack => [Option] -> SpecWith a+registerOptions = Core.modifyConfig . Core.addExtensionOptions section . map liftOption+  where+    section = "OPTIONS FOR " <> package+    package = maybe "main" (CallStack.srcLocPackage . snd) CallStack.callSite++    liftOption :: Option -> Declarative.Option Core.Config+    liftOption = Config.unOption++{- |+Register a transformation that transforms the spec tree in phase 3.++The registered transformation can use:++- @Tree.`mapItems`@ to modify spec items+- @Tree.`filterItems`@ to discard spec items+- @Config.`Test.Hspec.Core.Extension.Config.getAnnotation`@ to access custom config metadata+- @Item.`getAnnotation`@ to access custom item metadata+-}+registerTransformation :: (Config -> [SpecTree] -> [SpecTree]) -> SpecWith a+registerTransformation = modifyConfig . Config.addSpecTransformation
+ src/Test/Hspec/Core/Extension/Config.hs view
@@ -0,0 +1,19 @@+{-# OPTIONS_GHC -fno-warn-deprecations #-}+module Test.Hspec.Core.Extension.Config {-# WARNING "This API is experimental." #-} (+-- * Types+  Config(..)+, Path+, ColorMode(..)+, UnicodeMode(..)++-- * Operations+, setAnnotation+, getAnnotation+) where++import           Prelude ()++import           Test.Hspec.Core.Format+import           Test.Hspec.Core.Config.Definition (ColorMode(..), UnicodeMode(..))++import           Test.Hspec.Core.Extension.Config.Type
+ src/Test/Hspec/Core/Extension/Config/Type.hs view
@@ -0,0 +1,43 @@+{-# OPTIONS_GHC -fno-warn-deprecations #-}+module Test.Hspec.Core.Extension.Config.Type (+  Option(..)+, Config(..)++, setAnnotation+, getAnnotation++, addSpecTransformation+, applySpecTransformation+) where++import           Prelude ()+import           Test.Hspec.Core.Compat++import qualified GetOpt.Declarative as Declarative++import           Test.Hspec.Core.Config.Definition (Config(..))+import qualified Test.Hspec.Core.Config.Definition as Core++import           Test.Hspec.Core.Extension.Tree (SpecTree)++newtype Option = Option { unOption :: Declarative.Option Config }++setAnnotation :: Typeable value => value -> Config -> Config+setAnnotation = Core.setConfigAnnotation++getAnnotation :: Typeable value => Config -> Maybe value+getAnnotation = Core.getConfigAnnotation++newtype SpecTransformation = SpecTransformation { unSpecTransformation :: Config -> [SpecTree] -> [SpecTree] }++setSpecTransformation :: (Config -> [SpecTree] -> [SpecTree]) -> Config -> Config+setSpecTransformation = setAnnotation . SpecTransformation++getSpecTransformation :: Config -> Config -> [SpecTree] -> [SpecTree]+getSpecTransformation = maybe (\ _ -> id) unSpecTransformation . getAnnotation++addSpecTransformation :: (Config -> [SpecTree] -> [SpecTree]) -> Config -> Config+addSpecTransformation f config = setSpecTransformation (\ c -> f c . getSpecTransformation config c) config++applySpecTransformation :: Core.Config -> [SpecTree] -> [SpecTree]+applySpecTransformation config = getSpecTransformation config config
+ src/Test/Hspec/Core/Extension/Item.hs view
@@ -0,0 +1,46 @@+module Test.Hspec.Core.Extension.Item {-# WARNING "This API is experimental." #-} (+-- * Types+  Item(..)+, Location(..)+, Params(..)+, ActionWith+, Progress+, ProgressCallback+, Result(..)+, ResultStatus(..)+, FailureReason(..)++-- * Operations+, isFocused+, pending+, pendingWith+, setAnnotation+, getAnnotation+) where++import           Prelude ()+import           Test.Hspec.Core.Compat++import           Test.Hspec.Core.Spec hiding (pending, pendingWith)+import           Test.Hspec.Core.Tree++isFocused :: Item a -> Bool+isFocused = itemIsFocused++pending :: Item a -> Item a+pending item = item { itemExample = \ _params _hook _progress -> result }+  where+    result :: IO Result+    result = return $ Result "" (Pending Nothing Nothing)++pendingWith :: String -> Item a -> Item a+pendingWith reason item = item { itemExample = \ _params _hook _progress -> result }+  where+    result :: IO Result+    result = return $ Result "" (Pending Nothing (Just reason))++setAnnotation :: Typeable value => value -> Item a -> Item a+setAnnotation = setItemAnnotation++getAnnotation :: Typeable value => Item a -> Maybe value+getAnnotation = getItemAnnotation
+ src/Test/Hspec/Core/Extension/Option.hs view
@@ -0,0 +1,27 @@+module Test.Hspec.Core.Extension.Option {-# WARNING "This API is experimental." #-} (+  Option+, flag+, argument+, noArgument+, optionalArgument+) where++import           Prelude ()+import           Test.Hspec.Core.Compat++import qualified GetOpt.Declarative as Declarative+import qualified Test.Hspec.Core.Config.Definition as Core++import           Test.Hspec.Core.Extension.Config.Type (Option(..), Config)++flag :: String -> (Bool -> Config -> Config) -> String -> Option+flag name setter = Option . Core.flag name setter++argument :: String -> String -> (String -> Config -> Maybe Config) -> String -> Option+argument name argumentName setter = Option . Core.option name (Declarative.Arg argumentName setter)++optionalArgument :: String -> String -> (Maybe String -> Config -> Maybe Config) -> String -> Option+optionalArgument name argumentName setter = Option . Core.option name (Declarative.OptArg argumentName setter)++noArgument :: String -> (Config -> Config) -> String -> Option+noArgument name setter help = Option $ Declarative.Option name Nothing (Declarative.NoArg setter) help False
+ src/Test/Hspec/Core/Extension/Spec.hs view
@@ -0,0 +1,10 @@+module Test.Hspec.Core.Extension.Spec {-# WARNING "This API is experimental." #-} (+  mapItems+) where++import           Prelude ()++import           Test.Hspec.Core.Spec++mapItems :: (Item a -> Item b) -> SpecWith a -> SpecWith b+mapItems = mapSpecItem_
+ src/Test/Hspec/Core/Extension/Tree.hs view
@@ -0,0 +1,19 @@+module Test.Hspec.Core.Extension.Tree {-# WARNING "This API is experimental." #-} (+  SpecTree+, mapItems+, filterItems+) where++import           Prelude ()+import           Test.Hspec.Core.Compat++import           Test.Hspec.Core.Spec hiding (SpecTree)+import qualified Test.Hspec.Core.Spec as Core++type SpecTree = Core.SpecTree ()++mapItems :: (Item () -> Item ()) -> [SpecTree] -> [SpecTree]+mapItems = map . fmap++filterItems :: (Item () -> Bool) -> [SpecTree] -> [SpecTree]+filterItems = filterForest
src/Test/Hspec/Core/Formatters/Internal.hs view
@@ -60,7 +60,7 @@  import qualified System.IO as IO import           System.IO (stdout)-import           System.Console.ANSI+import           System.Console.ANSI hiding (clearLine) import           Control.Monad.Trans.Reader (ReaderT(..), ask) import           Control.Monad.IO.Class import           Data.Char (isSpace)@@ -271,11 +271,20 @@ writeTransient :: String -> FormatM () writeTransient new = do   reportProgress <- getConfigValue formatConfigReportProgress-  when reportProgress $ do-    write new-    liftIO $ IO.hFlush stdout-    write $ "\r" ++ replicate (length new) ' ' ++ "\r"+  when reportProgress . liftIO $ do+    bracket_ disableLineWrapping enableLineWrapping $ writePlain new+    IO.hFlush stdout+    clearLine+  where+    disableLineWrapping :: IO ()+    disableLineWrapping = writePlain "\ESC[?7l" +    enableLineWrapping :: IO ()+    enableLineWrapping = writePlain "\ESC[?7h"++    clearLine :: IO ()+    clearLine = writePlain "\r\ESC[K"+ -- | Append some output to the report. write :: String -> FormatM () write = mapM_ writeChunk . splitLines@@ -288,13 +297,16 @@ writeChunk :: String -> FormatM () writeChunk str = do   let-    plainOutput = IO.hPutStr stdout str+    plainOutput = writePlain str     colorOutput color = bracket_ (hSetSGR stdout [color]) (hSetSGR stdout [Reset]) plainOutput   mColor <- gets stateColor   liftIO $ case mColor of     Just (SetColor Foreground _ _) | all isSpace str -> plainOutput     Just color -> colorOutput color     Nothing -> plainOutput++writePlain :: String -> IO ()+writePlain = IO.hPutStr stdout  -- | Set output color to red, run given action, and finally restore the default -- color.
src/Test/Hspec/Core/Formatters/V2.hs view
@@ -188,7 +188,7 @@       Success {} -> pass       Failure {} -> pass       Pending _ reason -> withPendingColor $ do-        writeLine $ indentationFor ("" : nesting) ++ "# PENDING: " ++ fromMaybe "No reason given" reason+        indentBy (indentationFor ("" : nesting)) $ "# PENDING: " ++ fromMaybe "No reason given" reason } where     indentationFor nesting = replicate (length nesting * 2) ' ' @@ -198,8 +198,7 @@       write $ indentationFor nesting ++ requirement ++ " ["       withColor $ write symbol       writeLine $ "]" ++ if shouldPrintTimes then times else ""-      forM_ (lines info) $ \ s ->-        writeLine $ indentationFor ("" : nesting) ++ s+      indentBy (indentationFor ("" : nesting)) info       where         dt :: Int         dt = toMilliseconds duration@@ -233,7 +232,7 @@         writeResult nesting requirement duration info       Pending _ reason -> withPendingColor $ do         writeResult nesting requirement duration info-        writeLine $ indentationFor ("" : nesting) ++ "# PENDING: " ++ fromMaybe "No reason given" reason+        indentBy (indentationFor ("" : nesting)) $ "# PENDING: " ++ fromMaybe "No reason given" reason       Failure {} -> withFailColor $ do         n <- getFailCount         writeResult nesting (requirement ++ " FAILED [" ++ show n ++ "]") duration info@@ -245,8 +244,7 @@     writeResult nesting requirement (Seconds duration) info = do       shouldPrintTimes <- printTimes       writeLine $ indentationFor nesting ++ requirement ++ if shouldPrintTimes then times else ""-      forM_ (lines info) $ \ s ->-        writeLine $ indentationFor ("" : nesting) ++ s+      indentBy (indentationFor ("" : nesting)) info       where         dt :: Int         dt = floor (duration * 1000)@@ -362,9 +360,12 @@         writeLine ("  To rerun use: --match " ++ path_ <> " --seed " <> show seed)       where         indentation = "       "-        indent message = do-          forM_ (lines message) $ \line -> do-            writeLine (indentation ++ line)+        indent = indentBy indentation++indentBy :: String -> String -> FormatM ()+indentBy indentation message = do+  forM_ (lines message) $ \ line -> do+    writeLine (indentation ++ line)  data Chunk = Original String | Modified String | OmittedLines Int   deriving (Eq, Show)
src/Test/Hspec/Core/Runner.hs view
@@ -117,8 +117,9 @@ import           Test.Hspec.Core.Spec hiding (pruneTree, pruneForest) import           Test.Hspec.Core.Tree (formatDefaultDescription) import           Test.Hspec.Core.Config+import           Test.Hspec.Core.Config.Definition as Config (getSeed, getFormatter)+import           Test.Hspec.Core.Extension.Config.Type as Extension (applySpecTransformation) import           Test.Hspec.Core.Format (Format, FormatConfig(..))-import qualified Test.Hspec.Core.Formatters.V1 as V1 import qualified Test.Hspec.Core.Formatters.V2 as V2 import           Test.Hspec.Core.FailureReport import           Test.Hspec.Core.QuickCheck.Util@@ -197,7 +198,7 @@ -- for all properties.  This helps with --seed and --rerun. ensureSeed :: Config -> IO (Config, Integer) ensureSeed config = do-  seed <- case configSeed config <|> configQuickCheckSeed config of+  seed <- case Config.getSeed config of     Nothing -> toInteger <$> newSeed     Just seed -> return seed   return (config { configSeed = Just seed }, seed)@@ -391,7 +392,7 @@       , formatConfigExpertMode = configExpertMode config       } -      formatter = fromMaybe (V2.formatterToFormat V2.checks) (configFormat config <|> V1.formatterToFormat <$> configFormatter config)+      formatter = fromMaybe (V2.formatterToFormat V2.checks) (Config.getFormatter config)      format <- maybe id printSlowSpecItems (configPrintSlowItems config) <$> formatter formatConfig @@ -418,6 +419,7 @@   >>> addDefaultDescriptions   >>> failFocusedItems config   >>> failPendingItems config+  >>> Extension.applySpecTransformation config   >>> focusSpec config   >>> toEvalItemForest params   >>> applyDryRun config@@ -450,7 +452,7 @@ toEvalItemForest params = bimapForest id toEvalItem . filterForest itemIsFocused   where     toEvalItem :: Item () -> EvalItem-    toEvalItem (Item requirement loc isParallelizable _isFocused e) = EvalItem {+    toEvalItem (Item requirement loc isParallelizable _isFocused _annotations e) = EvalItem {       evalItemDescription = requirement     , evalItemLocation = loc     , evalItemConcurrency = if isParallelizable == Just True then Concurrent else Sequential
src/Test/Hspec/Core/Tree.hs view
@@ -24,6 +24,9 @@ , callSite , formatDefaultDescription , toModuleName++, setItemAnnotation+, getItemAnnotation ) where  import           Prelude ()@@ -34,6 +37,8 @@ import qualified Data.CallStack as CallStack  import           Test.Hspec.Core.Example+import           Test.Hspec.Core.Annotations (Annotations)+import qualified Test.Hspec.Core.Annotations as Annotations  -- | Internal tree data structure data Tree c a =@@ -114,10 +119,21 @@   -- | A flag that indicates whether this spec item is focused , itemIsFocused :: Bool +  -- | Arbitrary additional data that can be used by third-party extensions.+  --+  -- @since 2.12.0+, itemAnnotations :: Annotations+   -- | Example for behavior , itemExample :: Params -> (ActionWith a -> IO ()) -> ProgressCallback -> IO Result } +setItemAnnotation :: Typeable value => value -> Item a -> Item a+setItemAnnotation value config = config { itemAnnotations = Annotations.setValue value $ itemAnnotations config }++getItemAnnotation :: Typeable value => Item a -> Maybe value+getItemAnnotation = Annotations.getValue . itemAnnotations+ -- | The @specGroup@ function combines a list of specs into a larger spec. specGroup :: HasCallStack => String -> [SpecTree a] -> SpecTree a specGroup s = Node msg@@ -134,6 +150,7 @@   , itemLocation = location   , itemIsParallelizable = Nothing   , itemIsFocused = False+  , itemAnnotations = mempty   , itemExample = safeEvaluateExample e   } 
+ test/Test/Hspec/Core/AnnotationsSpec.hs view
@@ -0,0 +1,29 @@+module Test.Hspec.Core.AnnotationsSpec (spec) where++import           Prelude ()+import           Helper++import           Test.Hspec.Core.Annotations++newtype A = A Int+  deriving (Eq, Show)++newtype B = B Int+  deriving (Eq, Show)++spec :: Spec+spec = do+  describe "Annotations" $ do+    it "can store a value" $ do+      let annotations = setValue (A 23) mempty+      getValue annotations `shouldBe` Just (A 23)++    it "can store multiple values of different types" $ do+      let annotations = setValue (B 42) $ setValue (A 23) mempty+      getValue annotations `shouldBe` Just (A 23)+      getValue annotations `shouldBe` Just (B 42)++    context "when a value of the same type is added multiple times" $ do+      it "gives precedence to the value that was added last" $ do+        let annotations = setValue (A 42) $  setValue (A 23) mempty+        getValue annotations `shouldBe` Just (A 42)
test/Test/Hspec/Core/CompatSpec.hs view
@@ -5,7 +5,6 @@ import           Helper  import           System.Environment-import           Data.Typeable  data SomeType = SomeType   deriving Typeable
test/Test/Hspec/Core/RunnerSpec.hs view
@@ -1,3 +1,4 @@+{-# OPTIONS_GHC -fno-warn-deprecations #-} {-# LANGUAGE CPP #-} {-# LANGUAGE ScopedTypeVariables #-} {-# LANGUAGE TypeFamilies #-}@@ -27,6 +28,7 @@ import qualified Test.Hspec.Core.Hooks as H  import           Test.Hspec.Core.Formatters.Pretty.ParserSpec (Person(..))+import           Test.Hspec.Core.Extension ()  runPropFoo :: [String] -> IO String runPropFoo args = unlines . normalizeSummary . lines <$> do
version.yaml view
@@ -1,4 +1,4 @@-version: &version 2.11.9+version: &version 2.11.10 synopsis: A Testing Framework for Haskell author: Simon Hengel <sol@typeful.net> maintainer: Simon Hengel <sol@typeful.net>