checkmate-0.4.0: test/Checkmate/DiscoverSpec.hs
{-# LANGUAGE OverloadedLists #-}
{-# LANGUAGE OverloadedStrings #-}
{-# LANGUAGE TemplateHaskell #-}
module Checkmate.DiscoverSpec (spec) where
import Control.Monad
import Data.ByteString
import Data.FileEmbed
import Data.Text
import System.Directory
import System.FilePath
import System.IO.Temp
import Test.Hspec
import Text.Diff.Parse (parseDiff)
import Text.Diff.Parse.Types
import Checkmate.Check
import Checkmate.Discover
fixtures :: [(FilePath, ByteString)]
fixtures = $(embedDir "test/fixtures/")
diffTextFixture :: Text
diffTextFixture = $(embedStringFile "test/fixtures/patch.diff")
diffFixture :: FileDeltas
Right diffFixture = parseDiff diffTextFixture
rootChecklistFixture :: FilePath -> Checklist
rootChecklistFixture dirPath =
[ Check { checkScope = dir
, checkOrderIndex = 1
, checkText = "Sample check A"
}
, Check { checkScope = dir
, checkOrderIndex = 2
, checkText = "sample check B"
}
, Check { checkScope = dir
, checkOrderIndex = 3
, checkText = "Sample check C"
}
]
where
dir :: Scope
dir = Directory dirPath
subdirChecklistFixture :: FilePath -> Checklist
subdirChecklistFixture dirPath =
[ Check { checkScope = dir
, checkOrderIndex = 1
, checkText = "sub-dir check A"
}
, Check { checkScope = dir
, checkOrderIndex = 2
, checkText = "sub-dir check B"
}
] `union` rootChecklistFixture dirPath
where
dir :: Scope
dir = Directory $ dirPath </> "subdir"
pyChecklistFixture :: FilePath -> Checklist
pyChecklistFixture d =
[ Check { checkScope = FileBlock { scopePath = pyPath
, scopeRange = Range 2 24
}
, checkOrderIndex = 1
, checkText = "module-level check"
}
, Check { checkScope = FileBlock { scopePath = pyPath
, scopeRange = Range 11 5
}
, checkOrderIndex = 3
, checkText = "function-level check 2"
}
, Check { checkScope = FileBlock { scopePath = pyPath
, scopeRange = Range 14 2
}
, checkOrderIndex = 4
, checkText = "nested function-level check"
}
]
where
pyPath :: FilePath
pyPath = d </> "sample.py"
jsChecklistFixture :: FilePath -> Checklist
jsChecklistFixture d =
[ Check { checkScope = FileBlock { scopePath = jsPath
, scopeRange = Range 2 20
}
, checkOrderIndex = 1
, checkText = "global check"
}
, Check { checkScope = FileBlock { scopePath = jsPath
, scopeRange = Range 10 11
}
, checkOrderIndex = 3
, checkText = "function-level check 2"
}
, Check { checkScope = FileBlock { scopePath = jsPath
, scopeRange = Range 13 5
}
, checkOrderIndex = 4
, checkText = "closure check.\nIt can be multiline."
}
]
where
jsPath :: FilePath
jsPath = d </> "subdir" </> "inner_sample.js"
withTempDir :: (FilePath -> IO a) -> IO a
withTempDir = withSystemTempDirectory "checkmate-test"
withFixtureDir :: (FilePath -> IO a) -> IO a
withFixtureDir action =
withTempDir $ \ dirPath -> do
forM_ fixtures $ \ (filePath, contents) -> do
let path = dirPath </> filePath
parent = takeDirectory path
-- `parent` can differ from `dirPath` when `filePath` has '/'
createDirectoryIfMissing True parent
Data.ByteString.writeFile path contents
action dirPath
spec :: Spec
spec = do
describe "discover" $ do
it "scans all relative checks" $
withFixtureDir $ \ dirPath -> do
checklist <- discover dirPath diffFixture
let expected = subdirChecklistFixture dirPath
`union` pyChecklistFixture dirPath
`union` jsChecklistFixture dirPath
checklist `shouldBe` expected
it "ignores files/directories that do not exist" $
withTempDir $ \ dirPath -> do
checklist <- discover dirPath diffFixture
checklist `shouldBe` []
describe "discoverDirectory" $ do
it "lists files in the given path" $
withFixtureDir $ \ dirPath -> do
subdirChecks <- discoverDirectory dirPath "subdir"
subdirChecks `shouldBe` subdirChecklistFixture dirPath
rootChecks <- discoverDirectory dirPath "."
rootChecks `shouldBe` rootChecklistFixture dirPath
it "ignores files/directories that do not exist" $
withTempDir $ \ dirPath -> do
checks <- discoverDirectory
(dirPath </> "dir-do-not-exist")
"dir-do-not-exist"
checks `shouldBe` []
describe "discoverFile" $ do
it "scans all relative checks" $
withFixtureDir $ \ dirPath -> do
pyChecks <- discoverFile dirPath $ Prelude.head diffFixture
pyChecks `shouldBe` pyChecklistFixture dirPath
jsChecks <- discoverFile dirPath $ Prelude.last diffFixture
jsChecks `shouldBe` jsChecklistFixture dirPath
it "ignores files/directories that do not exist" $
withTempDir $ \ dirPath -> do
checklist <- discoverFile dirPath $ Prelude.head diffFixture
checklist `shouldBe` []