1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110
|
{-# LANGUAGE LambdaCase #-}
{-# LANGUAGE NamedFieldPuns #-}
{-# LANGUAGE OverloadedStrings #-}
{-# LANGUAGE RecordWildCards #-}
{-# LANGUAGE TupleSections #-}
{-# LANGUAGE UnicodeSyntax #-}
module Main where
import qualified Codec.Archive.Tar as Tar
import qualified Codec.Compression.GZip as GZip
import Control.Applicative ((<$>), (<*>))
import Control.Lens
import Control.Monad
import Data.ByteString.Lazy (toStrict)
import Data.Foldable (for_)
import qualified Data.HashMap.Strict as HM (HashMap, empty,
traverseWithKey)
import Data.List
import Data.Maybe (fromMaybe)
import qualified Data.Text as T
import Data.Yaml as Y (FromJSON, Value (..), decode,
parseJSON, (.!=), (.:), (.:?))
import Network.Wreq
import System.FilePath
import Test.Hspec
import Text.Mustache
langspecs :: [String]
langspecs =
[ "https://codeload.github.com/andrewthad/spec/legacy.tar.gz/add_list_context_check"
, "https://codeload.github.com/mustache/spec/tar.gz/v1.1.3"
]
data LangSpecFile = LangSpecFile
{ overview :: String
, tests :: [LangSpecTest]
}
data LangSpecTest = LangSpecTest
{ name :: String
, specDescription :: String
, specData :: Y.Value
, template :: T.Text
, expected :: T.Text
, testPartials :: HM.HashMap String T.Text
}
instance FromJSON LangSpecFile where
parseJSON (Y.Object o) = LangSpecFile
<$> o .: "overview"
<*> o .: "tests"
parseJSON _ = mzero
instance FromJSON LangSpecTest where
parseJSON (Y.Object o) = LangSpecTest
<$> o .: "name"
<*> o .: "desc"
<*> o .: "data"
<*> o .: "template"
<*> o .: "expected"
<*> o .:? "partials" .!= HM.empty
parseJSON _ = mzero
getOfficialSpecRelease :: String -> IO [(String, LangSpecFile)]
getOfficialSpecRelease releaseURL = do
res <- get releaseURL
let archive = Tar.read $ GZip.decompress (res ^. responseBody)
return $ Tar.foldEntries handleEntry [] (error . show) archive
where
handleEntry e acc =
case content of
Tar.NormalFile f _
| takeExtension filename `elem` [".yml", ".yaml"]
&& not ("~" `isPrefixOf` takeFileName filename) ->
(filename, fromMaybe (error $ "Error parsing spec file " ++ filename) $ decode $ toStrict f):acc
_ -> acc
where
filename = Tar.entryPath e
content = Tar.entryContent e
testOfficialLangSpec :: [(String, LangSpecFile)] -> Spec
testOfficialLangSpec testfiles =
for_ testfiles $ \(filename, LangSpecFile { tests }) ->
describe ("File: " ++ takeFileName filename) $
for_ tests $ \(LangSpecTest { .. }) ->
it ("Name: " ++ name ++ " Description: " ++ specDescription) $
let
compiled = do
partials' <- HM.traverseWithKey compileTemplate testPartials
template' <- compileTemplate name template
return $ template' { partials = partials' }
in
case compiled of
Left m -> expectationFailure $ show m
Right tmp ->
substituteValue tmp (toMustache specData) `shouldBe` expected
main :: IO ()
main =
void $ do
specs <- mapM getOfficialSpecRelease langspecs
hspec $ mapM_ testOfficialLangSpec specs
|