@@ -8,17 +8,21 @@ import Data.Argonaut.Core as J
88import Data.Argonaut.Gen (genJson )
99import Data.Char.Gen (genAsciiChar )
1010import Data.Codec.Argonaut.Common ((~))
11- import Data.Codec.Argonaut.Common as JA
11+ import Data.Codec.Argonaut.Common as CA
12+ import Data.Either (Either (..), either , note )
1213import Data.Generic.Rep (class Generic )
14+ import Data.Int as Int
1315import Data.Maybe (Maybe (..))
16+ import Data.Maybe (Maybe (..), maybe )
1417import Data.Newtype (class Newtype , unwrap , wrap )
1518import Data.Profunctor (dimap )
1619import Data.Show.Generic (genericShow )
1720import Data.String.Gen (genAsciiString )
1821import Effect (Effect )
1922import Effect.Console (log )
23+ import Foreign.Object as Object
2024import Foreign.Object.Gen (genForeignObject )
21- import Test.QuickCheck (Result , quickCheck )
25+ import Test.QuickCheck (Result (..) , quickCheck )
2226import Test.QuickCheck.Gen (Gen )
2327import Test.Util (genInt , propCodec , propCodec' , propCodec'' )
2428import Type.Proxy (Proxy (..))
@@ -43,8 +47,8 @@ main = do
4347 log " Checking Char codec"
4448 quickCheck propChar
4549
46- log " Checking JArray codec"
47- quickCheck propJArray
50+ log " Checking CArray codec"
51+ quickCheck propCArray
4852
4953 log " Checking JObject codec"
5054 quickCheck propJObject
@@ -55,32 +59,41 @@ main = do
5559 log " Checking record codec"
5660 quickCheck (propTestRecord codecRecord)
5761
62+ log " Checking record codec with optional field"
63+ quickCheck propTestRecordOptional
64+
65+ log " Checking record codec with optional field does include the field"
66+ quickCheck propPresentOptionalField
67+
68+ log " Checking record codec with optional field does omit the field entirely"
69+ quickCheck propMissingOptionalField
70+
5871 log " Checking fixed-point codec"
5972 quickCheck propFix
6073
6174propNull ∷ Gen Result
62- propNull = propCodec (pure unit) JA .null
75+ propNull = propCodec (pure unit) CA .null
6376
6477propBoolean ∷ Gen Result
65- propBoolean = propCodec Gen .chooseBool JA .boolean
78+ propBoolean = propCodec Gen .chooseBool CA .boolean
6679
6780propNumber ∷ Gen Result
68- propNumber = propCodec (Gen .chooseFloat (-100000.0 ) 100000.0 ) JA .number
81+ propNumber = propCodec (Gen .chooseFloat (-100000.0 ) 100000.0 ) CA .number
6982
7083propInt ∷ Gen Result
71- propInt = propCodec genInt JA .int
84+ propInt = propCodec genInt CA .int
7285
7386propString ∷ Gen Result
74- propString = propCodec genAsciiString JA .string
87+ propString = propCodec genAsciiString CA .string
7588
7689propChar ∷ Gen Result
77- propChar = propCodec genAsciiChar JA .char
90+ propChar = propCodec genAsciiChar CA .char
7891
79- propJArray ∷ Gen Result
80- propJArray = propCodec'' (show <<< map J .stringify) (Gen .unfoldable genJson) JA .jarray
92+ propCArray ∷ Gen Result
93+ propCArray = propCodec'' (show <<< map J .stringify) (Gen .unfoldable genJson) CA .jarray
8194
8295propJObject ∷ Gen Result
83- propJObject = propCodec'' (show <<< map J .stringify) (genForeignObject genAsciiString genJson) JA .jobject
96+ propJObject = propCodec'' (show <<< map J .stringify) (genForeignObject genAsciiString genJson) CA .jobject
8497
8598type TestRecord = { tag ∷ String , x ∷ Int , y ∷ Boolean }
8699
@@ -91,28 +104,73 @@ genRecord =
91104 <*> genInt
92105 <*> Gen .chooseBool
93106
94- codecObject ∷ JA .JsonCodec TestRecord
107+ codecObject ∷ CA .JsonCodec TestRecord
95108codecObject =
96- JA .object " Test Object" $
109+ CA .object " Test Object" $
97110 { tag: _, x: _, y: _ }
98- <$> _.tag ~ JA .prop " tag" JA .string
99- <*> _.x ~ JA .prop " x" JA .int
100- <*> _.y ~ JA .prop " y" JA .boolean
111+ <$> _.tag ~ CA .prop " tag" CA .string
112+ <*> _.x ~ CA .prop " x" CA .int
113+ <*> _.y ~ CA .prop " y" CA .boolean
101114
102- codecRecord ∷ JA .JsonCodec TestRecord
115+ codecRecord ∷ CA .JsonCodec TestRecord
103116codecRecord =
104- JA .object " Test Record" $ JA .record
105- # JA .recordProp (Proxy ∷ Proxy " tag" ) JA .string
106- # JA .recordProp (Proxy ∷ Proxy " x" ) JA .int
107- # JA .recordProp (Proxy ∷ Proxy " y" ) JA .boolean
117+ CA .object " Test Record" $ CA .record
118+ # CA .recordProp (Proxy ∷ Proxy " tag" ) CA .string
119+ # CA .recordProp (Proxy ∷ Proxy " x" ) CA .int
120+ # CA .recordProp (Proxy ∷ Proxy " y" ) CA .boolean
108121
109- propTestRecord ∷ JA .JsonCodec TestRecord → Gen Result
122+ propTestRecord ∷ CA .JsonCodec TestRecord → Gen Result
110123propTestRecord = propCodec' checkEq print genRecord
111124 where
112125 checkEq r1 r2 = r1.tag == r2.tag && r1.x == r2.x && r1.y == r2.y
113126 print { tag, x, y } =
114127 " { tag: " <> show tag <> " , x: " <> show x <> " , y: " <> show y <> " }"
115128
129+ type TestRecordOptional = { tag ∷ String , x ∷ Maybe Int }
130+
131+ genRecordOptional ∷ Gen TestRecordOptional
132+ genRecordOptional =
133+ { tag: _, x: _ }
134+ <$> genAsciiString
135+ <*> GenC .genMaybe genInt
136+
137+ codecRecordOptional ∷ CA.JsonCodec TestRecordOptional
138+ codecRecordOptional =
139+ CA .object " Test record with optional field" $ CA .record
140+ # CA .recordProp (Proxy ∷ Proxy " tag" ) CA .string
141+ # CA .recordPropOptional (Proxy ∷ Proxy " x" ) CA .int
142+
143+ propTestRecordOptional ∷ Gen Result
144+ propTestRecordOptional = propCodec' checkEq print genRecordOptional codecRecordOptional
145+ where
146+ checkEq r1 r2 = r1.tag == r2.tag && r1.x == r2.x
147+ print { tag, x } =
148+ case x of
149+ Just _ → " { tag: " <> show tag <> " , x: " <> show x <> " }"
150+ Nothing → " { tag: " <> show tag <> " }"
151+
152+ propPresentOptionalField ∷ Gen Result
153+ propPresentOptionalField = do
154+ tag ← genAsciiString
155+ x ← genInt
156+ let value = { tag, x: Just x }
157+ let json = CA .encode codecRecordOptional value
158+ pure $ either Failed (pure Success ) do
159+ obj ← note " Encoded JSON is not an object" $ J .toObject json
160+ prop ← note " Optional property unexpectedly missing in object" $ Object .lookup " x" obj
161+ n ← note " x value is not a plain number" $ J .toNumber prop
162+ if n == Int .toNumber x then pure unit
163+ else Left " x value is wrong"
164+
165+ propMissingOptionalField ∷ Gen Result
166+ propMissingOptionalField = do
167+ tag ← genAsciiString
168+ let value = { tag, x: Nothing }
169+ let json = CA .encode codecRecordOptional value
170+ pure $ either Failed (pure Success ) do
171+ obj ← note " Encoded JSON is not an object" $ J .toObject json
172+ maybe (Right Success ) (\_ → Left " Optional property unexpectedly appeared in object" ) $ Object .lookup " x" obj
173+
116174newtype FixTest = FixTest (Maybe FixTest )
117175
118176derive instance newtypeFixTest ∷ Newtype FixTest _
@@ -128,9 +186,9 @@ genFixTest = Gen.sized \n →
128186 if n <= 1 then pure $ FixTest Nothing
129187 else FixTest <$> Gen .resize (_ - 1 ) (GenC .genMaybe genFixTest)
130188
131- codecFixTest ∷ JA .JsonCodec FixTest
132- codecFixTest = JA .fix \codec →
133- dimap unwrap wrap (JA .maybe codec)
189+ codecFixTest ∷ CA .JsonCodec FixTest
190+ codecFixTest = CA .fix \codec →
191+ dimap unwrap wrap (CA .maybe codec)
134192
135193propFix ∷ Gen Result
136194propFix = propCodec genFixTest codecFixTest
0 commit comments