on master help sign in
Add ISO8601 and UUID regex helpers, move to regex-tdfa
commit870bf5d422fa93fbb3a901e3d51ae1f67c0810fa authorDenis Redozubov <denis.redozubov@gmail.com> dateThu 28 Sep 2017, 23:21 (9 years ago) parent91db48c
5 files changed+88−7
schematic.cabal+6−2 src/Data/Schematic.hs+3−1 src/Data/Schematic/Helpers.hs+13 src/Data/Schematic/Validation.hs+4−4 test/HelpersSpec.hs+62
schematic.cabal+6−2
@@ -16,6 +16,7 @@ library
1616 exposed-modules: Data.Schematic
1717 , Data.Schematic.Instances
1818 , Data.Schematic.JsonSchema
19+ , Data.Schematic.Helpers
1920 , Data.Schematic.Lens
2021 , Data.Schematic.Migration
2122 , Data.Schematic.Path
@@ -62,7 +63,8 @@ library
6263 , containers
6364 , hjsonschema
6465 , mtl
65− , regex-compat
66+ , regex-tdfa
67+ , regex-tdfa-text
6668 , scientific
6769 , singletons >= 2.2
6870 , smallcheck
@@ -118,7 +120,8 @@ test-suite spec
118120 , hspec-discover
119121 , hspec-smallcheck
120122 , lens
121− , regex-compat
123+ , regex-tdfa
124+ , regex-tdfa-text
122125 , schematic
123126 , smallcheck
124127 , singletons
@@ -128,5 +131,6 @@ test-suite spec
128131 , validationt >= 0.1.0.1
129132 , vinyl
130133 other-modules: SchemaSpec
134+ , HelpersSpec
131135 , LensSpec
132136 , JsonSchemaSpec
src/Data/Schematic.hs+3−1
@@ -3,9 +3,10 @@
33
44module Data.Schematic
55 ( module Data.Schematic.JsonSchema
6− , module Data.Schematic.Schema
6+ , module Data.Schematic.Helpers
77 , module Data.Schematic.Lens
88 , module Data.Schematic.Migration
9+ , module Data.Schematic.Schema
910 , module Data.Schematic.Utils
1011 , decodeAndValidateJson
1112 , parseAndValidateJson
@@ -26,6 +27,7 @@ import Data.Aeson.Types as J
2627import Data.ByteString.Lazy as BL
2728import Data.Functor.Identity
2829import Data.Schematic.JsonSchema
30+import Data.Schematic.Helpers
2931import Data.Schematic.Lens
3032import Data.Schematic.Migration
3133import Data.Schematic.Schema
src/Data/Schematic/Helpers.hsnew file+13
@@ -0,0 +1,13 @@
1+module Data.Schematic.Helpers where
2+
3+import Data.Schematic.Schema
4+
5+type UUIDRegex =
6+ 'TRegex "[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}"
7+
8+type IsUUID = '[UUIDRegex]
9+
10+type ISO8601Regex =
11+ 'TRegex "(\\d{4}-[01]\\d-[0-3]\\dT[0-2]\\d:[0-5]\\d:[0-5]\\d\\.\\d+([+-][0-2]\\d:[0-5]\\d|Z))|(\\d{4}-[01]\\d-[0-3]\\dT[0-2]\\d:[0-5]\\d:[0-5]\\d([+-][0-2]\\d:[0-5]\\d|Z))|(\\d{4}-[01]\\d-[0-3]\\dT[0-2]\\d:[0-5]\\d([+-][0-2]\\d:[0-5]\\d|Z))"
12+
13+type IsDateTime = '[ISO8601Regex]
src/Data/Schematic/Validation.hs+4−4
@@ -16,7 +16,7 @@ import Data.Traversable
1616import Data.Vector as V
1717import Data.Vinyl
1818import Prelude as P
19−import Text.Regex
19+import Text.Regex.TDFA
2020
2121
2222type Validation a = ValidationT ErrorMap Identity a
@@ -84,9 +84,9 @@ validateTextConstraint (JSONPath path) t = \case
8484 unless predicate warn
8585 STRegex r -> do
8686 let
87− regex = withKnownSymbol r $ symbolVal r
88− predicate = maybe False (const True) $ matchRegex (mkRegex regex) (T.unpack t)
89− errMsg = path <> " must match " <> T.pack (show regex)
87+ regex = withKnownSymbol r $ fromSing r
88+ predicate = matchTest (makeRegex (T.unpack regex) :: Regex) (T.unpack t)
89+ errMsg = path <> " must match " <> regex
9090 warn = vWarning $ mmSingleton path (pure errMsg)
9191 unless predicate warn
9292 STEnum ss -> do
test/HelpersSpec.hsnew file+62
@@ -0,0 +1,62 @@
1+{-# OPTIONS_GHC -Wno-unticked-promoted-constructors #-}
2+
3+module HelpersSpec (spec, main) where
4+
5+import Control.Lens
6+import Data.Aeson
7+import Data.ByteString.Char8 as C8
8+import Data.ByteString.Lazy as BL
9+import Data.ByteString.Lazy.Lens
10+import Data.Foldable
11+import Data.Functor.Identity
12+import Data.Monoid
13+import Data.Proxy
14+import Data.Schematic
15+import Data.Text as T
16+import Data.Text.Lens
17+import Data.Vinyl
18+import Test.Hspec
19+
20+
21+type UUIDSchema = 'SchemaObject '[ '("uuid", 'SchemaText IsUUID) ]
22+
23+-- | Taken from UUID RFC 4122
24+uuid :: Text
25+uuid = "f81d4fae-7dec-11d0-a765-00a0c91e6bf6"
26+
27+type ISO8601Schema = 'SchemaObject '[ '("datetime", 'SchemaText IsDateTime) ]
28+
29+-- | Taken from ISO8601 RFC 3339
30+iso8601datetimes :: [Text]
31+iso8601datetimes =
32+ [ "1985-04-12T23:20:50.52Z"
33+ , "1996-12-19T16:39:57-08:00"
34+ , "1990-12-31T23:59:60Z"
35+ , "1990-12-31T15:59:60-08:00"
36+ , "1937-01-01T12:00:27.87+00:20"
37+ ]
38+
39+spec :: Spec
40+spec = do
41+ describe "UUID: " $ do
42+ it "validates correct UUID" $ do
43+ let
44+ uuidJson = "{\"uuid\": \"" <> (uuid ^. unpacked . packedChars) <> "\" }"
45+ (decodeAndValidateJson uuidJson :: ParseResult (JsonRepr UUIDSchema))
46+ `shouldSatisfy` isValid
47+
48+ it "fails to validate incorrect UUID" $ do
49+ let
50+ incorrectJson = "{\"uuid\": \"incorrect\" }"
51+ (decodeAndValidateJson incorrectJson :: ParseResult (JsonRepr UUIDSchema))
52+ `shouldSatisfy` isValidationError
53+
54+ describe "ISO8601 datetime: " $ do
55+ for_ iso8601datetimes $ \dt -> do
56+ it ("validates correct datetime - " <> dt ^. unpacked) $ do
57+ let json = "{\"datetime\": \"" <> (dt ^. unpacked . packedChars) <> "\" }"
58+ (decodeAndValidateJson json :: ParseResult (JsonRepr ISO8601Schema))
59+ `shouldSatisfy` isValidationError
60+
61+main :: IO ()
62+main = hspec spec