1{-# LANGUAGE OverloadedStrings #-}
2module Tests.Lua ( tests ) where
4import Control.Monad (when)
5import Data.Version (Version (versionBranch))
6import System.FilePath ((</>))
7import Test.Tasty (TestTree, localOption)
8import Test.Tasty.HUnit (Assertion, assertEqual, testCase)
9import Test.Tasty.QuickCheck (QuickCheckTests (..), ioProperty, testProperty)
10import Text.Pandoc.Arbitrary ()
11import Text.Pandoc.Builder (bulletList, divWith, doc, doubleQuoted, emph,
12 header, linebreak, para, plain, rawBlock,
13 singleQuoted, space, str, strong, (<>))
14import Text.Pandoc.Class (runIOorExplode, setUserDataDir)
15import Text.Pandoc.Definition (Block (BlockQuote, Div, Para), Inline (Emph, Str),
16 Attr, Meta, Pandoc, pandocTypesVersion)
17import Text.Pandoc.Lua (runLuaFilter, runPandocLua)
18import Text.Pandoc.Options (def)
19import Text.Pandoc.Shared (pandocVersion)
21import qualified Foreign.Lua as Lua
24tests = map (localOption (QuickCheckTests 20))
25 [ testProperty "inline elements can be round-tripped through the lua stack" $
26 \x -> ioProperty (roundtripEqual (x::Inline))
28 , testProperty "block elements can be round-tripped through the lua stack" $
29 \x -> ioProperty (roundtripEqual (x::Block))
31 , testProperty "meta blocks can be round-tripped through the lua stack" $
32 \x -> ioProperty (roundtripEqual (x::Meta))
34 , testProperty "documents can be round-tripped through the lua stack" $
35 \x -> ioProperty (roundtripEqual (x::Pandoc))
37 , testCase "macro expansion via filter" $
38 assertFilterConversion "a '{{helloworld}}' string is expanded"
40 (doc . para $ str "{{helloworld}}")
41 (doc . para . emph $ str "Hello, World")
43 , testCase "convert all plains to paras" $
44 assertFilterConversion "plains become para"
46 (doc $ bulletList [plain (str "alfa"), plain (str "bravo")])
47 (doc $ bulletList [para (str "alfa"), para (str "bravo")])
49 , testCase "make hello world document" $
50 assertFilterConversion "Document contains 'Hello, World!'"
52 (doc . para $ str "Hey!" <> linebreak <> str "What's up?")
53 (doc . para $ str "Hello," <> space <> str "World!")
55 , testCase "implicit doc filter" $
56 assertFilterConversion "Document contains 'Hello, World!'"
57 "implicit-doc-filter.lua"
58 (doc . plain $ linebreak)
59 (doc . para $ str "Hello," <> space <> str "World!")
61 , testCase "parse raw markdown blocks" $
62 assertFilterConversion "raw markdown block is converted"
64 (doc $ rawBlock "markdown" "*charly* **delta**")
65 (doc . para $ emph "charly" <> space <> strong "delta")
67 , testCase "allow shorthand functions for quote types" $
68 assertFilterConversion "single quoted becomes double quoted string"
69 "single-to-double-quoted.lua"
70 (doc . para . singleQuoted $ str "simple")
71 (doc . para . doubleQuoted $ str "simple")
73 , testCase "Count inlines via metatable catch-all" $
74 assertFilterConversion "filtering with metatable catch-all failed"
75 "metatable-catch-all.lua"
76 (doc . para $ "four words, three spaces")
77 (doc . para $ str "7")
79 , testCase "Count blocks via Block-specific catch-all" $
80 assertFilterConversion "filtering with Block catch-all failed"
82 (doc $ para "one" <> para "two")
85 , testCase "Convert header upper case" $
86 assertFilterConversion "converting header to upper case failed"
87 "uppercase-header.lua"
88 (doc $ header 1 "les états-unis" <> para "text")
89 (doc $ header 1 "LES ÉTATS-UNIS" <> para "text")
91 , testCase "Attribute lists are convenient to use" $
92 let kv_before = [("one", "1"), ("two", "2"), ("three", "3")]
93 kv_after = [("one", "eins"), ("three", "3"), ("five", "5")]
94 in assertFilterConversion "Attr doesn't behave as expected"
96 (doc $ divWith ("", [], kv_before) (para "nil"))
97 (doc $ divWith ("", [], kv_after) (para "nil"))
99 , testCase "Test module pandoc.utils" $
100 assertFilterConversion "pandoc.utils doesn't work as expected."
101 "test-pandoc-utils.lua"
102 (doc $ para "doesn't matter")
103 (doc $ mconcat [ plain (str "hierarchicalize: OK")
104 , plain (str "normalize_date: OK")
105 , plain (str "pipe: OK")
106 , plain (str "failing pipe: OK")
107 , plain (str "read: OK")
108 , plain (str "failing read: OK")
109 , plain (str "sha1: OK")
110 , plain (str "stringify: OK")
111 , plain (str "to_roman_numeral: OK")
114 , testCase "Pandoc version is set" . runPandocLua' $ do
115 Lua.getglobal' "table.concat"
116 Lua.getglobal "PANDOC_VERSION"
117 Lua.push ("." :: String) -- seperator
119 Lua.liftIO . assertEqual "pandoc version is wrong" pandocVersion
120 =<< Lua.peek Lua.stackTop
122 , testCase "Pandoc types version is set" . runPandocLua' $ do
123 let versionNums = versionBranch pandocTypesVersion
124 Lua.getglobal "PANDOC_API_VERSION"
125 Lua.liftIO . assertEqual "pandoc-types version is wrong" versionNums
126 =<< Lua.peek Lua.stackTop
128 , testCase "Allow singleton inline in constructors" . runPandocLua' $ do
129 Lua.liftIO . assertEqual "Not the exptected Emph" (Emph [Str "test"])
130 =<< Lua.callFunc "pandoc.Emph" (Str "test")
131 Lua.liftIO . assertEqual "Unexpected element" (Para [Str "test"])
132 =<< Lua.callFunc "pandoc.Para" ("test" :: String)
133 Lua.liftIO . assertEqual "Unexptected element"
134 (BlockQuote [Para [Str "foo"]]) =<< (
136 Lua.getglobal' "pandoc.BlockQuote"
137 Lua.push (Para [Str "foo"])
139 Lua.peek Lua.stackTop
142 , testCase "Elements with Attr have `attr` accessor" . runPandocLua' $ do
143 Lua.push (Div ("hi", ["moin"], [])
144 [Para [Str "ignored"]])
145 Lua.getfield Lua.stackTop "attr"
146 Lua.liftIO . assertEqual "no accessor" (("hi", ["moin"], []) :: Attr)
147 =<< Lua.peek Lua.stackTop
149 , testCase "informative error messages" . runPandocLua' $ do
151 err <- Lua.peekEither Lua.stackTop :: Lua.Lua (Either String Pandoc)
154 let expectedMsg = "Could not get Pandoc value: "
155 ++ "expected table but got boolean."
156 Lua.liftIO $ assertEqual "unexpected error message" expectedMsg msg
157 Right _ -> error "Getting a Pandoc element from a bool should fail."
160assertFilterConversion :: String -> FilePath -> Pandoc -> Pandoc -> Assertion
161assertFilterConversion msg filterPath docIn docExpected = do
162 docEither <- runIOorExplode $ do
163 setUserDataDir (Just "../data")
164 runLuaFilter def ("lua" </> filterPath) [] docIn
166 Left _ -> fail "lua filter failed"
167 Right docRes -> assertEqual msg docExpected docRes
169roundtripEqual :: (Eq a, Lua.FromLuaStack a, Lua.ToLuaStack a) => a -> IO Bool
170roundtripEqual x = (x ==) <$> roundtripped
172 roundtripped :: (Lua.FromLuaStack a, Lua.ToLuaStack a) => IO a
173 roundtripped = runPandocLua' $ do
174 oldSize <- Lua.gettop
177 when (size - oldSize /= 1) $
178 error ("not exactly one additional element on the stack: " ++ show size)
179 res <- Lua.peekEither (-1)
181 Left e -> error (show e)
184runPandocLua' :: Lua.Lua a -> IO a
185runPandocLua' op = runIOorExplode $ do
186 setUserDataDir (Just "../data")
187 res <- runPandocLua op
189 Left e -> error (show e)
keysesc to close
- j k
- move down, up
- enter
- open
- esc
- back, or up a level
- 1 2 3 4
- readme, files, commits, refs
- /
- filter
- y
- copy the clone command
- c
- compare the chosen commit with another (or shift-click both)
- ?
- show or hide this list