{-| Module : Text.Jira.Parser.BlockTests Copyright : © 2019 Albert Krewinkel License : MIT Maintainer : Albert Krewinkel Stability : alpha Portability : portable Tests for jira wiki block parsers. -} module Text.Jira.Parser.BlockTests (tests) where import Data.Either (isLeft) import Data.Text () import Text.Jira.Markup import Text.Jira.Parser.Block import Text.Jira.Parser.Core import Test.Tasty (TestTree, testGroup) import Test.Tasty.HUnit (testCase, (@?=), (@?)) import qualified Data.Text as Text tests :: TestTree tests = testGroup "Blocks" [ testGroup "components" [ testGroup "para" [ testCase "two lines" $ parseJira block "one\ntwo\n" @?= Right (Para [Str "one", Linebreak, Str "two"]) , testCase "ended by newline" $ parseJira para "Hello, World\n" @?= Right (Para [Str "Hello,", Space, Str "World"]) , testCase "ended by eof" $ parseJira para "Hello, World" @?= Right (Para [Str "Hello,", Space, Str "World"]) , testCase "ended by spaces and newline" $ parseJira para "Hello, World \n" @?= Right (Para [Str "Hello,", Space, Str "World"]) , testCase "ended by blank line" $ parseJira para "Hello\n\n" @?= Right (Para [Str "Hello"]) ] , testGroup "header" [ testCase "Level 1" $ parseJira header "h1. Intro\n" @?= Right (Header 1 [Str "Intro"]) , testCase "many spaces before title" $ parseJira header "h2. space\n" @?= Right (Header 2 [Str "space"]) , testCase "no space after dot" $ parseJira header "h3.hug\n" @?= Right (Header 3 [Str "hug"]) , testCase "empty header" $ parseJira header "h4.\n" @?= Right (Header 4 []) , testCase "Level 6" $ parseJira header "h6. More\n" @?= Right (Header 6 [Str "More"]) , testCase "Level 7 fails" $ isLeft (parseJira header "h7. More\n") @? "level 7 header" , testCase "Level 0 fails" $ isLeft (parseJira header "h0. More\n") @? "level 0 header" , testCase "leading spaces are disallowed" $ isLeft (parseJira header " h1. nope\n") @? "leading spaces" ] , testGroup "list" [ testCase "single item list" $ parseJira list "* hello\n" @?= Right (List CircleBullets [[Para [Str "hello"]]]) , testCase "simple list" $ let text = Text.unlines [ "* one" , "* two" ] in parseJira list text @?= Right (List CircleBullets [ [Para [Str "one"]] , [Para [Str "two"]]]) , testCase "list followed by different list" $ parseJira ((,) <$> list <*> list) "- first\n* second\n" @?= Right ( List SquareBullets [[Para [Str "first"]]] , List CircleBullets [[Para [Str "second"]]]) , testCase "nested lists" $ parseJira list "* first\n** nested\n" @?= Right (List CircleBullets [ [ Para [Str "first"] , List CircleBullets [[Para [Str "nested"]]] ] ]) , testCase "deeply nested list" $ parseJira list "*-* nested\n*-* list\n" @?= Right (List CircleBullets [ [ List SquareBullets [[ List CircleBullets [ [Para [Str "nested"]] , [Para [Str "list"]]] ]] ] ]) , testCase "markers can vary" $ parseJira list "#-* nested\n*** list\n" @?= Right (List Enumeration [[ List SquareBullets [[ List CircleBullets [ [Para [Str "nested"]] , [Para [Str "list"]] ] ]] ]]) , testCase "single nested list after paragraph" $ let text = Text.unlines [ "* line" , "continued" , "** nested" ] in parseJira list text @?= Right (List CircleBullets [ [ Para [Str "line", Linebreak, Str "continued"] , List CircleBullets [[Para [Str "nested"]]]]]) , testCase "multiple nested lists after paragraph" $ let text = Text.unlines [ "* line" , "continued" , "** nested" , "*# another" ] in parseJira list text @?= Right (List CircleBullets [ [ Para [Str "line", Linebreak, Str "continued"] , List CircleBullets [[Para [Str "nested"]]] , List Enumeration [[Para [Str "another"]]]]]) , testCase "item after nested list" $ let text = Text.unlines [ "* first" , "** nested" , "* second" ] in parseJira list text @?= Right (List CircleBullets [ [ Para [Str "first"] , List CircleBullets [[Para [Str "nested"]]]] , [ Para [Str "second"]]]) , testCase "nested lists" $ let text = Text.unlines [ "** eins" , "*- zwei" , "** drei" ] in parseJira list text @?= Right (List CircleBullets [ [ List CircleBullets [[Para [Str "eins"]]] , List SquareBullets [[Para [Str "zwei"]]] , List CircleBullets [[Para [Str "drei"]]] ] ]) ] , testGroup "Table" [ testCase "single cell" $ parseJira table "| Lua \n" @?= Right (Table [Row [BodyCell [Para [Str "Lua"]]]]) , testCase "header cell" $ parseJira table "|| Language\n" @?= Right (Table [Row [HeaderCell [Para [Str "Language"]]]]) , testCase "2x2 table" $ parseJira table (Text.unlines [ "|| Language || Type ||" , "| Lua | dynamic |\n"]) @?= Right (Table [ Row [ HeaderCell [Para [Str "Language"]] , HeaderCell [Para [Str "Type"]] ] , Row [ BodyCell [Para [Str "Lua"]] , BodyCell [Para [Str "dynamic"]] ] ]) , testCase "row headeres" $ parseJira table (Text.unlines [ "|| Language | Haskell ||" , "|| Type | static |\n"]) @?= Right (Table [ Row [ HeaderCell [Para [Str "Language"]] , BodyCell [Para [Str "Haskell"]] ] , Row [ HeaderCell [Para [Str "Type"]] , BodyCell [Para [Str "static"]] ] ]) , testCase "list in table" $ parseJira table "| * foo\n* bar\n" @?= Right (Table [ Row [BodyCell [List CircleBullets [ [Para [Str "foo"]] , [Para [Str "bar"]] ]]]]) , testCase "multiple line cells" $ parseJira table "| foo\nbar | baz |\n" @?= Right (Table [ Row [ BodyCell [Para [Str "foo", Linebreak, Str "bar"]] , BodyCell [Para [Str "baz"]]]]) , testCase "multiple lists in cell" $ parseJira table "| * foo\n- bar\n" @?= Right (Table [Row [BodyCell [ List CircleBullets [[Para [Str "foo"]]] , List SquareBullets [[Para [Str "bar"]]]]]]) ] , testGroup "code" [ testCase "no language" $ parseJira code "{code}\nprint('Hi Mom!'){code}\n" @?= Right (Code (Language "java") [] "print('Hi Mom!')") , testCase "with language" $ parseJira code "{code:swift}\nfunc foo() -> Int { return 4 }{code}\n" @?= Right (Code (Language "swift") [] "func foo() -> Int { return 4 }") , testCase "with parameters" $ parseJira code "{code:title=coffee|bgColor=#ccc}\nblack(){code}\n" @?= Right (Code (Language "java") [Parameter "title" "coffee", Parameter "bgColor" "#ccc"] "black()") , testCase "with language and parameter" $ parseJira code "{code:haskell|title=Hello World}\nputStrLn \"Hello, World!\"{code}\n" @?= Right (Code (Language "haskell") [Parameter "title" "Hello World"] "putStrLn \"Hello, World!\"") ] , testGroup "noformat" [ testCase "no parameters" $ parseJira noformat "{noformat}\nline 1\nline 2{noformat}\n" @?= Right (NoFormat [] "line 1\nline 2") , testCase "with parameters" $ parseJira noformat "{noformat:title=test}\nline 1\nline 2{noformat}\n" @?= Right (NoFormat [Parameter "title" "test"] "line 1\nline 2") ] , testGroup "panel" [ testCase "two-line paragraph" $ parseJira panel "{panel}\nline 1\nline 2\n{panel}\n" @?= Right (Panel [] [Para [Str "line", Space, Str "1", Linebreak, Str "line", Space, Str "2"]]) -- FIXME: the next two shouldn't require a blank line after the contents , testCase "list" $ parseJira panel "{panel}\n* first\n* second\n\n{panel}\n" @?= Right (Panel [] [List CircleBullets [ [Para [Str "first"]] , [Para [Str "second"]]]]) , testCase "with parameters" $ parseJira panel "{panel:title=test}\nline\n{panel}\n" @?= Right (Panel [Parameter "title" "test"] [Para [Str "line"]]) ] , testGroup "blockQuote" [ testCase "single line quite before eof" $ parseJira blockQuote "bq. this text" @?= Right (BlockQuote [Para [Str "this", Space, Str "text"]]) , testCase "single line blockquote" $ parseJira blockQuote "bq. this test\n" @?= Right (BlockQuote [Para [Str "this", Space, Str "test"]]) , testCase "multi-paragraph block quote" $ parseJira blockQuote "{quote}\npara1\n\npara2\n{quote}\n" @?= Right (BlockQuote [ Para [Str "para1"] , Para [Str "para2"]]) , testCase "condensed block quote" $ parseJira blockQuote "{quote}life is good{quote}\n" @?= Right (BlockQuote [Para [Str "life", Space, Str "is", Space, Str "good"]]) ] ] , testGroup "block combinations" [ testCase "single paragraph" $ parseJira block "Lorem ipsum." @?= Right (Para [Str "Lorem", Space, Str "ipsum."]) , testCase "para before header" $ parseJira ((,) <$> block <*> block) "paragraph\nh1.header\n" @?= Right (Para [Str "paragraph"], Header 1 [Str "header"]) , testCase "para after header" $ parseJira ((,) <$> block <*> block) "h2.header\nparagraph\n" @?= Right (Header 2 [Str "header"], Para [Str "paragraph"]) , testCase "para after list" $ parseJira ((,) <$> block <*> block) "* foo\n\nbar\n" @?= Right (List CircleBullets [[Para [Str "foo"]]], Para [Str "bar"]) , testCase "successive lists of same type" $ parseJira ((,) <$> block <*> block) "* foo\n\n* bar\n" @?= Right ( List CircleBullets [[Para [Str "foo"]]] , List CircleBullets [[Para [Str "bar"]]]) , testCase "para after table" $ parseJira ((,) <$> block <*> block) "|| point |\nhuh\n" @?= Right ( Table [Row [HeaderCell [Para [Str "point"]]]] , Para [Str "huh"]) , testCase "para after blankline terminated table" $ parseJira ((,) <$> block <*> block) "|| love\n\npeace\n" @?= Right ( Table [Row [HeaderCell [Para [Str "love"]]]] , Para [Str "peace"]) , testCase "para before code" $ parseJira ((,) <$> block <*> block) "nice\n{code}\nhappy(){code}\n" @?= Right ( Para [Str "nice"] , Code (Language "java") [] "happy()") , testCase "para after code" $ parseJira ((,) <$> block <*> block) "{code}\nfn(){code}\ntext" @?= Right ( Code (Language "java") [] "fn()" , Para [Str "text"]) , testCase "para before noformat" $ parseJira ((,) <$> block <*> block) "wholesome\n{noformat}\nenjoy{noformat}\n" @?= Right ( Para [Str "wholesome"] , NoFormat [] "enjoy") , testCase "para after noformat" $ parseJira ((,) <$> block <*> block) "{noformat}\nlala{noformat}\ntext" @?= Right ( NoFormat [] "lala" , Para [Str "text"]) ] ]