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 +22/−3
- src/Test/Hspec/Core/Annotations.hs +29/−0
- src/Test/Hspec/Core/Compat.hs +2/−1
- src/Test/Hspec/Core/Config.hs +1/−1
- src/Test/Hspec/Core/Config/Definition.hs +43/−7
- src/Test/Hspec/Core/Config/Options.hs +12/−15
- src/Test/Hspec/Core/Extension.hs +112/−0
- src/Test/Hspec/Core/Extension/Config.hs +19/−0
- src/Test/Hspec/Core/Extension/Config/Type.hs +43/−0
- src/Test/Hspec/Core/Extension/Item.hs +46/−0
- src/Test/Hspec/Core/Extension/Option.hs +27/−0
- src/Test/Hspec/Core/Extension/Spec.hs +10/−0
- src/Test/Hspec/Core/Extension/Tree.hs +19/−0
- src/Test/Hspec/Core/Formatters/Internal.hs +18/−6
- src/Test/Hspec/Core/Formatters/V2.hs +10/−9
- src/Test/Hspec/Core/Runner.hs +6/−4
- src/Test/Hspec/Core/Tree.hs +17/−0
- test/Test/Hspec/Core/AnnotationsSpec.hs +29/−0
- test/Test/Hspec/Core/CompatSpec.hs +0/−1
- test/Test/Hspec/Core/RunnerSpec.hs +2/−0
- version.yaml +1/−1
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>