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