module RunSpec (main, spec) where
import Helper
import System.IO
import System.Directory
import System.FilePath
import Data.List (sort)
import Test.Hspec.Discover.Run hiding (Spec)
import qualified Test.Hspec.Discover.Run
main :: IO ()
main = hspec spec
withTempFile :: (FilePath -> IO a) -> IO a
withTempFile action = do
dir <- getTemporaryDirectory
(file, h) <- openTempFile dir ""
hClose h
action file <* removeFile file
spec :: Spec
spec = do
describe "run" $ do
it "generates test driver" $ withTempFile $ \f -> do
run ["test-data/nested-spec/Spec.hs", "", f]
readFile f `shouldReturn` unlines [
"{-# LINE 1 \"test-data/nested-spec/Spec.hs\" #-}"
, "{-# OPTIONS_GHC -fno-warn-warnings-deprecations #-}"
, "module Main where"
, "import qualified Foo.Bar.BazSpec"
, "import qualified Foo.BarSpec"
, "import qualified FooSpec"
, "import Test.Hspec.Discover"
, "main :: IO ()"
, "main = hspec spec"
, "spec :: Spec"
, "spec = " ++ unwords [
"postProcessSpec \"test-data/nested-spec/Foo/Bar/BazSpec.hs\" (describe \"Foo.Bar.Baz\" Foo.Bar.BazSpec.spec)"
, ">> postProcessSpec \"test-data/nested-spec/Foo/BarSpec.hs\" (describe \"Foo.Bar\" Foo.BarSpec.spec)"
, ">> postProcessSpec \"test-data/nested-spec/FooSpec.hs\" (describe \"Foo\" FooSpec.spec)"
]
]
it "generates test driver for an empty directory" $ withTempFile $ \f -> do
run ["test-data/empty-dir/Spec.hs", "", f]
readFile f `shouldReturn` unlines [
"{-# LINE 1 \"test-data/empty-dir/Spec.hs\" #-}"
, "{-# OPTIONS_GHC -fno-warn-warnings-deprecations #-}"
, "module Main where"
, "import Test.Hspec.Discover"
, "main :: IO ()"
, "main = hspec spec"
, "spec :: Spec"
, "spec = return ()"
]
describe "pathToModule" $ do
it "derives module name from a given path" $ do
pathToModule "test/Spec.hs" `shouldBe` "Spec"
describe "getFilesRecursive" $ do
it "recursively returns all file entries of a given directory" $ do
getFilesRecursive "test-data" `shouldReturn` sort [
"empty-dir/Foo/Bar/Baz/.placeholder"
, "nested-spec/Foo/Bar/BazSpec.hs"
, "nested-spec/Foo/BarSpec.hs"
, "nested-spec/FooSpec.hs"
]
describe "fileToSpec" $ do
it "converts path to spec name" $ do
fileToSpec "" "FooSpec.hs" `shouldBe` Just (spec_ "FooSpec.hs" "Foo")
it "rejects spec with empty name" $ do
fileToSpec "" "Spec.hs" `shouldBe` Nothing
it "works for lhs files" $ do
fileToSpec "" "FooSpec.lhs" `shouldBe` Just (spec_ "FooSpec.lhs" "Foo")
it "returns Nothing for invalid spec name" $ do
fileToSpec "" "foo" `shouldBe` Nothing
context "when spec does not have a valid module name" $ do
it "returns Nothing" $ do
fileToSpec "" "flycheck_Spec.hs" `shouldBe` Nothing
context "when any component of a hierarchical module name is not valid"$ do
it "returns Nothing" $ do
fileToSpec "" ("Valid" </> "invalid" </>"MiddleNamesSpec.hs") `shouldBe` Nothing
context "when path has directory component" $ do
it "converts path to spec name" $ do
let file = "Foo" </> "Bar" </> "BazSpec.hs"
fileToSpec "" file `shouldBe` Just (spec_ file "Foo.Bar.Baz")
it "rejects spec with empty name" $ do
fileToSpec "" ("Foo" </> "Bar" </> "Spec.hs") `shouldBe` Nothing
describe "findSpecs" $ do
it "finds specs" $ do
let dir = "test-data/nested-spec"
findSpecs (dir </> "Spec.hs") `shouldReturn` [spec_ (dir </> "Foo/Bar/BazSpec.hs") "Foo.Bar.Baz", spec_ (dir </> "Foo/BarSpec.hs") "Foo.Bar", spec_ (dir </> "FooSpec.hs") "Foo"]
describe "driverWithFormatter" $ do
it "generates a test driver that uses a custom formatter" $ do
driverWithFormatter "Some.Module.formatter" "" `shouldBe` unlines [
"import qualified Some.Module"
, "main :: IO ()"
, "main = hspecWithFormatter Some.Module.formatter spec"
]
describe "moduleNameFromId" $ do
it "returns the module name of a fully qualified identifier" $ do
moduleNameFromId "Some.Module.someId" `shouldBe` "Some.Module"
describe "importList" $ do
it "generates imports for a list of specs" $ do
importList [spec_ "FooSpec.hs" "Foo", spec_ "BarSpec.hs" "Bar"] "" `shouldBe` unlines [
"import qualified FooSpec"
, "import qualified BarSpec"
]
where
spec_ = Test.Hspec.Discover.Run.Spec