{-# LANGUAGE OverloadedStrings #-} {-# LANGUAGE OverloadedLists #-} module Hpack.RenderSpec (spec) where import Helper import Control.Monad.Reader (runReader) import Hpack.Syntax.DependencyVersion import Hpack.ConfigSpec hiding (spec) import Hpack.Config hiding (package) import Hpack.Render.Dsl hiding (RenderSettings, defaultRenderSettings, render) import qualified Hpack.Render.Dsl as Dsl import Hpack.Render library :: Library library = Library Nothing Nothing [] [] [] [] [] executable :: Section Executable executable = (section $ Executable (Just "Main.hs") [] []) { sectionLanguage = Just $ Language "Haskell2010" } renderEmptySection :: Empty -> [Element] renderEmptySection Empty = [] cabalVersion :: CabalVersion cabalVersion = makeCabalVersion [1,12] render :: Element -> [FilePath] render = Dsl.render Dsl.defaultRenderSettings 0 spec :: Spec spec = do describe "renderPackageWith" $ do let renderPackage_ = renderPackageWith defaultRenderSettings 0 [] [] it "renders a package" $ do renderPackage_ package `shouldBe` unlines [ "name: foo" , "version: 0.0.0" , "build-type: Simple" ] it "aligns fields" $ do renderPackageWith defaultRenderSettings 16 [] [] package `shouldBe` unlines [ "name: foo" , "version: 0.0.0" , "build-type: Simple" ] it "includes description" $ do renderPackage_ package {packageDescription = Just "foo\n\nbar\n"} `shouldBe` unlines [ "name: foo" , "version: 0.0.0" , "description: foo" , " ." , " bar" , "build-type: Simple" ] it "aligns description" $ do renderPackageWith defaultRenderSettings 16 [] [] package {packageDescription = Just "foo\n\nbar\n"} `shouldBe` unlines [ "name: foo" , "version: 0.0.0" , "description: foo" , " ." , " bar" , "build-type: Simple" ] it "includes stability" $ do renderPackage_ package {packageStability = Just "experimental"} `shouldBe` unlines [ "name: foo" , "version: 0.0.0" , "stability: experimental" , "build-type: Simple" ] it "includes license-file" $ do renderPackage_ package {packageLicenseFile = ["FOO"]} `shouldBe` unlines [ "name: foo" , "version: 0.0.0" , "license-file: FOO" , "build-type: Simple" ] it "aligns license-files" $ do renderPackageWith defaultRenderSettings 16 [] [] package {packageLicenseFile = ["FOO", "BAR"]} `shouldBe` unlines [ "name: foo" , "version: 0.0.0" , "license-files: FOO," , " BAR" , "build-type: Simple" ] it "includes copyright holder" $ do renderPackage_ package {packageCopyright = ["(c) 2015 Simon Hengel"]} `shouldBe` unlines [ "name: foo" , "version: 0.0.0" , "copyright: (c) 2015 Simon Hengel" , "build-type: Simple" ] it "aligns copyright holders" $ do renderPackageWith defaultRenderSettings 16 [] [] package {packageCopyright = ["(c) 2015 Foo", "(c) 2015 Bar"]} `shouldBe` unlines [ "name: foo" , "version: 0.0.0" , "copyright: (c) 2015 Foo," , " (c) 2015 Bar" , "build-type: Simple" ] it "includes extra-source-files" $ do renderPackage_ package {packageExtraSourceFiles = ["foo", "bar"]} `shouldBe` unlines [ "name: foo" , "version: 0.0.0" , "build-type: Simple" , "extra-source-files:" , " foo" , " bar" ] it "includes buildable" $ do renderPackage_ package {packageLibrary = Just (section library){sectionBuildable = Just False}} `shouldBe` unlines [ "name: foo" , "version: 0.0.0" , "build-type: Simple" , "" , "library" , " buildable: False" ] context "when given list of existing fields" $ do it "retains field order" $ do renderPackageWith defaultRenderSettings 16 ["version", "build-type", "name"] [] package `shouldBe` unlines [ "version: 0.0.0" , "build-type: Simple" , "name: foo" ] it "uses default field order for new fields" $ do renderPackageWith defaultRenderSettings 16 [] [] package `shouldBe` unlines [ "name: foo" , "version: 0.0.0" , "build-type: Simple" ] it "retains section field order" $ do renderPackageWith defaultRenderSettings 0 [] [("executable foo", ["default-language", "main-is", "ghc-options"])] package {packageExecutables = [("foo", executable {sectionGhcOptions = ["-Wall", "-Werror"]})]} `shouldBe` unlines [ "name: foo" , "version: 0.0.0" , "build-type: Simple" , "" , "executable foo" , " default-language: Haskell2010" , " main-is: Main.hs" , " ghc-options: -Wall -Werror" ] context "when rendering executable section" $ do it "includes dependencies" $ do let dependencies = Dependencies [ ("foo", defaultInfo { dependencyInfoVersion = versionRange "== 0.1.0" }) , ("bar", defaultInfo) ] renderPackage_ package {packageExecutables = [("foo", executable {sectionDependencies = dependencies})]} `shouldBe` unlines [ "name: foo" , "version: 0.0.0" , "build-type: Simple" , "" , "executable foo" , " main-is: Main.hs" , " build-depends:" , " bar" , " , foo == 0.1.0" , " default-language: Haskell2010" ] it "includes GHC options" $ do renderPackage_ package {packageExecutables = [("foo", executable {sectionGhcOptions = ["-Wall", "-Werror"]})]} `shouldBe` unlines [ "name: foo" , "version: 0.0.0" , "build-type: Simple" , "" , "executable foo" , " main-is: Main.hs" , " ghc-options: -Wall -Werror" , " default-language: Haskell2010" ] it "includes frameworks" $ do renderPackage_ package {packageExecutables = [("foo", executable {sectionFrameworks = ["foo", "bar"]})]} `shouldBe` unlines [ "name: foo" , "version: 0.0.0" , "build-type: Simple" , "" , "executable foo" , " main-is: Main.hs" , " frameworks:" , " foo" , " bar" , " default-language: Haskell2010" ] it "includes extra-framework-dirs" $ do renderPackage_ package {packageExecutables = [("foo", executable {sectionExtraFrameworksDirs = ["foo", "bar"]})]} `shouldBe` unlines [ "name: foo" , "version: 0.0.0" , "build-type: Simple" , "" , "executable foo" , " main-is: Main.hs" , " extra-frameworks-dirs:" , " foo" , " bar" , " default-language: Haskell2010" ] it "includes GHC profiling options" $ do renderPackage_ package {packageExecutables = [("foo", executable {sectionGhcProfOptions = ["-fprof-auto", "-rtsopts"]})]} `shouldBe` unlines [ "name: foo" , "version: 0.0.0" , "build-type: Simple" , "" , "executable foo" , " main-is: Main.hs" , " ghc-prof-options: -fprof-auto -rtsopts" , " default-language: Haskell2010" ] describe "renderConditional" $ do let run = flip runReader (RenderEnv cabalVersion "foo") it "renders conditionals" $ do let conditional = Conditional "os(windows)" (section Empty) {sectionDependencies = deps ["Win32"]} Nothing render (run $ renderConditional renderEmptySection conditional) `shouldBe` [ "if os(windows)" , " build-depends:" , " Win32" ] it "renders conditionals with else-branch" $ do let conditional = Conditional "os(windows)" (section Empty) {sectionDependencies = deps ["Win32"]} (Just $ (section Empty) {sectionDependencies = deps ["unix"]}) render (run $ renderConditional renderEmptySection conditional) `shouldBe` [ "if os(windows)" , " build-depends:" , " Win32" , "else" , " build-depends:" , " unix" ] it "renders nested conditionals" $ do let conditional = Conditional "arch(i386)" (section Empty) {sectionGhcOptions = ["-threaded"], sectionConditionals = [innerConditional]} Nothing innerConditional = Conditional "os(windows)" (section Empty) {sectionDependencies = deps ["Win32"]} Nothing render (run $ renderConditional renderEmptySection conditional) `shouldBe` [ "if arch(i386)" , " ghc-options: -threaded" , " if os(windows)" , " build-depends:" , " Win32" ] it "conditionalises both build-depends and mixins" $ do let conditional = Conditional "os(windows)" (section Empty) {sectionDependencies = [("Win32", depInfo)]} Nothing depInfo = defaultInfo { dependencyInfoMixins = ["hiding (Blah)"] } render (run $ renderConditional renderEmptySection conditional) `shouldBe` [ "if os(windows)" , " build-depends:" , " Win32" , " mixins:" , " Win32 hiding (Blah)" ] describe "renderFlag" $ do it "renders flags" $ do let flag = (Flag "foo" (Just "some flag") True False) render (renderFlag flag) `shouldBe` [ "flag foo" , " description: some flag" , " manual: True" , " default: False" ] describe "renderSourceRepository" $ do it "renders source-repository without subdir correctly" $ do let repository = SourceRepository "https://github.com/hspec/hspec" Nothing (render $ renderSourceRepository repository) `shouldBe` [ "source-repository head" , " type: git" , " location: https://github.com/hspec/hspec" ] it "renders source-repository with subdir" $ do let repository = SourceRepository "https://github.com/hspec/hspec" (Just "hspec-core") (render $ renderSourceRepository repository) `shouldBe` [ "source-repository head" , " type: git" , " location: https://github.com/hspec/hspec" , " subdir: hspec-core" ] describe "renderDirectories" $ do it "replaces . with ./. (for compatibility with cabal syntax)" $ do (render $ renderDirectories "name" ["."]) `shouldBe` [ "name:" , " ./" ] describe "renderDependencies" $ do it "renders build-depends" $ do let deps_ = [ ("foo", DependencyInfo [] anyVersion) ] renderDependencies "build-depends" deps_ `shouldBe` [ Field "build-depends" $ CommaSeparatedList [ "foo" ] , Field "mixins" $ CommaSeparatedList [] ] it "renders build-depends with versions" $ do let deps_ = [ ("foo", DependencyInfo [] (versionRange ">= 2 && < 3")) ] renderDependencies "build-depends" deps_ `shouldBe` [ Field "build-depends" $ CommaSeparatedList [ "foo >= 2 && < 3" ] , Field "mixins" $ CommaSeparatedList [] ] it "renders mixins and build-depends for multiple modules" $ do let deps_ = [ ("foo", DependencyInfo ["(Foo as Foo1)"] anyVersion) , ("bar", DependencyInfo ["hiding (Spam)", "(Spam as Spam1) requires (Mod as Sig)"] anyVersion) ] renderDependencies "build-depends" deps_ `shouldBe` [ Field "build-depends" $ CommaSeparatedList [ "bar" , "foo" ] , Field "mixins" $ CommaSeparatedList [ "bar hiding (Spam)" , "bar (Spam as Spam1) requires (Mod as Sig)" , "foo (Foo as Foo1)" ] ]