git.iko.soy/typeable/hjsonpointer
on master help sign in
92 lines 2.8 kB history raw
1{-# LANGUAGE GeneralizedNewtypeDeriving #-}
2{-# LANGUAGE StandaloneDeriving #-}
4module Main where
6import Data.Aeson
7import Data.Bifunctor (first)
8import Data.Foldable
9import Data.Monoid
10import Data.Text (Text)
11import qualified Data.Text as T
12import Data.Text.Encoding (decodeUtf8, encodeUtf8)
13import qualified Data.Vector as V
14import qualified JSONPointer as JP
15import Network.HTTP.Types.URI (urlDecode)
17import Test.Hspec
18import Test.QuickCheck (Arbitrary(..), property)
20import qualified Example
22deriving instance Arbitrary JP.Pointer
24instance Arbitrary JP.Token where
25 arbitrary = JP.Token . T.pack <$> arbitrary
27main :: IO ()
28main = hspec $ do
29 describe "example" $ do
30 it "compiles and runs without errors" Example.main
31 describe "pointers" $ do
32 it "can be stored as JSON without changing its value" (property roundtrip)
33 it "can be represented in a JSON string value" jsonString
34 it "can be represented in a URI fragment identifier" uriFragment
36roundtrip :: JP.Pointer -> Bool
37roundtrip a = Just a == decode (encode a)
39jsonString :: Expectation
40jsonString = traverse_ resolvesTo
41 [ ("" , specExample)
42 , ("/foo" , Array $ V.fromList ["bar", "baz"])
43 , ("/foo/0", String "bar")
44 , ("/" , Number 0)
45 , ("/a~1b" , Number 1)
46 , ("/c%d" , Number 2)
47 , ("/e^f" , Number 3)
48 , ("/g|h" , Number 4)
49 , ("/i\\j" , Number 5)
50 , ("/k\"l" , Number 6)
51 , ("/ " , Number 7)
52 , ("/m~0n" , Number 8)
53 ]
55uriFragment :: Expectation
56uriFragment = traverse_ resolvesTo . fmap (first decodeFragment) $
57 [ ("#" , specExample)
58 , ("#/foo" , Array $ V.fromList ["bar", "baz"])
59 , ("#/foo/0", String "bar")
60 , ("#/" , Number 0)
61 , ("#/a~1b" , Number 1)
62 , ("#/c%25d", Number 2)
63 , ("#/e%5Ef", Number 3)
64 , ("#/g%7Ch", Number 4)
65 , ("#/i%5Cj", Number 5)
66 , ("#/k%22l", Number 6)
67 , ("#/%20" , Number 7)
68 , ("#/m~0n" , Number 8)
69 ]
70 where
71 decodeFragment :: Text -> Text
72 decodeFragment = T.drop 1 . decodeUtf8 . urlDecode True . encodeUtf8
74resolvesTo :: (Text, Value) -> Expectation
75resolvesTo (t, expected) =
76 case JP.unescape t of
77 Left e -> expectationFailure (show e <> " error for pointer: " <> show t)
78 Right p -> JP.resolve p specExample `shouldBe` Right expected
80specExample :: Value
81specExample = object
82 [ "foo" .= (["bar", "baz"] :: [Text])
83 , "" .= (0 :: Int)
84 , "a/b" .= (1 :: Int)
85 , "c%d" .= (2 :: Int)
86 , "e^f" .= (3 :: Int)
87 , "g|h" .= (4 :: Int)
88 , "i\\j" .= (5 :: Int)
89 , "k\"l" .= (6 :: Int)
90 , " " .= (7 :: Int)
91 , "m~n" .= (8 :: Int)
92 ]