packages feed

orchestrate 0.2.0.2 → 0.2.0.3

raw patch · 13 files changed

+628/−30 lines, 13 filesdep ~QuickCheckdep ~aesondep ~bytestringPVP: major bump suggested

API removals or changes: PVP suggests a major version bump

Dependency ranges changed: QuickCheck, aeson, bytestring, case-insensitive, data-default, either, errors, hspec, http-client, http-types, lens, mtl, smallcheck, text, transformers, unordered-containers, wreq

API changes (from Hackage documentation)

- Database.Orchestrate.Types: instance GHC.Base.Monad m => GHC.Base.Functor (Database.Orchestrate.Types.OrchestrateT m)
+ Database.Orchestrate.Types: instance GHC.Base.Functor m => GHC.Base.Functor (Database.Orchestrate.Types.OrchestrateT m)
- Database.Orchestrate.Types: OrchestrateT :: EitherT SomeException (ReaderT Session m) a -> OrchestrateT m a
+ Database.Orchestrate.Types: OrchestrateT :: ExceptT SomeException (ReaderT Session m) a -> OrchestrateT m a
- Database.Orchestrate.Types: [runOrchestrate] :: OrchestrateT m a -> EitherT SomeException (ReaderT Session m) a
+ Database.Orchestrate.Types: [runOrchestrate] :: OrchestrateT m a -> ExceptT SomeException (ReaderT Session m) a
- Database.Orchestrate.Types: eventItem :: Lens (EventItem a_aimp b_aimq) (EventItem a_aiR5 b_aiR6) (ResultItem EventPath a_aimp) (ResultItem EventPath a_aiR5)
+ Database.Orchestrate.Types: eventItem :: Lens (EventItem a_agXD b_agXE) (EventItem a_ahzU b_ahzV) (ResultItem EventPath a_agXD) (ResultItem EventPath a_ahzU)
- Database.Orchestrate.Types: eventOrd :: Lens (EventItem a_aimp b_aimq) (EventItem a_aimp b_aiR7) Int Int
+ Database.Orchestrate.Types: eventOrd :: Lens (EventItem a_agXD b_agXE) (EventItem a_agXD b_ahzW) Int Int
- Database.Orchestrate.Types: eventTime :: Lens (EventItem a_aimp b_aimq) (EventItem a_aimp b_aiR8) Timestamp Timestamp
+ Database.Orchestrate.Types: eventTime :: Lens (EventItem a_agXD b_agXE) (EventItem a_agXD b_ahzX) Timestamp Timestamp
- Database.Orchestrate.Types: itemPath :: Lens (ResultItem p_aicC v_aicD) (ResultItem p_aiha v_aicD) p_aicC p_aiha
+ Database.Orchestrate.Types: itemPath :: Lens (ResultItem p_agNZ v_agO0) (ResultItem p_agSx v_agO0) p_agNZ p_agSx
- Database.Orchestrate.Types: itemValue :: Lens (ResultItem p_aicC v_aicD) (ResultItem p_aicC v_aihb) v_aicD v_aihb
+ Database.Orchestrate.Types: itemValue :: Lens (ResultItem p_agNZ v_agO0) (ResultItem p_agNZ v_agSy) v_agO0 v_agSy
- Database.Orchestrate.Types: livePath :: Traversal' (TombstoneItem v_aiRz) Path
+ Database.Orchestrate.Types: livePath :: Traversal' (TombstoneItem v_ahAo) Path
- Database.Orchestrate.Types: liveTime :: Traversal' (TombstoneItem v_aiRz) Timestamp
+ Database.Orchestrate.Types: liveTime :: Traversal' (TombstoneItem v_ahAo) Timestamp
- Database.Orchestrate.Types: liveValue :: Traversal (TombstoneItem v_aiRz) (TombstoneItem v_aiXf) (Maybe v_aiRz) (Maybe v_aiXf)
+ Database.Orchestrate.Types: liveValue :: Traversal (TombstoneItem v_ahAo) (TombstoneItem v_ahGk) (Maybe v_ahAo) (Maybe v_ahGk)
- Database.Orchestrate.Types: resultCount :: Lens' (ResultList i_ahFK) Int
+ Database.Orchestrate.Types: resultCount :: Lens' (ResultList i_afXb) Int
- Database.Orchestrate.Types: resultList :: Lens (ResultList i_ahFK) (ResultList i_aic5) [i_ahFK] [i_aic5]
+ Database.Orchestrate.Types: resultList :: Lens (ResultList i_afXb) (ResultList i_agNs) [i_afXb] [i_agNs]
- Database.Orchestrate.Types: resultNext :: Lens' (ResultList i_ahFK) (Maybe Location)
+ Database.Orchestrate.Types: resultNext :: Lens' (ResultList i_afXb) (Maybe Location)
- Database.Orchestrate.Types: resultPrev :: Lens' (ResultList i_ahFK) (Maybe Location)
+ Database.Orchestrate.Types: resultPrev :: Lens' (ResultList i_afXb) (Maybe Location)
- Database.Orchestrate.Types: searchItem :: Lens (SearchItem v_aiY1) (SearchItem v_aja4) (ResultItem Path v_aiY1) (ResultItem Path v_aja4)
+ Database.Orchestrate.Types: searchItem :: Lens (SearchItem v_ahH6) (SearchItem v_ahT9) (ResultItem Path v_ahH6) (ResultItem Path v_ahT9)
- Database.Orchestrate.Types: searchResults :: Lens (SearchList v_ajaj) (SearchList v_ajdx) (ResultList (SearchItem v_ajaj)) (ResultList (SearchItem v_ajdx))
+ Database.Orchestrate.Types: searchResults :: Lens (SearchList v_ahTo) (SearchList v_ahWC) (ResultList (SearchItem v_ahTo)) (ResultList (SearchItem v_ahWC))
- Database.Orchestrate.Types: searchScore :: Lens' (SearchItem v_aiY1) Double
+ Database.Orchestrate.Types: searchScore :: Lens' (SearchItem v_ahH6) Double
- Database.Orchestrate.Types: searchTotal :: Lens' (SearchList v_ajaj) Int
+ Database.Orchestrate.Types: searchTotal :: Lens' (SearchList v_ahTo) Int
- Database.Orchestrate.Types: tombstonePath :: Traversal' (TombstoneItem v_aiRz) Path
+ Database.Orchestrate.Types: tombstonePath :: Traversal' (TombstoneItem v_ahAo) Path
- Database.Orchestrate.Types: tombstoneTime :: Traversal' (TombstoneItem v_aiRz) Timestamp
+ Database.Orchestrate.Types: tombstoneTime :: Traversal' (TombstoneItem v_ahAo) Timestamp

