hspec-golden 0.2.1.0 → 0.2.2.0
raw patch · 6 files changed
+155/−39 lines, 6 filesdep +ansi-terminaldep ~directorydep ~hspec-coredep ~optparse-applicativenew-uploader
Dependencies added: ansi-terminal
Dependency ranges changed: directory, hspec-core, optparse-applicative
Files
- ChangeLog.md +8/−0
- README.md +57/−5
- app/Main.hs +31/−16
- hspec-golden.cabal +9/−6
- src/Test/Hspec/Golden.hs +30/−7
- test/Test/Hspec/GoldenSpec.hs +20/−5
ChangeLog.md view
@@ -1,4 +1,12 @@ # Changelog for hspec-golden+## 0.2.2.0+#### Add+* `golden` helper to write tests++## 0.2.1.1+#### Add+* Add colors to hspec-golden CLI tool.+ ## 0.2.1.0 #### Add * Instance for IO Golden type. Kudos to @dbalseiro
README.md view
@@ -1,5 +1,5 @@ # hspec-golden-[](https://travis-ci.org/stackbuilders/hspec-golden)+[](https://github.com/stackbuilders/hspec-golden/actions/workflows/build-and-test.yml) [](http://hackage.haskell.org/package/hspec-golden) ## Description Golden tests store the expected output in a separated file. Each time a golden test@@ -25,6 +25,15 @@ always have a unique name for your file. Example: `show 'myFunc == MyModule.myFunc`. Although, you can name it as you like. +You can write golden tests using `golden` helper:++```haskell+describe "myFunc" $+ golden "generates the right output with the right params" $+ let output = show $ myFunc params+ in return output+```+ In case your output isn't a `String` you can define your own `Golden` test using the `Golden` data type: @@ -48,10 +57,12 @@ failFirstTime = False } -describe "myTextFunc" $- it "generates the right output with the right params" $- let textOutput = myTextFunc params- in myGoldenTest (show 'myTextFunc) textOutput+spec :: Spec+spec =+ describe "myTextFunc" $+ it "generates the right output with the right params" $+ let textOutput = myTextFunc params+ in myGoldenTest (show 'myTextFunc) textOutput ``` ## Install CLI@@ -96,6 +107,47 @@ ``` $ hgold -u .myGoldenTest ```++## Contributors ✨++Thanks goes to these wonderful people ([emoji key](https://allcontributors.org/docs/en/emoji-key)):++<!-- ALL-CONTRIBUTORS-LIST:START - Do not remove or modify this section -->+<!-- prettier-ignore-start -->+<!-- markdownlint-disable -->+<table>+ <tbody>+ <tr>+ <td align="center" valign="top" width="14.28%"><a href="https://cristhianmotoche.github.io/"><img src="https://avatars.githubusercontent.com/u/8370088?v=4?s=100" width="100px;" alt="Cristhian Motoche"/><br /><sub><b>Cristhian Motoche</b></sub></a><br /><a href="https://github.com/stackbuilders/hspec-golden/commits?author=CristhianMotoche" title="Code">💻</a></td>+ <td align="center" valign="top" width="14.28%"><a href="https://www.christian-wuensche.com/"><img src="https://avatars.githubusercontent.com/u/3807237?v=4?s=100" width="100px;" alt="Christian Wünsche (ehem Heyn)"/><br /><sub><b>Christian Wünsche (ehem Heyn)</b></sub></a><br /><a href="https://github.com/stackbuilders/hspec-golden/commits?author=christianwish" title="Code">💻</a></td>+ <td align="center" valign="top" width="14.28%"><a href="https://github.com/bitc"><img src="https://avatars.githubusercontent.com/u/996487?v=4?s=100" width="100px;" alt="Bit Connor"/><br /><sub><b>Bit Connor</b></sub></a><br /><a href="https://github.com/stackbuilders/hspec-golden/commits?author=bitc" title="Code">💻</a></td>+ <td align="center" valign="top" width="14.28%"><a href="https://dbalseiro.github.io/"><img src="https://avatars.githubusercontent.com/u/2053849?v=4?s=100" width="100px;" alt="Diego Balseiro"/><br /><sub><b>Diego Balseiro</b></sub></a><br /><a href="https://github.com/stackbuilders/hspec-golden/commits?author=dbalseiro" title="Code">💻</a></td>+ <td align="center" valign="top" width="14.28%"><a href="https://github.com/Jagl257"><img src="https://avatars.githubusercontent.com/u/27145248?v=4?s=100" width="100px;" alt="Jorge Guerra Landázuri"/><br /><sub><b>Jorge Guerra Landázuri</b></sub></a><br /><a href="https://github.com/stackbuilders/hspec-golden/commits?author=Jagl257" title="Code">💻</a></td>+ <td align="center" valign="top" width="14.28%"><a href="https://github.com/ChickenProp"><img src="https://avatars.githubusercontent.com/u/57271?v=4?s=100" width="100px;" alt="Phil Hazelden"/><br /><sub><b>Phil Hazelden</b></sub></a><br /><a href="https://github.com/stackbuilders/hspec-golden/commits?author=ChickenProp" title="Code">💻</a></td>+ <td align="center" valign="top" width="14.28%"><a href="http://alexvieth.wordpress.com/"><img src="https://avatars.githubusercontent.com/u/1420272?v=4?s=100" width="100px;" alt="Alexander Vieth"/><br /><sub><b>Alexander Vieth</b></sub></a><br /><a href="https://github.com/stackbuilders/hspec-golden/commits?author=avieth" title="Code">💻</a></td>+ </tr>+ <tr>+ <td align="center" valign="top" width="14.28%"><a href="https://github.com/guibou"><img src="https://avatars.githubusercontent.com/u/9705357?v=4?s=100" width="100px;" alt="Guillaume Bouchard"/><br /><sub><b>Guillaume Bouchard</b></sub></a><br /><a href="https://github.com/stackbuilders/hspec-golden/commits?author=guibou" title="Code">💻</a></td>+ <td align="center" valign="top" width="14.28%"><a href="https://github.com/fefi95"><img src="https://avatars.githubusercontent.com/u/12057338?v=4?s=100" width="100px;" alt="Stefani Castellanos"/><br /><sub><b>Stefani Castellanos</b></sub></a><br /><a href="https://github.com/stackbuilders/hspec-golden/commits?author=fefi95" title="Code">💻</a></td>+ </tr>+ </tbody>+ <tfoot>+ <tr>+ <td align="center" size="13px" colspan="7">+ <img src="https://raw.githubusercontent.com/all-contributors/all-contributors-cli/1b8533af435da9854653492b1327a23a4dbd0a10/assets/logo-small.svg">+ <a href="https://all-contributors.js.org/docs/en/bot/usage">Add your contributions</a>+ </img>+ </td>+ </tr>+ </tfoot>+</table>++<!-- markdownlint-restore -->+<!-- prettier-ignore-end -->++<!-- ALL-CONTRIBUTORS-LIST:END -->++This project follows the [all-contributors](https://github.com/all-contributors/all-contributors) specification. Contributions of any kind welcome! ## License
app/Main.hs view
@@ -1,10 +1,12 @@ module Main where +import System.Console.ANSI import Control.Monad (forM_, when) import Data.Version (showVersion) import Paths_hspec_golden (version) import Options.Applicative import Data.Monoid ((<>))+import GHC.IO (catch) import System.Directory (doesDirectoryExist, doesFileExist, listDirectory, renameFile) import qualified Test.Hspec.Golden as G@@ -14,14 +16,10 @@ -- CLI Params -data Params =- Params- { updateDir :: FilePath - -- , shouldUpdate :: Bool- } deriving Show- +newtype Params = Params { updateDir :: FilePath } deriving Show+ params :: Parser Params-params = Params +params = Params <$> strOption (long "update" <> short 'u'@@ -31,18 +29,28 @@ <> help "The testing directory where you're dumping your results.") versionOpt :: Parser (a->a)-versionOpt = infoOption (showVersion version) +versionOpt = infoOption (showVersion version) (long "version"- <> short 'v' + <> short 'v' <> help "Show version")- ---Update Files+withColor :: Color -> IO () -> IO ()+withColor color action = do+ setSGR [SetColor Foreground Dull color]+ action+ setSGR [Reset]++success, warning, failure :: IO () -> IO ()+success = withColor Green+warning = withColor Yellow+failure = withColor Red++-- Update golden files in the given directory updateGolden :: FilePath -> IO () updateGolden dir = do- putStrLn "Replacing golden with actual..."+ putStrLn "Replacing golden with actual:" go dir- putStrLn "Finish..."+ success $ putStrLn "Finished!" where go dir = do entries <- listDirectory dir@@ -59,9 +67,16 @@ goldenFilePath = testPath ++ "/golden" in do actualFileExist <- doesFileExist actualFilePath- when actualFileExist (do- putStrLn $ " Replacing file: " ++ goldenFilePath ++ " with: " ++ actualFilePath- renameFile actualFilePath goldenFilePath)+ when actualFileExist $ do+ putStr " Replacing file: "+ warning $ putStr goldenFilePath+ putStr " with: "+ success $ putStrLn actualFilePath+ renameFile actualFilePath goldenFilePath `catch` handleErr+ where+ handleErr :: IOError -> IO ()+ handleErr e =+ failure $ putStr $ "Warning: Could not replace file due to error: " ++ show e -- Main
hspec-golden.cabal view
@@ -1,11 +1,11 @@ cabal-version: 1.12 --- This file has been generated from package.yaml by hpack version 0.35.2.+-- This file has been generated from package.yaml by hpack version 0.36.0. -- -- see: https://github.com/sol/hpack name: hspec-golden-version: 0.2.1.0+version: 0.2.2.0 synopsis: Golden tests for hspec description: . Golden tests store the expected output in a separated file. Each time a golden test@@ -31,6 +31,8 @@ license: MIT license-file: LICENSE build-type: Simple+tested-with:+ GHC==8.8, GHC==8.10, GHC==9.0 extra-source-files: README.md ChangeLog.md@@ -48,9 +50,9 @@ src build-depends: base >=4.6 && <5- , directory+ , directory >=1.3.6 && <1.4 , filepath >=1.0 && <2.0- , hspec-core >=2.5 && <3.0+ , hspec-core >=2.10 && <3.0 default-language: Haskell2010 executable hgold@@ -61,10 +63,11 @@ app ghc-options: -threaded -rtsopts -with-rtsopts=-N build-depends:- base >=4.6 && <5+ ansi-terminal >=1.0 && <2.0+ , base >=4.6 && <5 , directory >=1.2.5.0 , hspec-golden- , optparse-applicative+ , optparse-applicative >=0.18.1 && <0.19 default-language: Haskell2010 test-suite hspec-golden-test
src/Test/Hspec/Golden.hs view
@@ -21,14 +21,19 @@ module Test.Hspec.Golden ( Golden(..) , defaultGolden+ , golden ) where +import Control.Monad.IO.Class (MonadIO (liftIO)) import Data.IORef-import System.Directory (createDirectoryIfMissing, doesFileExist)-import System.FilePath (takeDirectory, (</>))-import Test.Hspec.Core.Spec (Example (..), FailureReason (..),- Result (..), ResultStatus (..))+import Data.List (intercalate)+import System.Directory (createDirectoryIfMissing,+ doesFileExist)+import System.FilePath (takeDirectory, (</>))+import Test.Hspec.Core.Spec (Example (..), FailureReason (..),+ Result (..), ResultStatus (..), Spec,+ SpecWith, getSpecDescriptionPath, it) -- | Golden tests parameters@@ -99,7 +104,7 @@ fromGoldenResult FirstExecutionFail = Result "First time execution. Golden file created." (Failure Nothing (Reason "Golden file did not exist and was created. Failed because failFirstTime is set to True"))-fromGoldenResult (MissmatchOutput expected actual) =+fromGoldenResult (MismatchOutput expected actual) = Result "Files golden and actual not match" (Failure Nothing (ExpectedButGot Nothing expected actual)) @@ -127,7 +132,7 @@ -- | Possible results from a golden test execution data GoldenResult =- MissmatchOutput String String+ MismatchOutput String String | SameOutput | FirstExecutionSucceed | FirstExecutionFail@@ -161,4 +166,22 @@ if contentGolden == output then return SameOutput- else return $ MissmatchOutput (encodePretty contentGolden) (encodePretty output)+ else return $ MismatchOutput (encodePretty contentGolden) (encodePretty output)+++-- | A helper function to create a golden test.+--+-- @+-- describe "function" $+-- golden "some name" $+-- return content+-- @++golden+ :: String -- ^ Test description+ -> IO String -- ^ Content (@return content@ for pure functions)+ -> Spec+golden description runAction = do+ path <- (++ words description) <$> getSpecDescriptionPath+ it description $+ defaultGolden (intercalate "-" path) <$> runAction
test/Test/Hspec/GoldenSpec.hs view
@@ -1,6 +1,6 @@ module Test.Hspec.GoldenSpec (spec) where -import Control.Monad (void)+import Control.Monad (void, when) import Test.Hspec import qualified Test.Hspec.Core.Runner as H@@ -24,12 +24,20 @@ fixtureTest :: String -> H.Spec fixtureTest content =- H.describe "id" $- H.it "should work" $+ describe "id" $+ it "should work" $ defaultGolden fixtureTestName content +fixtureGoldenTest :: String -> H.Spec+fixtureGoldenTest content =+ describe "id" $+ golden "golden sample file" $+ return content+ removeFixtures :: IO ()-removeFixtures = removeDirectoryRecursive goldenTestDir+removeFixtures = do+ exists <- doesDirectoryExist ".golden"+ when exists $ removeDirectoryRecursive ".golden" runSpec :: H.Spec -> IO [String] runSpec = captureLines . H.hspecResult@@ -59,7 +67,7 @@ actualFileContent <- readFile actualFilePath actualFileContent `shouldBe` fixtureUpdatedContent - it "shouldn't overide the `golden` file" $ do+ it "shouldn't override the `golden` file" $ do void $ runSpec $ fixtureTest fixtureContent void $ runSpec $ fixtureTest fixtureUpdatedContent goldenFileContent <- readFile goldenFilePath@@ -78,3 +86,10 @@ void $ runSpec $ fixtureTest fixtureContent goldenFileContent <- readFile goldenFilePath goldenFileContent `shouldBe` fixtureContent++ describe "golden" $+ context "given some input" $+ it "creates file with separated dashes" $ do+ void $ runSpec $ fixtureGoldenTest fixtureContent+ goldenFile <- readFile ".golden/id-golden-sample-file/golden"+ goldenFile `shouldBe` fixtureContent