packages feed

language-gemini-0.1.0.1: test/Main.hs

{-# LANGUAGE OverloadedStrings #-}

module Main (main) where

import Language.Gemini (GeminiDocument, GeminiLine (..), decodeGemini, encodeGemini)

import Data.Text.Lazy (Text)
import qualified Data.Text.Lazy as TL
import Hedgehog (Gen, PropertyT, forAll, (===))
import Hedgehog.Gen (alphaNum, choice, frequency, list, sample, text, unicode)
import qualified Hedgehog.Gen as G
import Hedgehog.Range (constant, singleton)
import Test.Hspec (Spec, describe, hspec, it, shouldBe)
import Test.Hspec.Hedgehog (hedgehog)


main :: IO ()
main = hspec $ do
  encodeDecodeTrip

encodeDecodeTrip :: Spec
encodeDecodeTrip = do
  describe "Convertion" $ do
    it "Hello, world!" $ decodeGemini False (encodeGemini helloWorld) `shouldBe` helloWorld
    it "Hello, world! Text." $ encodeGemini (decodeGemini False helloWorldT) `shouldBe` helloWorldT
    it "Lorum ipsum." $ decodeGemini False (encodeGemini lorumIpsum) `shouldBe` lorumIpsum
    it "Lorum ipsum. Text." $ encodeGemini (decodeGemini False lorumIpsumT) `shouldBe` lorumIpsumT
    it "Gemini random trip" geminiTrip

helloWorld :: GeminiDocument
helloWorld =
  [ LH1 "Hello, World!"
  , LPre
    [ "main :: IO ()"
    , "main = putStrLn \"Welcome, geminicules!\""
    ]
  ]

helloWorldT :: Text
helloWorldT = "# Hello, World!\r\n```\r\nmain :: IO ()\r\nmain = putStrLn \"Welcome, geminiks!\"\r\n```"

lorumIpsum :: GeminiDocument
lorumIpsum =
  [ LH1 "Lorem ipsum dolor sit amet"
  , LH2 "consectetur adipiscing elit"
  , LH3 "sed do eiusmod tempor incididunt"
  , LLink "gemini://geminispace.info" (Just "ut labore et dolore magna aliqua.")
  , LPre
      [ "Ut enim ad minim veniam"
      , "quis nostrud exercitation ullamco laboris nisi"
      , "ut aliquip ex ea commodo consequat."
      ]
  , LText "Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur."
  , LItem "Excepteur sint occaecat cupidatat non proident,"
  , LItem "sunt in culpa qui officia deserunt mollit anim id est laborum."
  , LQuote "Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum."
  ]

lorumIpsumT :: Text
lorumIpsumT ="# Lorem ipsum dolor sit amet\r\n## consectetur adipiscing elit\r\n### sed do eiusmod tempor incididunt\r\n=> gemini://geminispace.info ut labore et dolore magna aliqua.\r\n```\r\nUt enim ad minim veniam\r\nquis nostrud exercitation ullamco laboris nisi\r\nut aliquip ex ea commodo consequat.\r\n```\r\nDuis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur.\r\n* Excepteur sint occaecat cupidatat non proident,\r\n* sunt in culpa qui officia deserunt mollit anim id est laborum.\r\n> Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum."


space :: Gen Char
space = G.constant ' '

txt :: Gen Text
txt = do
  -- It not tripped with empty text.
  notSpaceChar <- TL.fromStrict <$> text (singleton 1) alphaNum
  anyText <- TL.fromStrict <$> text (constant 0 20) char
  pure $ TL.append notSpaceChar anyText
  where
    char = frequency [(90, alphaNum), (10, space)]

textUnicode :: Gen Text
textUnicode = TL.fromStrict <$> (text (constant 1 20) char)
  where
    char = frequency [(90, unicode), (10, space)]

lText :: Gen GeminiLine
lText = LText <$> txt

lLink :: Gen GeminiLine
lLink = do
  link <- txt
  desc <- txt
  pure $ LLink link (Just desc)

lPre :: Gen GeminiLine
lPre = do
  pre <- list (constant 0 10) txt
  pure $ LPre pre

lItem :: Gen GeminiLine
lItem = LItem <$> txt

lQuote :: Gen GeminiLine
lQuote = LQuote <$> txt

lh1 :: Gen GeminiLine
lh1 = LH1 <$> txt

lh2 :: Gen GeminiLine
lh2 = LH1 <$> txt

lh3 :: Gen GeminiLine
lh3 = LH1 <$> txt

geminiTrip :: PropertyT IO ()
geminiTrip = hedgehog $ do
  let line = choice
        [ lh1
        , lh2
        , lh3
        , lQuote
        , lItem
        , lPre
        {-
        LLink not trips. Consider add encodeGeminiLenient to return spaces.
        Or better rename current encodeGemini to encodeGeminiEscapeSpace
        decodeGemini False $ encodeGemini $ [LLink "d d l" Nothing]
        [LLink "d+d+l" Nothing]
        -}
        -- , lLink
        , lText
        ]
  doc <- forAll $ list (constant 1 50) line
  decodeGemini False (encodeGemini doc) === doc