Files

orchestrate.cabal view
@@ -2,7 +2,7 @@ -- documentation, see http://haskell.org/cabal/users-guide/  name:                orchestrate-version:             0.2.0.2+version:             0.2.0.3 synopsis:            An API client for http://orchestrate.io/. -- description:          license:             Apache-2.0@@ -34,21 +34,21 @@                      , Database.Orchestrate.Utils   -- other-modules:          -- other-extensions:    -  build-depends:       base >=4.7 && <5-                     , text-                     , wreq-                     , http-client-                     , http-types-                     , aeson-                     , unordered-containers-                     , errors < 2.0-                     , either-                     , mtl-                     , lens-                     , data-default-                     , bytestring-                     , case-insensitive-                     , transformers+  build-depends:       base                 >=4.7 && <5+                     , text                 >=1.2 && <1.3+                     , wreq                 >=0.4 && <0.5+                     , http-client          >=0.4 && <0.5+                     , http-types           >=0.8 && <0.9+                     , aeson                >=0.8 && <0.9+                     , unordered-containers >=0.2 && <0.3+                     , errors               >=2.0 && <2.1+                     , either               >=4.4 && <4.5+                     , mtl                  >=2.2 && <2.3+                     , lens                 >=4.12 && <4.13+                     , data-default         >=0.5 && <0.6+                     , bytestring           >=0.10 && <0.11+                     , case-insensitive     >=1.2 && <1.3+                     , transformers         >=0.4 && <0.5   -- hs-source-dirs:         default-language:    Haskell2010 @@ -57,17 +57,25 @@   ghc-options:         -threaded -rtsopts   hs-source-dirs:      specs   main-is:             Specs.hs+  other-modules:         Specs.Orchestrate.EventSpec+                       , Specs.Orchestrate.GraphSpec+                       , Specs.Orchestrate.KeyValueSpec+                       , Specs.Orchestrate.RefSpec+                       , Specs.Orchestrate.SearchSpec+                       , Specs.Orchestrate.Spec.Types+                       , Specs.Orchestrate.Spec.Utils+                       , Specs.Orchestrate.UtilsSpec   build-depends:         base                        , orchestrate-                       , QuickCheck-                       , smallcheck-                       , hspec-                       , lens-                       , text-                       , aeson-                       , bytestring-                       , wreq-                       , errors < 2.0+                       , QuickCheck >=2.8 && <2.9+                       , smallcheck >=1.1 && <1.2+                       , hspec      >=2.1 && <2.2+                       , lens       >=4.12 && <4.13+                       , text       >=1.2 && <1.3+                       , aeson      >=0.8 && <0.9+                       , bytestring >=0.10 && <0.11+                       , wreq       >=0.4 && <0.5+                       , errors     >=2.0 && <2.1   default-language:    Haskell2010   if flag(network-specs)     cpp-options: -DNETWORK_SPECS
+ specs/Specs/Orchestrate/EventSpec.hs view
@@ -0,0 +1,128 @@+{-# LANGUAGE CPP               #-}+{-# LANGUAGE NamedFieldPuns    #-}+{-# LANGUAGE OverloadedStrings #-}+++module Specs.Orchestrate.EventSpec where+++import           Control.Applicative+import           Control.Error+import           Control.Exception+import           Control.Lens+import           Control.Monad+import qualified Data.Text                     as T+import           Network.Wreq++import           Test.Hspec++import           Database.Orchestrate.Events+import           Database.Orchestrate.KeyValue+import           Database.Orchestrate.Types+import           Database.Orchestrate.Utils++import           Specs.Orchestrate.Spec.Types+import           Specs.Orchestrate.Spec.Utils+++type GetEvent = IO (Either SomeException (Maybe (EventItem Event Person)))++fixtures :: [Person]+fixtures = [ Person "joe" 42+           , Person "ella" 13+           ]++events :: [(Event, Timestamp)]+events = [ (Event "birth"    0.0, 784111777000)+         , (Event "marriage" 0.5, 784111777100)+         , (Event "child"    0.6, 784111777200)+         , (Event "divorce"  0.8, 784111777300)+         , (Event "death"    1.0, 784111777400)+         ]++deleteLocs :: [Location] -> IO ()+deleteLocs locs = do+    Session{_sessionOptions,_sessionURL} <- envSession+    let url = T.unpack _sessionURL+    mapM_ (deleteWith _sessionOptions . (++ "?purge=true") . (url ++) . T.unpack) locs++withEvents :: Person -> EventType -> [(Event, Timestamp)] -> IO () -> IO ()+withEvents p et evs = withEvents' p et evs . const++withEvents' :: Person -> EventType -> [(Event, Timestamp)]+            -> (Either SomeException [Location] -> IO ())+            -> IO ()+withEvents' p et evs action =+    bracket (run . mapM (uncurry (createEvent p et)) $ map (fmap Just) evs)+            (either (const $ return ()) deleteLocs)+            action++callLoc :: Location -> (Timestamp -> Int -> OrchestrateIO a)+        -> IO (Either SomeException a)+callLoc loc f = run . join $ f <$> eithererr loc (loc ^? locationTimestamp)+                               <*> eithererr loc (loc ^? locationOrdinal)++eithererr :: Monad m => Location -> Maybe a -> OrchestrateT m a+eithererr loc = orchestrateEither+              . note (SomeException+                        (ErrorCall $ "Invalid location: " ++ T.unpack loc))++#if NETWORK_SPECS+spec :: Spec+spec = describe "Database.Orchestrate.Events" $ around_ (withFixtures fixtures) $ do+    describe "createEvent" $+        it "should create events." $+            withEvents' (fixtures !! 1) "create" events $ \locs -> do+                length (locs ^.. _Right . traverse) `shouldBe` 5+                locs ^.. _Right . traverse . locationKey  `shouldBe` replicate 5 "ella"+                locs ^.. _Right . traverse . locationType `shouldBe` replicate 5 "create"+                length (locs ^.. _Right . traverse . locationTimestamp) `shouldBe` 5+                length (locs ^.. _Right . traverse . locationOrdinal)   `shouldBe` 5++    describe "getEvent" $+        it "should retrieve the stored data for an event." $+            let p = head fixtures+            in  withEvents' p "get" events $ \(Right locs) -> do+                let events' = map fst events+                    items   = zip events'+                            $ zipWith locationEventItem locs events'+                forM_ items $ \(event, Just evtItem) -> do+                    e <- run $ getEvent p "get" (evtItem ^. eventTime) (evtItem ^. eventOrd)+                    e ^? _Right . _Just . eventItem . itemValue `shouldBe` Just event++    describe "updateEvent" $+        it "should update the data in the event." $+            let ev@(e, _) = head events+                p         = fixtures !! 1+            in  withEvents' p "life" [ev] $ \(Right [loc]) -> do+                let e' = e & eventScale .~ 3.1415+                r <- callLoc loc $ \t o -> updateEvent p "life" e' t o Nothing+                r `shouldSatisfy` isRight+                mNewE <- callLoc loc $ getEvent p "life"+                mNewE ^? _Right . _Just . eventItem . itemValue . eventScale+                    `shouldBe` Just 3.1415++    describe "deleteEvent" $+        it "should remove the event" $ do+            let (e, ts) = head events+                p       = fixtures !! 1+            Right loc <- run $ createEvent p "test" e (Just ts)+            r <- callLoc loc $ \t o -> deleteEvent p "test" t o Nothing+            r `shouldSatisfy` isRight+            Right e' <- (run $   eithererr loc (loc ^? locationOrdinal)+                             >>= getEvent p "test" ts) :: GetEvent+            e' `shouldSatisfy` isNothing++    describe "listEvents" $ around_ (withEvents (head fixtures) "list" events) $ do+        it "should return all events" $ do+            elist <- run $ listEvents (head fixtures) "list" Nothing (Open, Open)+            elist ^? _Right . resultCount `shouldBe` Just (length events)+            elist ^.. _Right . resultList . traverse . eventItem . itemValue . eventTitle+                `shouldMatchList` ["birth", "marriage", "child", "divorce", "death"]++#else+spec :: Spec+spec = describe "Database.Orchestrate.Events" $+    it "should contain tests." $+        pendingWith "configure with \"--enable-tests -fnetwork-specs\"."+#endif
+ specs/Specs/Orchestrate/GraphSpec.hs view
@@ -0,0 +1,63 @@+{-# LANGUAGE CPP               #-}+{-# LANGUAGE OverloadedStrings #-}+++module Specs.Orchestrate.GraphSpec where+++import           Control.Error+import           Control.Exception+import           Control.Lens+import           Control.Monad++import           Test.Hspec++import           Database.Orchestrate.Graph+import           Database.Orchestrate.KeyValue+import           Database.Orchestrate.Types+import           Database.Orchestrate.Utils++import           Specs.Orchestrate.Spec.Types+import           Specs.Orchestrate.Spec.Utils+++-- Names for 2014 tropical cyclones (from NOAA).+fixtures :: [Person]+fixtures = [ Person "Bertha"    1    -- 0+           , Person "Fay"       9    -- 1+           , Person "Laura"     8    -- 2+           , Person "Rene"      2    -- 3+           ]+++#if NETWORK_SPECS+spec :: Spec+spec = describe "Database.Orchestrate.Graph" $ around_ (withFixtures fixtures) $ do+    describe "createRel and getRel" $+        it "should create relationships that getRel can retrieve." $ do+            let bertha = fixtures !! 0+                rene   = fixtures !! 3++            r' <- run $ createRel bertha "brother" rene+            r' `shouldSatisfy` isRight++            r <- run $ getRel bertha "brother" []+            r ^? _Right . resultCount `shouldBe` Just 1+            r ^.. _Right . resultList . traverse . itemValue . personName+                `shouldBe` ["Rene"]++    describe "deleteRel" $+        it "should have tests" $ do+            let fay   = fixtures !! 1+                laura = fixtures !! 2+            void . run' $ createRel fay "sister" laura+            void . run' $ deleteRel fay "sister" laura+            r <- (run $ getRel fay "sister" []) :: IO (Either SomeException (RelList Person Person))+            r ^? _Right . resultCount `shouldBe` Just 0++#else+spec :: Spec+spec = describe "Database.Orchestrate.Graph" $+    it "should contain tests." $+        pendingWith "configure with \"--enable-tests -fnetwork-specs\"."+#endif
+ specs/Specs/Orchestrate/KeyValueSpec.hs view
@@ -0,0 +1,64 @@+{-# LANGUAGE CPP               #-}+{-# LANGUAGE OverloadedStrings #-}+++module Specs.Orchestrate.KeyValueSpec where+++import           Control.Lens                  hiding ((.=))+import           Data.Either+import qualified Data.List                     as L++import           Test.Hspec++import           Database.Orchestrate.KeyValue+import           Database.Orchestrate.Types++import           Specs.Orchestrate.Spec.Types+import           Specs.Orchestrate.Spec.Utils+++#if NETWORK_SPECS+spec :: Spec+spec = describe "Database.Orchestrate.KeyValue" $ do+    describe "getV" $+        it "should return Nothing if the key isn't there." $ do+            r <- getPerson "name"+            r `shouldSatisfy` isn't (_Right . _Just)+    describe "putV" $+        it "should insert a value into the database." $ do+            r <- run $ putV (Person "eric" 44) NoMatch+            r `shouldSatisfy` isRight+            r' <- getPerson "eric"+            r' ^? _Right . _Just `shouldBe` Just (Person "eric" 44)+    describe "postV" $+        it "should insert a value and get back a key." $ do+            let elsa = Person "elsa" 10+            Right (_, Just k) <- run (postV elsa)+            e <- getPerson k+            e ^? _Right . _Just `shouldBe` Just (Person "elsa" 10)+            run' $ purgeKV k (Person "elsa" undefined) Nothing+    describe "deleteV" $+        it "should remove a value from the database." $ do+            r <- run $ deleteV (Person "eric" undefined) Nothing+            r `shouldSatisfy` isRight+            r' <- getPerson "eric"+            r' `shouldSatisfy` isn't (_Right . _Just)+    describe "listVals" $+        it "should retrieve values from the database." $ do+            let names = ["abbie", "bob", "carol"]+            r <- run . mapM_ ((`putV` NoMatch) . uncurry Person) $ zip names [1..]+            r `shouldSatisfy` isRight+            r' <- run $ listVals "test-coll" Nothing (Open, Open)+            r' `shouldSatisfy` isRight+            let Right kvl = r'+            _resultCount kvl `shouldBe` 3+            L.sort (map (name . _itemValue) (_resultList kvl)) `shouldBe` names+            run' $ mapM_ ((`purgeV` Nothing) . (`Person` undefined)) names++#else+spec :: Spec+spec = describe "Database.Orchestrate.KeyValue" $ do+    it "should contain tests." $+        pendingWith "configure with \"--enable-tests -fnetwork-specs\"."+#endif
+ specs/Specs/Orchestrate/RefSpec.hs view
@@ -0,0 +1,84 @@+{-# LANGUAGE CPP               #-}+{-# LANGUAGE OverloadedStrings #-}+++module Specs.Orchestrate.RefSpec where+++import           Control.Applicative+import           Control.Exception             (SomeException, bracket_)+import           Control.Lens+import           Data.Aeson+import qualified Data.ByteString.Lazy          as BS+import           Data.Either+import           Data.Maybe++import           Test.Hspec++import           Database.Orchestrate.KeyValue+import           Database.Orchestrate.Ref+import           Database.Orchestrate.Types+import           Database.Orchestrate.Utils++import           Specs.Orchestrate.Spec.Types+import           Specs.Orchestrate.Spec.Utils++runRefList :: OrchestrateIO (ResultList (TombstoneItem Person))+           -> IO (Either SomeException (ResultList (TombstoneItem Person)))+runRefList = run++cats :: [Person]+cats = map (uncurry Person) . (`zip` [1..]) . take 7 $ repeat "elsa"++withCats :: IO () -> IO ()+withCats = withFixtures cats++#if NETWORK_SPECS+spec :: Spec+spec = describe "Database.Orchestrate.Ref" $ do+    describe "getRef" $+        it "can return old version of objects." $ do+            r <- run $ putV (Person "eric" 42) NoMatch+            let ref = r ^? _Right . locationRef+            ref `shouldSatisfy` isn't _Nothing++            run' $ putV (Person "eric" 44) NoMatch+            eric <- run . getRef "test-coll" "eric" $ fromJust ref+            eric ^? _Right . _Just . personAge `shouldBe` Just 42++            run' $ purgeV (Person "eric" undefined) Nothing++    describe "decoding ResultList (TombstoneItem Person)." $ do+        it "should work." $ do+            r <- (eitherDecode <$> BS.readFile "specs/data.json") :: IO (Either String (ResultList (TombstoneItem Person)))+            r `shouldSatisfy` isRight++    describe "listRefs" $ around_ withCats $ do+        it "returns a list of references for an object." $ do+            refs <- runRefList $ listRefs "test-coll" "elsa" Nothing Nothing False+            refs ^? _Right . resultCount `shouldBe` Just 7+        it "returns a list of empty live values." $ do+            refs <- runRefList $ listRefs "test-coll" "elsa" Nothing Nothing False+            length (refs ^.. _Right . resultList . traverse . _LiveItem . liveValue . _Nothing)+                `shouldBe` 7+        it "returns a list of values if requested." $ do+            refs <- runRefList $ listRefs "test-coll" "elsa" Nothing Nothing True+            length (refs ^.. _Right . resultList . traverse . _LiveItem . liveValue . _Just)+                `shouldBe` 7+        it "limits the number of items requested." $ do+            refs <- runRefList $ listRefs "test-coll" "elsa" (Just 3) Nothing True+            refs ^.. _Right . resultList . to length `shouldBe` [3]+            refs ^.. _Right . resultList . traverse . _LiveItem . liveValue . _Just . personAge+                `shouldBe` [7, 6, 5]+        it "offsets the items returned." $ do+            refs <- runRefList $ listRefs "test-coll" "elsa" (Just 3) (Just 2) True+            refs ^.. _Right . resultList . to length `shouldBe` [3]+            refs ^.. _Right . resultList . traverse . _LiveItem . liveValue . _Just . personAge+                `shouldBe` [5, 4, 3]++#else+spec :: Spec+spec = describe "Database.Orchestrate.Ref" $ do+    it "should contain tests." $+        pendingWith "configure with \"--enable-tests -fnetwork-specs\"."+#endif
+ specs/Specs/Orchestrate/SearchSpec.hs view
@@ -0,0 +1,98 @@+{-# LANGUAGE CPP               #-}+{-# LANGUAGE OverloadedStrings #-}+{-# LANGUAGE RankNTypes        #-}+++module Specs.Orchestrate.SearchSpec where+++import           Control.Exception             (SomeException, bracket_)+import           Control.Lens+import qualified Data.List                     as L+import           Data.Monoid+import qualified Data.Text                     as T++import           Test.Hspec++import           Database.Orchestrate.KeyValue+import           Database.Orchestrate.Search+import           Database.Orchestrate.Types++import           Specs.Orchestrate.Spec.Types+import           Specs.Orchestrate.Spec.Utils+++-- From http://www.empireonline.com/features/30-star-wars-characters+fixtures :: [Person]+fixtures = map (uncurry Person)+         $ (`zip` [(1::Int)..])+         [ "Han Solo"+         , "Darth Vader"+         , "Boba Fett"+         , "R2-D2"+         , "Chewbacca"+         , "Yoda"+         , "Luke Skywalker"+         , "Darth Maul"+         , "Stormtrooper"+         , "Princess Leia"+         , "Jabba the Hut"+         , "Ben Kenobi"+         , "Darth Sidious"+         , "Jawa"+         , "Lando Calrissian"+         , "Anakin Skywalker"+         , "Scout Trooper"+         , "Tuskan Raiders"+         , "Greedo"+         , "Tie Fighter Pilot"+         , "Obi-Wan Kenobi"+         , "Imperial Guards"+         , "Qui-Gin Jinn"+         , "C-3PO"+         , "Gamorrean Guards"+         , "Padme Amidala"+         , "Admiral Ackbar"+         , "Count Dooku"+         , "Mace Windu"+         , "Wicket"+         ]++runSearch :: OrchestrateIO (SearchList Person)+          -> IO (Either SomeException (SearchList Person))+runSearch = run++allNames :: forall c. (T.Text -> Const (Endo [T.Text]) T.Text)+         -> Either c (SearchList Person)+         -> Const (Endo [T.Text]) (Either c (SearchList Person))+allNames = _Right . searchResults . resultList . traverse . searchItem . itemValue . personName++#if NETWORK_SPECS+spec :: Spec+spec = describe "Database.Orchestrate.Search" $ around_ (withFixtures fixtures) $+    describe "query" $ do+        it "should search for all fields." $ do+            s <- runSearch $ query "test-coll" "darth" Nothing Nothing+            s ^?  _Right . searchTotal `shouldBe` Just 3+            L.sort (s ^.. allNames)+                `shouldBe` ["Darth Maul", "Darth Sidious", "Darth Vader"]+        it "should search in a specific field." $ do+            s <- runSearch $ query "test-coll" "name=guards" Nothing Nothing+            s ^?  _Right . searchTotal `shouldBe` Just 2+            L.sort (s ^.. allNames)+                `shouldBe` ["Gamorrean Guards", "Imperial Guards"]+        it "should limit the number of results returned." $ do+            s <- runSearch $ query "test-coll" "darth" (Just 1) Nothing+            s ^?  _Right . searchTotal `shouldBe` Just 3+            s ^?  _Right . searchResults . resultCount `shouldBe` Just 1+        it "should offset the results returned." $ do+            s <- runSearch $ query "test-coll" "darth" Nothing (Just 2)+            s ^?  _Right . searchTotal `shouldBe` Just 3+            s ^?  _Right . searchResults . resultCount `shouldBe` Just 1++#else+spec :: Spec+spec = describe "Database.Orchestrate.Search" $+    it "should contain tests." $+        pendingWith "configure with \"--enable-tests -fnetwork-specs\"."+#endif
+ specs/Specs/Orchestrate/Spec/Types.hs view
@@ -0,0 +1,61 @@+{-# LANGUAGE OverloadedStrings #-}+++module Specs.Orchestrate.Spec.Types where+++import           Control.Applicative+import           Control.Monad+import           Data.Aeson+import qualified Data.Text                  as T++import           Database.Orchestrate.Types+++data Person = Person+            { name :: T.Text+            , age  :: Int+            } deriving (Eq, Show)++instance FromJSON Person where+    parseJSON (Object o) =   Person+                         <$> o .: "name"+                         <*> o .: "age"+    parseJSON _          = mzero++instance ToJSON Person where+    toJSON (Person n a) = object [ "name" .= n+                                 , "age"  .= a+                                 ]++instance OrchestrateData Person where+    tableName _          = "test-coll"+    dataKey (Person n _) = n++personName :: Functor f => (T.Text -> f T.Text) -> Person -> f Person+personName f (Person n a) = fmap (`Person` a) (f n)++personAge :: Functor f => (Int -> f Int) -> Person -> f Person+personAge f (Person n a) = fmap (Person n) (f a)++data Event = Event+           { title :: T.Text+           , scale :: Double+           } deriving (Eq, Show)++instance FromJSON Event where+    parseJSON (Object o) =   Event+                         <$> o .: "title"+                         <*> o .: "scale"+    parseJSON _          = mzero++instance ToJSON Event where+    toJSON (Event t s) = object [ "title" .= t+                                , "scale" .= s+                                ]++eventTitle :: Functor f => (T.Text -> f T.Text) -> Event -> f Event+eventTitle f (Event t s) = fmap (`Event` s) (f t)++eventScale :: Functor f => (Double -> f Double) -> Event -> f Event+eventScale f (Event t s) = fmap (Event t) (f s)
+ specs/Specs/Orchestrate/Spec/Utils.hs view
@@ -0,0 +1,29 @@+{-# LANGUAGE OverloadedStrings #-}+++module Specs.Orchestrate.Spec.Utils where+++import qualified Control.Exception             as Ex+import           Prelude                       hiding (lookup)++import           Database.Orchestrate.KeyValue (lookup, purgeV, putV)+import           Database.Orchestrate.Types+import           Database.Orchestrate.Utils++import           Specs.Orchestrate.Spec.Types+++run :: OrchestrateIO m -> IO (Either Ex.SomeException m)+run m = envSession >>= runO' m++run' :: OrchestrateIO m -> IO ()+run' m = envSession >>= runO' m >> return ()++getPerson :: Key -> IO (Either Ex.SomeException (Maybe Person))+getPerson = run . lookup "test-coll"++withFixtures :: OrchestrateData a => [a] -> IO () -> IO ()+withFixtures fixtures =+    Ex.bracket_ (run' $ mapM_ (`putV` NoMatch) fixtures)+                (run' $ mapM_ (`purgeV` Nothing) fixtures)
+ specs/Specs/Orchestrate/UtilsSpec.hs view
@@ -0,0 +1,60 @@+{-# LANGUAGE OverloadedStrings #-}+++module Specs.Orchestrate.UtilsSpec where+++import           Control.Lens++import           Test.Hspec++import           Database.Orchestrate.Utils+++spec :: Spec+spec = describe "Database.Orchestrate.Utils" $ do+    describe "locationCollection" $ do+        it "should extract the collection from a location URL." $ do+            shouldBe ("/v0/collection/035ab997adffe604/refs/82eafab14dc84ed3" ^? locationCollection)+                     (Just "collection")+            shouldBe ("/v0/collection/key/events/type/1398286518286/6" ^? locationCollection)+                     (Just "collection")+        it "should return Nothing if the URL is invalid." $ do+            "/v0" ^? locationCollection `shouldBe` Nothing++    describe "locationKey" $ do+        it "should extract the key from a location URL." $ do+            shouldBe ("/v0/collection/035ab997adffe604/refs/82eafab14dc84ed3" ^? locationKey)+                     (Just "035ab997adffe604")+            shouldBe ("/v0/collection/key/events/type/1398286518286/6" ^? locationKey)+                     (Just "key")+        it "should return Nothing if the URL is too short." $ do+            "/v0/collection" ^? locationKey `shouldBe` Nothing++    describe "locationRef" $ do+        it "should extract the ref from a location URL." $ do+            shouldBe ("/v0/collection/035ab997adffe604/refs/82eafab14dc84ed3" ^? locationRef)+                     (Just "82eafab14dc84ed3")+        it "should return Nothing if the URL is too short." $ do+            "/v0/collection" ^? locationRef `shouldBe` Nothing++    describe "locationType" $ do+        it "should extract the type of event from the location URL." $ do+            shouldBe ("/v0/collection/key/events/type/1398286518286/6" ^? locationType)+                     (Just "type")+        it "should return Nothing if the URL is too short." $ do+            "/v0/collection/key/events" ^? locationType `shouldBe` Nothing++    describe "locationTimestamp" $ do+        it "should extract the event timesteamp from the location URL." $ do+            shouldBe ("/v0/collection/key/events/type/1398286518286/6" ^? locationTimestamp)+                     (Just 1398286518286)+        it "should return Nothing if the URL is too short." $ do+            "/v0/collection/key/events" ^? locationTimestamp `shouldBe` Nothing++    describe "locationOrdinal" $ do+        it "should extract the event ordinal from the location URL." $ do+            shouldBe ("/v0/collection/key/events/type/1398286518286/6" ^? locationOrdinal)+                     (Just 6)+        it "should return Nothing if the URL is too short." $ do+            "/v0/collection/key/events" ^? locationOrdinal `shouldBe` Nothing
src/Database/Orchestrate/Graph.hs view
@@ -13,6 +13,7 @@  import           Control.Monad import           Data.Aeson+import qualified Data.HashMap.Strict        as M import qualified Data.Text                  as T import           Network.Wreq @@ -49,7 +50,7 @@           -> RelKind            -- ^ The label for the edge.           -> b                  -- ^ The target, destination node.           -> OrchestrateIO ()-createRel from rel to = void $ apiCheck [] url [] $ \o s -> putWith o s Null+createRel from rel to = void $ apiCheck [] url [] $ \o s -> putWith o s (Object M.empty)     where url = [ tableName from , dataKey from                 , "relation", rel                 , tableName to, dataKey to
src/Database/Orchestrate/Network.hs view
@@ -29,6 +29,8 @@ -- else is bad. Bad codes throw an exception in 'OrchestrateT'. checkStatusCode :: Monad m => Int -> OrchestrateT m () checkStatusCode 200 = return ()+checkStatusCode 201 = return ()+checkStatusCode 202 = return () checkStatusCode 204 = return () checkStatusCode rc  = throwError                     . Ex.SomeException
src/Database/Orchestrate/Types.hs view
@@ -196,7 +196,7 @@ -- 'Session' data with error handling using 'EitherT' 'Ex.SomeException'. newtype OrchestrateT m a     = OrchestrateT-    { runOrchestrate :: EitherT Ex.SomeException (ReaderT Session m) a }+    { runOrchestrate :: ExceptT Ex.SomeException (ReaderT Session m) a }     deriving (Functor, Applicative, Monad)  instance MonadTrans OrchestrateT where@@ -212,11 +212,11 @@ -- TODO: Need to define this for other monad classes.  instance Monad m => MonadError Ex.SomeException (OrchestrateT m) where-    throwError = OrchestrateT . EitherT . return . Left+    throwError = OrchestrateT . ExceptT . return . Left     catchError a handler =   join                          .   fmap (handler' handler)                          .   lift-                         .   runReaderT (runEitherT $ runOrchestrate a)+                         .   runReaderT (runExceptT $ runOrchestrate a)                          =<< ask  handler' :: Monad m
src/Database/Orchestrate/Utils.hs view
@@ -99,7 +99,7 @@ -- -- This is the most minimal handler. runO' :: Monad m => OrchestrateT m a -> Session -> m (Either Ex.SomeException a)-runO' m = runReaderT (runEitherT $ runOrchestrate m)+runO' m = runReaderT (runExceptT $ runOrchestrate m)  -- | Lifts an IO action into the 'OrchestrateT' monad. io :: MonadIO m => IO a -> OrchestrateT m a