packages feed

hjsonpointer-1.1.0.0: test/Unit.hs

module Main where

import           Control.Arrow
import           Data.Aeson
import           Data.Text              (Text)
import qualified Data.Text              as T
import           Data.Text.Encoding
import qualified Data.Vector            as V
import qualified JSONPointer            as JP
import           Network.HTTP.Types.URI (urlDecode)

import           Test.Hspec
import           Test.QuickCheck        (property)

-- For GHCs before 7.10:
import           Control.Applicative
import           Data.Foldable
import           Data.Monoid

import qualified Example

main :: IO ()
main = hspec $ do
    describe "example" $ do
        it "compiles and runs without errors" Example.main
    describe "pointers" $ do
        it "can be stored as JSON without changing its value" (property roundtrip)
        it "can be represented in a JSON string value" jsonString
        it "can be represented in a URI fragment identifier" uriFragment

roundtrip :: JP.Pointer -> Bool
roundtrip a = Just a == decode (encode a)

jsonString :: Expectation
jsonString = traverse_ resolvesTo
    [ (""      , specExample)
    , ("/foo"  , Array $ V.fromList ["bar", "baz"])
    , ("/foo/0", String "bar")
    , ("/"     , Number 0)
    , ("/a~1b" , Number 1)
    , ("/c%d"  , Number 2)
    , ("/e^f"  , Number 3)
    , ("/g|h"  , Number 4)
    , ("/i\\j" , Number 5)
    , ("/k\"l" , Number 6)
    , ("/ "    , Number 7)
    , ("/m~0n" , Number 8)
    ]

uriFragment :: Expectation
uriFragment = traverse_ resolvesTo . fmap (first decodeFragment) $
    [ ("#"      , specExample)
    , ("#/foo"  , Array $ V.fromList ["bar", "baz"])
    , ("#/foo/0", String "bar")
    , ("#/"     , Number 0)
    , ("#/a~1b" , Number 1)
    , ("#/c%25d", Number 2)
    , ("#/e%5Ef", Number 3)
    , ("#/g%7Ch", Number 4)
    , ("#/i%5Cj", Number 5)
    , ("#/k%22l", Number 6)
    , ("#/%20"  , Number 7)
    , ("#/m~0n" , Number 8)
    ]
  where
    decodeFragment :: Text -> Text
    decodeFragment = T.drop 1 . decodeUtf8 . urlDecode True . encodeUtf8

resolvesTo :: (Text, Value) -> Expectation
resolvesTo (t, expected) =
    case JP.unescape t of
        Left e  -> expectationFailure (show e <> " error for pointer: " <> show t)
        Right p -> JP.resolve p specExample `shouldBe` Right expected

specExample :: Value
specExample = object
    [ "foo"  .= (["bar", "baz"] :: [Text])
    , ""     .= (0 :: Int)
    , "a/b"  .= (1 :: Int)
    , "c%d"  .= (2 :: Int)
    , "e^f"  .= (3 :: Int)
    , "g|h"  .= (4 :: Int)
    , "i\\j" .= (5 :: Int)
    , "k\"l" .= (6 :: Int)
    , " "    .= (7 :: Int)
    , "m~n"  .= (8 :: Int)
    ]