packages feed

http-api-data-qq-0.1.0.0: test/Web/HttpApiData/QQ/ParserTest.hs

{-# LANGUAGE TupleSections #-}

module Web.HttpApiData.QQ.ParserTest (tests) where

import Test.Tasty (TestTree, testGroup)
import Test.Tasty.HUnit
import Test.Tasty.QuickCheck

import Web.HttpApiData.QQ.Parser

tests :: TestTree
tests =
  testGroup
    "Web.HttpApiData.QQ.Parser"
    [ testCase "Sanity check" $ do
        let expected = [RawString "/foo/", InterpolatedName "bar", RawString "/baz"]
        parseUrlPieces "/foo/#{bar}/baz" @?= Right expected
    , testCase "Allows special characters in non-interpolation settings" $
        parseUrlPieces "/foo/ba{r}/baz#asdf" @?= Right [RawString "/foo/ba{r}/baz#asdf"]
    , testProperty "Parses any raw string" $
        forAll rawString1 $ \s ->
          parseUrlPieces s === Right [RawString s]
    , testProperty "Parses any combination of raw/interpolated strings" $
        forAll (alternatingListOf ((,True) <$> rawString1) ((,False) <$> rawString1)) $ \parts ->
          let input =
                flip concatMap parts $ \(s, isRaw) ->
                  if isRaw then s else "#{" ++ s ++ "}"
              expected =
                flip map parts $ \(s, isRaw) ->
                  if isRaw then RawString s else InterpolatedName s
           in parseUrlPieces input === Right expected
    ]

{- |
For two generators A and B, generates a list where each element
alternates between the two generators.

e.g.
  * []
  * [A]
  * [B]
  * [A, B]
  * [B, A]
  * [A, B, A]
  * [B, A, B]
-}
alternatingListOf :: Gen a -> Gen a -> Gen [a]
alternatingListOf genA genB = do
  startOnB <- arbitrary
  NonNegative n <- arbitrary
  sequence $ take n $ cycle $ if startOnB then [genB, genA] else [genA, genB]

-- | String that won't contain any interpolation characters.
rawString :: Gen String
rawString = listOf (arbitrary `suchThat` (`notElem` "#{}"))

rawString1 :: Gen String
rawString1 = rawString `suchThat` (/= "")