packages feed

lentil-0.1.2.0: test/Lentil/Parse/IssueSpec.hs

module Lentil.Parse.IssueSpec where

import Test.Hspec
import Text.Parsec ( runParser )
import Text.Parsec.Char
import Control.Applicative

import Lentil.Types
import Lentil.Parse.Issue

import Prelude -- 7.8 hack

-- Parsing tests

-- simple parser (choosable if we are at begin of line or else)
sp :: ParIssue a -> String -> Maybe a
sp p cs = either (const Nothing) Just
                    (runParser p () fp cs)
    where fp = "<f>"


main :: IO ()
main = hspec spec



spec :: Spec
spec = do

  describe "ciString" $ do
    it "parses a case insensitive string" $
      sp (ciString "tEst") "Test" `shouldBe` Just "Test"

  describe "eoft" $ do
    it "parses a textfile end of file" $
      sp (string "test" <* eoft) "test\n" `shouldBe` Just "test"
    it "or an eof without '\\n'" $
      sp (string "test" <* eoft) "test"   `shouldBe` Just "test"

  describe "blankline" $ do
    it "parses an empty line" $
      sp blankline "\n\nlol"   `shouldBe` Just ()
    it "deals with eof blanklines too" $
      sp blankline "\n" `shouldBe` Just ()

  describe "htmlify" $ do
    it "removes unneeded whitespace" $
      htmlify "one  two " `shouldBe` "one two"
    it "removes newlines too" $
      htmlify "one  two\nthree " `shouldBe` "one two three"

  describe "tag" $ do
    it "parses a tag" $
      fmap tagString (sp tag "[test-tag]") `shouldBe` Just "test-tag"
    it "should not allow whitespace inside a tag" $
      fmap tagString (sp tag "[broken tag]") `shouldBe` Nothing

  describe "incipit" $ do
    it "parses the initial section of an issue, returns nothing" $
       do sp incipit "TODO: "  `shouldBe` Just Todo
          sp incipit "FIXME: "  `shouldBe` Just Fixme
          sp incipit "XXX: "  `shouldBe` Just Xxx
    it "doesn't work without previous newline" $
      sp incipit "TODO:some"  `shouldBe` Nothing
    it "doesn't work if you don't add a space after :" $
      sp incipit "TODO:some"  `shouldBe` Nothing
    it "does allow you to omit the :" $
      sp incipit "xxx some"  `shouldBe` Just Xxx
    it "is case unsensitive in flag-word" $
      sp incipit "tOdO some"  `shouldBe` Just Todo
    it "doesn't allow anything before flag-words" $
      sp incipit "so fixme someday"  `shouldBe` Nothing
    it "fails if we are not at the beginning of line" $
      sp incipit "so fixme someday"  `shouldBe` Nothing

  describe "tags" $ do
    it "parses a series of tags, sep by whitespace" $
      sp tags " [tag] [field:test] [tog]"
         `shouldBe` Just [Tag "tag", Tag "field:test", Tag "tog"]
    it "allows ending whitespace" $
      sp tags "   [tag] [field:test] [tog] "
         `shouldBe` Just [Tag "tag", Tag "field:test", Tag "tog"]

  describe "freeText" $ do
    it "parses a free form text" $
      sp freeText "this is it\n\n" `shouldBe` Just "this is it"
    it "can be ended by tags/fields" $
      sp freeText "this is it [field:val]" `shouldBe` Just "this is it"
    it "trims extra whitespace" $
      sp freeText "this is  it [bug]" `shouldBe` Just "this is it"
    it "cannot be ended by new issue on same line" $
      sp freeText "this is it   TODO: desc\n" `shouldBe`
             Just "this is it TODO: desc"
    it "cannot be ended by new issue on new-but-not-beginning-of-line" $
      sp freeText "this is it \nn  TODO: desc\n" `shouldBe`
             Just "this is it n TODO: desc"
    it "can be ended by blank line" $
      sp freeText "this is it\n\n  TODO: desc" `shouldBe` Just "this is it"
    it "can be ended by incomplete blank line (eof)" $
      sp freeText "this is it\n" `shouldBe` Just "this is it"

  describe "issue" $ do
    it "parses an issue" $
      sp issue "fixMe this is it [t] [f:w]"
         `shouldBe` (Just $ Issue "<f>" 1 "this is it"
                                  [Tag "fixme", Tag "t", Tag "f:w"])
    it "parses tagless/fieldless issues too" $
      sp issue "TODO: this is it\n"
         `shouldBe` (Just $ Issue "<f>" 1 "this is it" [])
    it "parses an issue not ended by \\n" $
      sp issue "todo block1 "
         `shouldBe` (Just $ Issue "<f>" 1 "block1" [])
    it "doesn't display the eventual \n at eof" $
      sp issue "TOdO: this is it\n"
         `shouldBe` (Just $ Issue "<f>" 1 "this is it" [])
    it "doesn't accept a lone (naked) todo" $
      sp issue "todo\n"
         `shouldBe` Nothing
    it "issues declared with fixme get a free [fixme] tag" $
      sp issue "fixme blah\n"
         `shouldBe` (Just $ Issue "<f>" 1 "blah" [Tag "fixme"])

  describe "issues" $ do
    it "parses multiple issues" $
      sp issues "TODO: this is it [f:w]\n TODO: hey [t]"
         `shouldBe` Just [Issue "<f>" 1 "this is it" [Tag "f:w"],
                          Issue "<f>" 2 "hey" [Tag "t"]]
    it "parse multiple issues if on the same line" $
      sp issues "TODO: this is it [f:w] TODO: hey [t]"
         `shouldBe` Just [Issue "<f>" 1 "this is it" [Tag "f:w"],
                          Issue "<f>" 1 "hey" [Tag "t"]]
    it "don't parse multiple issues on the same line if not ended by tags" $
      sp issues "TODO: this is it todo hey [t]"
         `shouldBe` Just [Issue "<f>" 1 "this is it todo hey" [Tag "t"]]
    it "parses two issues, tagless, if the second starts on nl" $
      sp issues "TODO: this is it \n  todo hey [t]"
         `shouldBe` Just [Issue "<f>" 1 "this is it" [],
                          Issue "<f>" 2 "hey" [Tag "t"]]