collection-json 1.1.0.0 → 1.1.0.1
raw patch · 13 files changed
+310/−282 lines, 13 filesPVP ok
version bump matches the API change (PVP)
API changes (from Hackage documentation)
Files
- ChangeLog.md +8/−0
- collection-json.cabal +7/−7
- src/Data/CollectionJSON.hs +1/−1
- src/External/Network/URI/JSON.hs +23/−0
- src/Internal/Network/URI/JSON.hs +0/−23
- test/Data/CollectionJSON/Arbitrary.hs +18/−2
- test/Data/CollectionJSONSpec.hs +10/−10
- test/External/Network/URI/Arbitrary.hs +191/−0
- test/External/Network/URI/ArbitrarySpec.hs +25/−0
- test/External/Network/URI/JSONSpec.hs +27/−0
- test/Internal/Network/URI/Arbitrary.hs +0/−187
- test/Internal/Network/URI/ArbitrarySpec.hs +0/−25
- test/Internal/Network/URI/JSONSpec.hs +0/−27
ChangeLog.md view
@@ -1,5 +1,13 @@ # Revision history for collection-json +## 1.1.0.1 -- 2017-11-11++* reduce prop usage by using it correctly+* add shrink methods to Arbitrary instances+* move Internal module to External+* fix git URL+* remove broken travis deployment+ ## 1.1.0.0 -- 2017-11-05 * minimize produced JSON in ToJSON instances
collection-json.cabal view
@@ -1,5 +1,5 @@ name: collection-json-version: 1.1.0.0+version: 1.1.0.1 synopsis: Collection+JSON—Hypermedia Type Tools description:@@ -27,7 +27,7 @@ source-repository head type: git- location: https://github.com/alunduil/collection+json.hs+ location: https://github.com/alunduil/collection-json.hs branch: develop library@@ -43,7 +43,7 @@ Data.CollectionJSON other-modules:- Internal.Network.URI.JSON+ External.Network.URI.JSON build-depends: aeson >= 0.8 && < 1.2@@ -71,10 +71,10 @@ Data.CollectionJSON , Data.CollectionJSON.Arbitrary , Data.CollectionJSONSpec- , Internal.Network.URI.Arbitrary- , Internal.Network.URI.ArbitrarySpec- , Internal.Network.URI.JSON- , Internal.Network.URI.JSONSpec+ , External.Network.URI.Arbitrary+ , External.Network.URI.ArbitrarySpec+ , External.Network.URI.JSON+ , External.Network.URI.JSONSpec build-tool-depends: hspec-discover:hspec-discover == 2.4.*
src/Data/CollectionJSON.hs view
@@ -20,7 +20,7 @@ import Data.Text (Text) import Network.URI (nullURI, URI) -import Internal.Network.URI.JSON ()+import External.Network.URI.JSON () -- * Core Data Types
+ src/External/Network/URI/JSON.hs view
@@ -0,0 +1,23 @@+{-# OPTIONS_GHC -fno-warn-orphans #-}++{-# LANGUAGE OverloadedStrings #-}++{-|+Module : External.Network.URI.JSON+Description : URI FromJSON and ToJSON Instances+Copyright : (c) Alex Brandt, 2017+License : MIT++URI Instances for FromJSON and ToJSON+-}+module External.Network.URI.JSON where++import Data.Aeson (FromJSON (parseJSON), ToJSON (toJSON), withText)+import Data.Text (unpack)+import Network.URI (parseURIReference, URI, uriToString)++instance FromJSON URI where+ parseJSON = withText "URI" $ maybe (fail "invalid URI") return . parseURIReference . unpack++instance ToJSON URI where+ toJSON u = toJSON $ uriToString id u ""
− src/Internal/Network/URI/JSON.hs
@@ -1,23 +0,0 @@-{-# OPTIONS_GHC -fno-warn-orphans #-}--{-# LANGUAGE OverloadedStrings #-}--{-|-Module : Internal.Network.URI.JSON-Description : URI FromJSON and ToJSON Instances-Copyright : (c) Alex Brandt, 2017-License : MIT--URI Instances for FromJSON and ToJSON--}-module Internal.Network.URI.JSON where--import Data.Aeson (FromJSON (parseJSON), ToJSON (toJSON), withText)-import Data.Text (unpack)-import Network.URI (parseURIReference, URI, uriToString)--instance FromJSON URI where- parseJSON = withText "URI" $ maybe (fail "invalid URI") return . parseURIReference . unpack--instance ToJSON URI where- toJSON u = toJSON $ uriToString id u ""
test/Data/CollectionJSON/Arbitrary.hs view
@@ -1,5 +1,7 @@ {-# OPTIONS_GHC -fno-warn-orphans #-} +{-# LANGUAGE RecordWildCards #-}+ {-| Module : Data.CollectionJSON.Arbitrary Description : Arbitrary Instances for Data.CollectionJSON@@ -12,11 +14,11 @@ import Control.Applicative ((<$>), (<*>)) import Data.Text (pack)-import Test.QuickCheck (Arbitrary (arbitrary))+import Test.QuickCheck (Arbitrary (arbitrary, shrink)) import Test.QuickCheck.Instances () import Data.CollectionJSON-import Internal.Network.URI.Arbitrary ()+import External.Network.URI.Arbitrary () instance Arbitrary Collection where arbitrary = Collection (pack "1.0") <$> arbitrary@@ -26,6 +28,8 @@ <*> arbitrary <*> arbitrary + shrink Collection{..} = [ Collection (pack "1.0") cHref' cLinks' cItems' cQueries' cTemplate' cError' | (cHref', cLinks', cItems', cQueries', cTemplate', cError') <- shrink (cHref, cLinks, cItems, cQueries, cTemplate, cError) ]+ instance Arbitrary Link where arbitrary = Link <$> arbitrary <*> arbitrary@@ -33,11 +37,15 @@ <*> arbitrary <*> arbitrary + shrink Link{..} = [ Link lHref' lRel' lName' lRender' lPrompt' | (lHref', lRel', lName', lRender', lPrompt') <- shrink (lHref, lRel, lName, lRender, lPrompt) ]+ instance Arbitrary Item where arbitrary = Item <$> arbitrary <*> arbitrary <*> arbitrary + shrink Item{..} = [ Item iHref' iData' iLinks' | (iHref', iData', iLinks') <- shrink (iHref, iData, iLinks) ]+ instance Arbitrary Query where arbitrary = Query <$> arbitrary <*> arbitrary@@ -45,15 +53,23 @@ <*> arbitrary <*> arbitrary + shrink Query{..} = [ Query qHref' qRel' qName' qPrompt' qData' | (qHref', qRel', qName', qPrompt', qData') <- shrink (qHref, qRel, qName, qPrompt, qData) ]+ instance Arbitrary Template where arbitrary = Template <$> arbitrary + shrink Template{..} = [ Template tData' | tData' <- shrink tData ]+ instance Arbitrary Error where arbitrary = Error <$> arbitrary <*> arbitrary <*> arbitrary + shrink Error{..} = [ Error eTitle' eCode' eMessage' | (eTitle', eCode', eMessage') <- shrink (eTitle, eCode, eMessage) ]+ instance Arbitrary Datum where arbitrary = Datum <$> arbitrary <*> arbitrary <*> arbitrary++ shrink Datum{..} = [ Datum dName' dValue' dPrompt' | (dName', dValue', dPrompt') <- shrink (dName, dValue, dPrompt) ]
test/Data/CollectionJSONSpec.hs view
@@ -29,11 +29,11 @@ spec = describe "application/vnd.collection+json" $ modifyMaxSize (const 25) $ do describe "RFC compliance (http://amundsen.com/media-types/collection/format/)" $- do prop "'Template' decode JSON string: \"{}\"" $ isJust (decode "{}" :: Maybe Template)- prop "'Collection' decode JSON string: \"{\"collection\":{}}\"" $ isJust (decode "{\"collection\":{}}" :: Maybe Collection) + do it "'Template' decode JSON string: \"{}\"" $ isJust (decode "{}" :: Maybe Template)+ it "'Collection' decode JSON string: \"{\"collection\":{}}\"" $ isJust (decode "{\"collection\":{}}" :: Maybe Collection) describe "common parse errors" $- prop "'Collection' errors on \"{}\"" $ isNothing (decode "{}" :: Maybe Collection)+ it "'Collection' errors on \"{}\"" $ isNothing (decode "{}" :: Maybe Collection) describe "properties" $ context "fromJust . decode . encode == id" $@@ -47,13 +47,13 @@ describe "JSON Missing Keys" $ do context "decode minimal JSON strings" $- do prop "Datum" $ isJust (decode mDatum :: Maybe Datum)- prop "Error" $ isJust (decode mError :: Maybe Error)- prop "Template" $ isJust (decode mTemplate :: Maybe Template)- prop "Query" $ isJust (decode mQuery :: Maybe Query)- prop "Item" $ isJust (decode mItem :: Maybe Item)- prop "Link" $ isJust (decode mLink :: Maybe Link)- prop "Collection" $ isJust (decode mCollection :: Maybe Collection)+ do it "Datum" $ isJust (decode mDatum :: Maybe Datum)+ it "Error" $ isJust (decode mError :: Maybe Error)+ it "Template" $ isJust (decode mTemplate :: Maybe Template)+ it "Query" $ isJust (decode mQuery :: Maybe Query)+ it "Item" $ isJust (decode mItem :: Maybe Item)+ it "Link" $ isJust (decode mLink :: Maybe Link)+ it "Collection" $ isJust (decode mCollection :: Maybe Collection) context "encode minimal data to JSON" $ do it "Datum" $
+ test/External/Network/URI/Arbitrary.hs view
@@ -0,0 +1,191 @@+{-# LANGUAGE RecordWildCards #-}++{-# OPTIONS_GHC -fno-warn-orphans #-}++{-|+Module : External.Network.URI.Arbitrary+Description : Arbitrary Instances for Network.URI+Copyright : (c) Alex Brandt, 2017+License : MIT++Arbitrary instances for "Network.URI".+-}+module External.Network.URI.Arbitrary () where++import Control.Applicative ((<$>), (<*>))+import Control.Monad (replicateM)+import Data.List (intercalate)+import Network.URI (URI (..), URIAuth (..))+import Test.QuickCheck (Arbitrary (arbitrary, shrink), choose, elements, Gen, listOf, listOf1, oneof, suchThat)++instance Arbitrary URI where+ arbitrary =+ do uriScheme <- scheme+ uriAuthority <- arbitrary :: Gen (Maybe URIAuth)+ uriPath <- path (null uriScheme) $ maybe True emptyAuthority uriAuthority+ uriQuery <- oneof [query, return ""]+ uriFragment <- oneof [fragment, return ""]++ return URI {..}+ where emptyAuthority URIAuth{..} = all null [uriUserInfo, uriRegName, uriPort]++ shrink URI{..} = [ URI uriScheme' uriAuthority' uriPath' uriQuery' uriFragment' | (uriScheme', uriAuthority', uriPath', uriQuery', uriFragment') <- shrink (uriScheme, uriAuthority, uriPath, uriQuery, uriFragment) ]++instance Arbitrary URIAuth where+ arbitrary = URIAuth <$> userinfo+ <*> host `suchThat` (not . null)+ <*> port++ shrink URIAuth{..} = [ URIAuth uriUserInfo' uriRegName' uriPort' | (uriUserInfo', uriRegName', uriPort') <- shrink (uriUserInfo, uriRegName, uriPort) ]++-- * RFC 3986 Generators+--+-- Some generators are handled by the 'Arbitrary' instances above, and others+-- are folded into symbols that are preceeded or followed by identifying+-- tokens.++scheme :: Gen String+scheme =+ do a <- alpha+ r <- listOf $ oneof [alpha, digit, elements ['+', '-', '.']]+ return $ a : (r ++ ":")++userinfo :: Gen String+userinfo =+ do u <- concat <$> userinfo'+ if null u+ then return ""+ else return $ u ++ "@"+ where userinfo' = listOf $ oneof [ replicateM 1 $ oneof [unreserved, subDelims, return ':']+ , percentEncoded+ ]++host :: Gen String+host = oneof [ ipLiteral+ , ipv4Address+ , regName+ ]++port :: Gen String+port =+ do p <- listOf digit+ if null p+ then return ""+ else return $ ':':p++ipLiteral :: Gen String+ipLiteral =+ do x <- oneof [ ipv6Address+ --, ipvFuture+ ]+ return $ "[" ++ x ++ "]"++{- TODO Check that "Network.URI" implements this correctly.+ipvFuture :: Gen String+ipvFuture =+ do h <- hexdig+ o <- oneof [ unreserved, subDelims, return ':' ]+ return ['v', h, '.', o]+-}++ipv6Address :: Gen String+ipv6Address = concat <$> oneof [ sequence [b 6, ls32]+ , sequence [return "::", b 5, ls32]+ , sequence [h16, return "::", b 4, ls32]+ , sequence [b 1, h16, return "::", b 3, ls32]+ , sequence [b 2, h16, return "::", b 2, ls32]+ , sequence [b 3, h16, return "::", b 1, ls32]+ , sequence [b 4, h16, return "::", ls32]+ , sequence [b 5, h16, return "::", h16]+ , sequence [b 6, h16, return "::"]+ ]+ where b n = fmap concat $ replicateM n $ fmap (++ ":") h16 :: Gen String++h16 :: Gen String+h16 = replicateM 4 hexdig++ls32 :: Gen String+ls32 = oneof [ intercalate ":" <$> replicateM 2 h16+ , ipv4Address+ ]++ipv4Address :: Gen String+ipv4Address = intercalate "." <$> replicateM 4 decOctet++decOctet :: Gen String+decOctet = (show :: Int -> String) <$> choose (0, 255)++regName :: Gen String+regName = fmap concat $ listOf $ oneof [ replicateM 1 unreserved+ , percentEncoded+ , replicateM 1 subDelims+ ]++path :: Bool -> Bool -> Gen String+path emptyScheme emptyURIAuth = if emptyURIAuth+ then oneof [ pathAbsolute+ , if emptyScheme then pathNoScheme else pathRootless+ , return ""+ ]+ else pathAbEmpty++pathAbEmpty :: Gen String+pathAbEmpty = concat <$> listOf ((('/':) . concat) <$> listOf pchar)++pathAbsolute :: Gen String+pathAbsolute = ('/':) <$> oneof [return "", pathRootless]++pathNoScheme :: Gen String+pathNoScheme = concat <$> sequence [segment1nc, pathAbEmpty]++pathRootless :: Gen String+pathRootless = concat <$> sequence [ concat <$> listOf1 pchar+ , pathAbEmpty+ ]++segment1nc :: Gen String+segment1nc = oneof [ replicateM 1 unreserved+ , percentEncoded+ , replicateM 1 subDelims+ , replicateM 1 $ return '@'+ ] ++pchar :: Gen String+pchar = oneof [ replicateM 1 unreserved+ , percentEncoded+ , replicateM 1 subDelims+ , replicateM 1 $ return ':'+ , replicateM 1 $ return '@'+ ]++query :: Gen String+query = fmap (('?':) . concat) $ listOf $ oneof [ pchar+ , return "/"+ , return "?"+ ]++fragment :: Gen String+fragment = fmap (('#':) . concat) $ listOf $ oneof [ pchar+ , return "/"+ , return "?"+ ]++percentEncoded :: Gen String+percentEncoded = ('%':) <$> replicateM 2 hexdig++unreserved :: Gen Char+unreserved = oneof [ alpha, digit, elements ['-', '.', '_', '~']]++subDelims :: Gen Char+subDelims = elements ['!', '$', '&', '\'', '(', ')', '*', '+', ',', ';', '=']++-- * RFC 2234 Generators++alpha :: Gen Char+alpha = elements $ ['a'..'z'] ++ ['A'..'Z']++digit :: Gen Char+digit = elements ['0'..'9']++hexdig :: Gen Char+hexdig = oneof [digit, elements ['A'..'F']]
+ test/External/Network/URI/ArbitrarySpec.hs view
@@ -0,0 +1,25 @@+{-|+Module : External.Network.URI.ArbitrarySpec+Description : Tests for External.Network.URI.Arbitrary+Copyright : (c) Alex Brandt, 2017+License : MIT++Tests for "External.Network.URI.Arbitrary".+-}+module External.Network.URI.ArbitrarySpec (main, spec) where++import Network.URI (isURIReference, parseURIReference, uriToString)+import Test.Hspec (describe, hspec, Spec)+import Test.Hspec.QuickCheck (prop)++import External.Network.URI.Arbitrary ()++main :: IO ()+main = hspec spec++spec :: Spec+spec =+ describe "properties" $+ do prop "isURIReference (uriToString id u \"\")" $ \ u -> isURIReference (uriToString id u "")++ prop "Just u == parseURIReference (uriToString id u \"\")" $ \ u -> Just u == parseURIReference (uriToString id u "")
+ test/External/Network/URI/JSONSpec.hs view
@@ -0,0 +1,27 @@+{-|+Module : External.Network.URI.JSONSpec+Description : Tests for External.Network.URI.JSON+Copyright : (c) Alex Brandt, 2017+License : MIT++Tests for "External.Network.URI.JSON".+-}+module External.Network.URI.JSONSpec (main, spec) where++import Data.Aeson (decode, encode)+import Data.Maybe (fromJust)+import Network.URI (URI)+import Test.Hspec (describe, hspec, Spec)+import Test.Hspec.QuickCheck (prop)+import Test.Invariant ((<=>))++import External.Network.URI.Arbitrary ()+import External.Network.URI.JSON ()++main :: IO ()+main = hspec spec++spec :: Spec+spec =+ describe "properties" $+ prop "fromJust . decode . encode == id" (fromJust . decode . encode <=> id :: URI -> Bool)
− test/Internal/Network/URI/Arbitrary.hs
@@ -1,187 +0,0 @@-{-# LANGUAGE RecordWildCards #-}--{-# OPTIONS_GHC -fno-warn-orphans #-}--{-|-Module : Internal.Network.URI.Arbitrary-Description : Arbitrary Instances for Network.URI-Copyright : (c) Alex Brandt, 2017-License : MIT--Arbitrary instances for "Network.URI".--}-module Internal.Network.URI.Arbitrary () where--import Control.Applicative ((<$>), (<*>))-import Control.Monad (replicateM)-import Data.List (intercalate)-import Network.URI (URI (..), URIAuth (..))-import Test.QuickCheck (Arbitrary (arbitrary), choose, elements, Gen, listOf, listOf1, oneof, suchThat)--instance Arbitrary URI where- arbitrary =- do uriScheme <- scheme- uriAuthority <- arbitrary :: Gen (Maybe URIAuth)- uriPath <- path (null uriScheme) $ maybe True emptyAuthority uriAuthority- uriQuery <- oneof [query, return ""]- uriFragment <- oneof [fragment, return ""]-- return URI {..}- where emptyAuthority URIAuth{..} = all null [uriUserInfo, uriRegName, uriPort]--instance Arbitrary URIAuth where- arbitrary = URIAuth <$> userinfo- <*> host `suchThat` (not . null)- <*> port---- * RFC 3986 Generators------ Some generators are handled by the 'Arbitrary' instances above, and others--- are folded into symbols that are preceeded or followed by identifying--- tokens.--scheme :: Gen String-scheme =- do a <- alpha- r <- listOf $ oneof [alpha, digit, elements ['+', '-', '.']]- return $ a : (r ++ ":")--userinfo :: Gen String-userinfo =- do u <- concat <$> userinfo'- if null u- then return ""- else return $ u ++ "@"- where userinfo' = listOf $ oneof [ replicateM 1 $ oneof [unreserved, subDelims, return ':']- , percentEncoded- ]--host :: Gen String-host = oneof [ ipLiteral- , ipv4Address- , regName- ]--port :: Gen String-port =- do p <- listOf digit- if null p- then return ""- else return $ ':':p--ipLiteral :: Gen String-ipLiteral =- do x <- oneof [ ipv6Address- --, ipvFuture- ]- return $ "[" ++ x ++ "]"--{- TODO Check that "Network.URI" implements this correctly.-ipvFuture :: Gen String-ipvFuture =- do h <- hexdig- o <- oneof [ unreserved, subDelims, return ':' ]- return ['v', h, '.', o]--}--ipv6Address :: Gen String-ipv6Address = concat <$> oneof [ sequence [b 6, ls32]- , sequence [return "::", b 5, ls32]- , sequence [h16, return "::", b 4, ls32]- , sequence [b 1, h16, return "::", b 3, ls32]- , sequence [b 2, h16, return "::", b 2, ls32]- , sequence [b 3, h16, return "::", b 1, ls32]- , sequence [b 4, h16, return "::", ls32]- , sequence [b 5, h16, return "::", h16]- , sequence [b 6, h16, return "::"]- ]- where b n = fmap concat $ replicateM n $ fmap (++ ":") h16 :: Gen String--h16 :: Gen String-h16 = replicateM 4 hexdig--ls32 :: Gen String-ls32 = oneof [ intercalate ":" <$> replicateM 2 h16- , ipv4Address- ]--ipv4Address :: Gen String-ipv4Address = intercalate "." <$> replicateM 4 decOctet--decOctet :: Gen String-decOctet = (show :: Int -> String) <$> choose (0, 255)--regName :: Gen String-regName = fmap concat $ listOf $ oneof [ replicateM 1 unreserved- , percentEncoded- , replicateM 1 subDelims- ]--path :: Bool -> Bool -> Gen String-path emptyScheme emptyURIAuth = if emptyURIAuth- then oneof [ pathAbsolute- , if emptyScheme then pathNoScheme else pathRootless- , return ""- ]- else pathAbEmpty--pathAbEmpty :: Gen String-pathAbEmpty = concat <$> listOf ((('/':) . concat) <$> listOf pchar)--pathAbsolute :: Gen String-pathAbsolute = ('/':) <$> oneof [return "", pathRootless]--pathNoScheme :: Gen String-pathNoScheme = concat <$> sequence [segment1nc, pathAbEmpty]--pathRootless :: Gen String-pathRootless = concat <$> sequence [ concat <$> listOf1 pchar- , pathAbEmpty- ]--segment1nc :: Gen String-segment1nc = oneof [ replicateM 1 unreserved- , percentEncoded- , replicateM 1 subDelims- , replicateM 1 $ return '@'- ] --pchar :: Gen String-pchar = oneof [ replicateM 1 unreserved- , percentEncoded- , replicateM 1 subDelims- , replicateM 1 $ return ':'- , replicateM 1 $ return '@'- ]--query :: Gen String-query = fmap (('?':) . concat) $ listOf $ oneof [ pchar- , return "/"- , return "?"- ]--fragment :: Gen String-fragment = fmap (('#':) . concat) $ listOf $ oneof [ pchar- , return "/"- , return "?"- ]--percentEncoded :: Gen String-percentEncoded = ('%':) <$> replicateM 2 hexdig--unreserved :: Gen Char-unreserved = oneof [ alpha, digit, elements ['-', '.', '_', '~']]--subDelims :: Gen Char-subDelims = elements ['!', '$', '&', '\'', '(', ')', '*', '+', ',', ';', '=']---- * RFC 2234 Generators--alpha :: Gen Char-alpha = elements $ ['a'..'z'] ++ ['A'..'Z']--digit :: Gen Char-digit = elements ['0'..'9']--hexdig :: Gen Char-hexdig = oneof [digit, elements ['A'..'F']]
− test/Internal/Network/URI/ArbitrarySpec.hs
@@ -1,25 +0,0 @@-{-|-Module : Internal.Network.URI.ArbitrarySpec-Description : Tests for Internal.Network.URI.Arbitrary-Copyright : (c) Alex Brandt, 2017-License : MIT--Tests for "Internal.Network.URI.Arbitrary".--}-module Internal.Network.URI.ArbitrarySpec (main, spec) where--import Network.URI (isURIReference, parseURIReference, uriToString)-import Test.Hspec (describe, hspec, Spec)-import Test.Hspec.QuickCheck (prop)--import Internal.Network.URI.Arbitrary ()--main :: IO ()-main = hspec spec--spec :: Spec-spec =- describe "properties" $- do prop "isURIReference (uriToString id u \"\")" $ \ u -> isURIReference (uriToString id u "")-- prop "Just u == parseURIReference (uriToString id u \"\")" $ \ u -> Just u == parseURIReference (uriToString id u "")
− test/Internal/Network/URI/JSONSpec.hs
@@ -1,27 +0,0 @@-{-|-Module : Internal.Network.URI.JSONSpec-Description : Tests for Internal.Network.URI.JSON-Copyright : (c) Alex Brandt, 2017-License : MIT--Tests for "Internal.Network.URI.JSON".--}-module Internal.Network.URI.JSONSpec (main, spec) where--import Data.Aeson (decode, encode)-import Data.Maybe (fromJust)-import Network.URI (URI)-import Test.Hspec (describe, hspec, Spec)-import Test.Hspec.QuickCheck (prop)-import Test.Invariant ((<=>))--import Internal.Network.URI.Arbitrary ()-import Internal.Network.URI.JSON ()--main :: IO ()-main = hspec spec--spec :: Spec-spec =- describe "properties" $- prop "fromJust . decode . encode == id" (fromJust . decode . encode <=> id :: URI -> Bool)