@@ -9,6 +9,7 @@ import Data.Time
99import qualified Data.Text as T
1010import qualified Data.Text.Lazy as L
1111import qualified Data.ByteString as BS
12+import Data.ByteString.Builder (toLazyByteString)
1213import Data.Version
1314import qualified Data.UUID as UUID
1415
@@ -29,6 +30,10 @@ import Web.Internal.TestInstances
2930(<=>) :: Eq a => (a -> b) -> (b -> Either T.Text a) -> a -> Bool
3031(f <=> g) x = g (f x) == Right x
3132
33+encodedUrlPieceProp :: ToHttpApiData a => a -> Bool
34+encodedUrlPieceProp x = toLazyByteString (toEncodedUrlPiece (toUrlPiece x)) == toLazyByteString (toEncodedUrlPiece x)
35+
36+
3237checkUrlPiece :: forall a. (Eq a, ToHttpApiData a, FromHttpApiData a, Show a, Arbitrary a) => Proxy a -> String -> Spec
3338checkUrlPiece _ name = prop name (toUrlPiece <=> parseUrlPiece :: a -> Bool)
3439
@@ -40,6 +45,15 @@ checkUrlPiece' gen name = prop name $ forAll gen (toUrlPiece <=> parseUrlPiece)
4045checkUrlPieceI :: forall a. (Eq a, ToHttpApiData a, FromHttpApiData a, Arbitrary a) => Proxy a -> String -> Spec
4146checkUrlPieceI _ = checkUrlPiece (Proxy :: Proxy (RandomCase a))
4247
48+-- | Check that 'toEncodedUrlPiece' is equivallent to default implementation.
49+checkEncodedUrlPiece :: forall a. (Show a, ToHttpApiData a, Arbitrary a) => Proxy a -> String -> Spec
50+checkEncodedUrlPiece _ = checkEncodedUrlPiece' (arbitrary :: Gen a)
51+
52+-- | Check that 'toEncodedUrlPiece' is equivallent to default implementation.
53+-- Use a given generator.
54+checkEncodedUrlPiece' :: forall a. (Show a, ToHttpApiData a) => Gen a -> String -> Spec
55+checkEncodedUrlPiece' gen name = prop name $ forAll gen encodedUrlPieceProp
56+
4357spec :: Spec
4458spec = do
4559 describe "toUrlPiece <=> parseUrlPiece" $ do
@@ -78,6 +92,42 @@ spec = do
7892 checkUrlPiece (Proxy :: Proxy Natural) "Natural"
7993#endif
8094
95+ describe "toEncodedUrlPiece encodes correctly" $ do
96+ checkEncodedUrlPiece (Proxy :: Proxy ()) "()"
97+ checkEncodedUrlPiece (Proxy :: Proxy Char) "Char"
98+ checkEncodedUrlPiece (Proxy :: Proxy Bool) "Bool"
99+ checkEncodedUrlPiece (Proxy :: Proxy Ordering) "Ordering"
100+ checkEncodedUrlPiece (Proxy :: Proxy Int) "Int"
101+ checkEncodedUrlPiece (Proxy :: Proxy Int8) "Int8"
102+ checkEncodedUrlPiece (Proxy :: Proxy Int16) "Int16"
103+ checkEncodedUrlPiece (Proxy :: Proxy Int32) "Int32"
104+ checkEncodedUrlPiece (Proxy :: Proxy Int64) "Int64"
105+ checkEncodedUrlPiece (Proxy :: Proxy Integer) "Integer"
106+ checkEncodedUrlPiece (Proxy :: Proxy Word) "Word"
107+ checkEncodedUrlPiece (Proxy :: Proxy Word8) "Word8"
108+ checkEncodedUrlPiece (Proxy :: Proxy Word16) "Word16"
109+ checkEncodedUrlPiece (Proxy :: Proxy Word32) "Word32"
110+ checkEncodedUrlPiece (Proxy :: Proxy Word64) "Word64"
111+ checkEncodedUrlPiece (Proxy :: Proxy String) "String"
112+ checkEncodedUrlPiece (Proxy :: Proxy T.Text) "Text.Strict"
113+ checkEncodedUrlPiece (Proxy :: Proxy L.Text) "Text.Lazy"
114+ checkEncodedUrlPiece (Proxy :: Proxy Day) "Day"
115+ checkEncodedUrlPiece' localTimeGen "LocalTime"
116+ checkEncodedUrlPiece' zonedTimeGen "ZonedTime"
117+ checkEncodedUrlPiece' utcTimeGen "UTCTime"
118+ checkEncodedUrlPiece' nominalDiffTimeGen "NominalDiffTime"
119+ checkEncodedUrlPiece (Proxy :: Proxy Version) "Version"
120+ checkEncodedUrlPiece' uuidGen "UUID"
121+
122+ checkEncodedUrlPiece (Proxy :: Proxy (Maybe String)) "Maybe String"
123+ checkEncodedUrlPiece (Proxy :: Proxy (Maybe Integer)) "Maybe Integer"
124+ checkEncodedUrlPiece (Proxy :: Proxy (Either Integer T.Text)) "Either Integer Text"
125+ checkEncodedUrlPiece (Proxy :: Proxy (Either Version Day)) "Either Version Day"
126+
127+#if MIN_VERSION_base(4,8,0)
128+ checkEncodedUrlPiece (Proxy :: Proxy Natural) "Natural"
129+#endif
130+
81131 it "bad integers are rejected" $ do
82132 parseUrlPieceMaybe (T.pack "123hello") `shouldBe` (Nothing :: Maybe Int)
83133
@@ -88,6 +138,7 @@ spec = do
88138 it "invalid utf8 is handled" $ do
89139 parseHeaderMaybe (BS.pack [128]) `shouldBe` (Nothing :: Maybe T.Text)
90140
141+
91142uuidGen :: Gen UUID.UUID
92143uuidGen = UUID.fromWords <$> arbitrary <*> arbitrary <*> arbitrary <*> arbitrary
93144