@@ -8,17 +8,21 @@ import Data.Argonaut.Core as J
8
8
import Data.Argonaut.Gen (genJson )
9
9
import Data.Char.Gen (genAsciiChar )
10
10
import 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 )
12
13
import Data.Generic.Rep (class Generic )
14
+ import Data.Int as Int
13
15
import Data.Maybe (Maybe (..))
16
+ import Data.Maybe (Maybe (..), maybe )
14
17
import Data.Newtype (class Newtype , unwrap , wrap )
15
18
import Data.Profunctor (dimap )
16
19
import Data.Show.Generic (genericShow )
17
20
import Data.String.Gen (genAsciiString )
18
21
import Effect (Effect )
19
22
import Effect.Console (log )
23
+ import Foreign.Object as Object
20
24
import Foreign.Object.Gen (genForeignObject )
21
- import Test.QuickCheck (Result , quickCheck )
25
+ import Test.QuickCheck (Result (..) , quickCheck )
22
26
import Test.QuickCheck.Gen (Gen )
23
27
import Test.Util (genInt , propCodec , propCodec' , propCodec'' )
24
28
import Type.Proxy (Proxy (..))
@@ -43,8 +47,8 @@ main = do
43
47
log " Checking Char codec"
44
48
quickCheck propChar
45
49
46
- log " Checking JArray codec"
47
- quickCheck propJArray
50
+ log " Checking CArray codec"
51
+ quickCheck propCArray
48
52
49
53
log " Checking JObject codec"
50
54
quickCheck propJObject
@@ -55,32 +59,41 @@ main = do
55
59
log " Checking record codec"
56
60
quickCheck (propTestRecord codecRecord)
57
61
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
+
58
71
log " Checking fixed-point codec"
59
72
quickCheck propFix
60
73
61
74
propNull ∷ Gen Result
62
- propNull = propCodec (pure unit) JA .null
75
+ propNull = propCodec (pure unit) CA .null
63
76
64
77
propBoolean ∷ Gen Result
65
- propBoolean = propCodec Gen .chooseBool JA .boolean
78
+ propBoolean = propCodec Gen .chooseBool CA .boolean
66
79
67
80
propNumber ∷ Gen Result
68
- propNumber = propCodec (Gen .chooseFloat (-100000.0 ) 100000.0 ) JA .number
81
+ propNumber = propCodec (Gen .chooseFloat (-100000.0 ) 100000.0 ) CA .number
69
82
70
83
propInt ∷ Gen Result
71
- propInt = propCodec genInt JA .int
84
+ propInt = propCodec genInt CA .int
72
85
73
86
propString ∷ Gen Result
74
- propString = propCodec genAsciiString JA .string
87
+ propString = propCodec genAsciiString CA .string
75
88
76
89
propChar ∷ Gen Result
77
- propChar = propCodec genAsciiChar JA .char
90
+ propChar = propCodec genAsciiChar CA .char
78
91
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
81
94
82
95
propJObject ∷ 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
84
97
85
98
type TestRecord = { tag ∷ String , x ∷ Int , y ∷ Boolean }
86
99
@@ -91,28 +104,73 @@ genRecord =
91
104
<*> genInt
92
105
<*> Gen .chooseBool
93
106
94
- codecObject ∷ JA .JsonCodec TestRecord
107
+ codecObject ∷ CA .JsonCodec TestRecord
95
108
codecObject =
96
- JA .object " Test Object" $
109
+ CA .object " Test Object" $
97
110
{ 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
101
114
102
- codecRecord ∷ JA .JsonCodec TestRecord
115
+ codecRecord ∷ CA .JsonCodec TestRecord
103
116
codecRecord =
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
108
121
109
- propTestRecord ∷ JA .JsonCodec TestRecord → Gen Result
122
+ propTestRecord ∷ CA .JsonCodec TestRecord → Gen Result
110
123
propTestRecord = propCodec' checkEq print genRecord
111
124
where
112
125
checkEq r1 r2 = r1.tag == r2.tag && r1.x == r2.x && r1.y == r2.y
113
126
print { tag, x, y } =
114
127
" { tag: " <> show tag <> " , x: " <> show x <> " , y: " <> show y <> " }"
115
128
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
+
116
174
newtype FixTest = FixTest (Maybe FixTest )
117
175
118
176
derive instance newtypeFixTest ∷ Newtype FixTest _
@@ -128,9 +186,9 @@ genFixTest = Gen.sized \n →
128
186
if n <= 1 then pure $ FixTest Nothing
129
187
else FixTest <$> Gen .resize (_ - 1 ) (GenC .genMaybe genFixTest)
130
188
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)
134
192
135
193
propFix ∷ Gen Result
136
194
propFix = propCodec genFixTest codecFixTest
0 commit comments