prune-juice-0.7: test/Data/Prune/Section/ParserSpec.hs
module Data.Prune.Section.ParserSpec where
import Prelude
import Data.Either (isLeft)
import System.FilePath.TH (fileRelativeToAbsolute)
import Test.Hspec (Spec, describe, it, shouldBe, shouldSatisfy)
import Text.Megaparsec (parse)
import Data.Prune.ApplyStrategy.Smart (stripSections)
import qualified Data.Prune.Section.Types as T
import qualified Data.Prune.Types as T
-- the module being tested
import Data.Prune.Section.Parser
buildDependsNestedSection, importNestedSection, otherNestedSection :: T.NestedSection
buildDependsNestedSection = T.BuildDependsNestedSection 2 ["", " , base <5.0"]
importNestedSection = T.ImportNestedSection 2 [" foo, bar"]
otherNestedSection = T.OtherNestedSection 2 ["default-language: Haskell2010"]
librarySection, executableSection, commonSection, otherSection :: T.Section
librarySection = T.TargetSection T.CompilableTypeLibrary Nothing [importNestedSection, buildDependsNestedSection, otherNestedSection]
executableSection = T.TargetSection T.CompilableTypeExecutable (Just (T.CompilableName "prune-juice")) [buildDependsNestedSection, otherNestedSection]
commonSection = T.CommonSection (T.CommonName "foo") [buildDependsNestedSection, otherNestedSection]
otherSection = T.OtherSection ["name: prune-juice"]
buildDependsNestedExample, importNestedExample, otherNestedExample
, libraryExample, executableExample, commonExample, otherExample :: String
buildDependsNestedExample = unlines
[ " build-depends:"
, " , base <5.0"
]
importNestedExample = unlines
[ " import: foo, bar"
]
otherNestedExample = unlines
[ " default-language: Haskell2010"
]
libraryExample = unlines
[ "library"
, " import: foo, bar"
, " build-depends:"
, " , base <5.0"
, " default-language: Haskell2010"
]
executableExample = unlines
[ "executable prune-juice"
, " build-depends:"
, " , base <5.0"
, " default-language: Haskell2010"
]
commonExample = unlines
[ "common foo"
, " build-depends:"
, " , base <5.0"
, " default-language: Haskell2010"
]
otherExample = unlines
[ "name: prune-juice"
]
spec :: Spec
spec = describe "Data.Prune.Section.Parser" $ do
let cabalFile = $(fileRelativeToAbsolute "../../../../prune-juice.cabal")
commonFile = $(fileRelativeToAbsolute "../../../fixtures/test.cabal")
it "should parse a target name" $
parse targetName "" "prune-juice" `shouldBe` Right (T.CompilableName "prune-juice")
it "should parse the rest of the line" $
parse restOfLine "" "foo\n" `shouldBe` Right "foo"
it "should parse an indented line" $
parse (indentedLine 0) "" " foo\n" `shouldBe` Right " foo"
it "should not parse a non-indented line" $
parse (indentedLine 0) "" "foo\n" `shouldSatisfy` isLeft
it "should parse indented lines" $
parse (indentedLines 0) "" "foo\n bar\nbaz\n" `shouldBe` Right ["foo", " bar"]
it "should parse a build depends nested section" $
parse nestedSection "" buildDependsNestedExample `shouldBe` Right buildDependsNestedSection
it "should parse an import nested section" $
parse nestedSection "" importNestedExample `shouldBe` Right importNestedSection
it "should parse an other nested section" $
parse nestedSection "" otherNestedExample `shouldBe` Right otherNestedSection
it "should parse a library section" $
parse section "" libraryExample `shouldBe` Right librarySection
it "should parse an executable section" $
parse section "" executableExample `shouldBe` Right executableSection
it "should parse a common section" $
parse section "" commonExample `shouldBe` Right commonSection
it "should parse an other section" $
parse section "" otherExample `shouldBe` Right otherSection
it "should parse multiple sections" $
parse sections "" (libraryExample <> executableExample <> commonExample <> otherExample) `shouldBe` Right [librarySection, executableSection, commonSection, otherSection]
it "should parse and output the same thing" $ do
input <- readFile cabalFile
xs <- either fail pure $ parseCabalSections input
xs `shouldSatisfy` not . null
renderCabalSections xs `shouldBe` input
it "should parse and output the same thing after applying a trivial change" $ do
input <- readFile cabalFile
xs <- either fail (\ys -> pure (stripSections ys mempty Nothing)) $ parseCabalSections input
xs `shouldSatisfy` not . null
renderCabalSections xs `shouldBe` input
it "should parse a cabal file with common stanzas" $ do
input <- readCabalSections commonFile
input `shouldBe` Right
[ T.CommonSection (T.CommonName "global-options")
[ T.OtherNestedSection 2 ["default-language: Haskell2010", ""]
]
, T.CommonSection (T.CommonName "options")
[ T.ImportNestedSection 2 [" global-options"]
, T.BuildDependsNestedSection 2 [" base", ""]
]
, T.CommonSection (T.CommonName "global-exe-options")
[ T.OtherNestedSection 2 ["ghc-options: -threaded", ""]
]
, T.TargetSection T.CompilableTypeLibrary Nothing
[ T.ImportNestedSection 2 [" options", ""]
]
, T.TargetSection T.CompilableTypeExecutable (Just (T.CompilableName "exe"))
[ T.ImportNestedSection 2 [" options, global-exe-options"]
]
]