module Data.String.Interpolate.UtilSpec (main, spec) where

import           Prelude ()
import           Prelude.Compat

import           Test.Hspec
import           Test.QuickCheck

import           Data.String.Interpolate.Util

main :: IO ()
main = hspec spec

emptyLine :: Gen String
emptyLine = (++ "\n") <$> listOf (elements " \t")

spec :: Spec
spec = do
  describe "unindent" $ do
    it "removes indentation" $ do
      let xs = "    foo\n  bar\n   baz  \n"
      unindent xs `shouldBe` "  foo\nbar\n baz  \n"

    it "removes the first line of the string if it is empty" $ do
      forAll emptyLine $ \xs -> do
        let ys = "  foo\nbar\n baz\n"
        unindent (xs ++ ys) `shouldBe` ys

    it "does not affect additional empty lines at the beginning" $ do
      unindent "  \n  \nfoo" `shouldBe` "  \nfoo"

    it "empties the last line if it only consists of spaces" $ do
      let xs = "foo\n  "
      unindent xs `shouldBe` "foo\n"

    it "does not affect other whitespace lines at the end" $ do
      unindent "foo\n  \n  " `shouldBe` "foo\n  \n"

    it "disregards empty lines when calculating indentation" $ do
      let xs = "  foo\n\n \n  bar\n"
      unindent xs `shouldBe` "foo\n\n\nbar\n"

    it "correctly handles strings that do not end with a newline" $ do
      let xs = "foo"
      unindent xs `shouldBe` xs

    it "does not affect lines consisting of whitespace (apart from unindenting)" $ do
      unindent " foo\n  \n bar" `shouldBe` "foo\n \nbar"

    it "is total" $ do
      property $ \xs -> length (unindent xs) `shouldSatisfy` (>= 0)

    context "when all lines are empty" $ do
      it "does not unindent at all" $ do
        forAll emptyLine $ \x -> (forAll $ listOf emptyLine) $ \xs -> do
          let ys = concat xs
          unindent (x ++ ys) `shouldBe` ys
