greskell-0.1.0.0: test/Data/Greskell/GTraversalSpec.hs
{-# LANGUAGE OverloadedStrings #-}
module Data.Greskell.GTraversalSpec (main,spec) where
import Control.Category ((>>>), (<<<))
import Data.Aeson (ToJSON(..), Value(Number))
import Data.Function ((&))
import Data.Text (Text)
import System.IO (stderr, hPutStrLn)
import Test.Hspec
import Data.Greskell.Gremlin
( oIncr, oDecr, oShuffle,
pEq, pNeq, pInside, pGte
)
import Data.Greskell.Graph
( Element,
Key, key,
tLabel, tId
)
import Data.Greskell.Greskell
( toGremlin, Greskell, value)
import Data.Greskell.GTraversal
( Walk, Transform,
source, (&.), ($.), sV', sE',
gHas1, gHas2, gHas2P, gHasLabelP, gHasIdP,
gOut', gRange, gValues, gNot, gIn',
gOrder,
gProperties, gHasKeyP, gHasValueP,
ByComparator(..), gBy2, gBy1, gBy
)
main :: IO ()
main = hspec spec
spec :: Spec
spec = do
spec_GraphTraversalSource
spec_order_by
spec_compose_steps
spec_has
spec_GraphTraversalSource :: Spec
spec_GraphTraversalSource = describe "GraphTraversalSource" $ do
specify "g.V()" $ do
(toGremlin $ sV' [] $ source "g") `shouldBe` ("g.V()")
specify "g.V(1,2,3)" $ do
let ids = [1,2,3] :: [Greskell Int]
(toGremlin $ sV' (map (fmap toJSON) ids) $ source "g") `shouldBe` ("g.V(1,2,3)")
spec_order_by :: Spec
spec_order_by = describe "gOrder" $ do
let gv = source "g" & sV' []
specify "no arg" $ do
toGremlin (gv &. gOrder []) `shouldBe` "g.V().order()"
specify "empty projection" $ do
-- This case is relatively rare (I think), so the API is not so convenient for now.
toGremlin (gv &. gOrder [ByComparatorComp oIncr]) `shouldBe` "g.V().order().by(Order.incr)"
specify "traversal projection" $ do
toGremlin (gv &. gOrder [gBy2 (gOut' ["foo"] >>> gIn' ["bar"]) oShuffle])
`shouldBe` "g.V().order().by(__.out(\"foo\").in(\"bar\"),Order.shuffle)"
specify "value projection" $ do
let nameKey :: Key e Text
nameKey = "name"
toGremlin (gv &. gOrder [gBy2 nameKey oDecr]) `shouldBe` "g.V().order().by(\"name\",Order.decr)"
specify "T token projection" $ do
toGremlin (gv &. gOrder [gBy2 tLabel oIncr]) `shouldBe` "g.V().order().by(T.label,Order.incr)"
specify "multiple .by steps of different comparison types" $ do
let ageKey :: Key e Int
ageKey = "age"
toGremlin (gv &. gOrder [gBy2 ageKey oDecr, gBy2 tId oDecr, gBy1 (gOut' ["foo"])])
`shouldBe` "g.V().order().by(\"age\",Order.decr).by(T.id,Order.decr).by(__.out(\"foo\"))"
specify "gBy1" $ do
toGremlin (gv &. gOrder [gBy1 (key "name")]) `shouldBe` "g.V().order().by(\"name\")"
specify "IsString instance of ByComparator" $ do
toGremlin (gv &. gOrder ["age"]) `shouldBe` "g.V().order().by(\"age\")"
specify "gBy" $ do
toGremlin (gv &. gOrder [ByComparatorProj $ gBy tLabel]) `shouldBe` "g.V().order().by(T.label)"
specify "IsString instance of ByProjection" $ do
toGremlin (gv &. gOrder [ByComparatorProjComp ("name") oIncr])
`shouldBe` "g.V().order().by(\"name\",Order.incr)"
spec_compose_steps :: Spec
spec_compose_steps = describe "DSL to compose steps" $ do
specify "(&) and (&.)" $ do
let gt = source "g" & sV' [] &. gHas2P ("x" :: Key e Int) (pEq 100) &. gOut' [] &. gRange 0 100
toGremlin gt `shouldBe` "g.V().has(\"x\",P.eq(100)).out().range(0,100)"
specify "(&) and (&.) and (>>>)" $ do
let gt = source "g" & sV' [value $ Number 200] &. (gOut' [] >>> gOut' ["friends_to"] >>> gValues ["name"])
toGremlin gt `shouldBe` "g.V(200.0).out().out(\"friends_to\").values(\"name\")"
specify "($) and ($.)" $ do
let gt = gRange 20 30 $. gNot (gOut' ["friends_to"]) $. sV' [] $ source "g"
toGremlin gt `shouldBe` "g.V().not(__.out(\"friends_to\")).range(20,30)"
specify "($) and ($.) and (<<<)" $ do
let gt = gHas2P (key "name" :: Key e Text) (pEq "hoge") <<< gIn' ["foo", "bar"] <<< gIn' [] $. sV' [] $ source "g"
toGremlin gt `shouldBe` "g.V().in().in(\"foo\",\"bar\").has(\"name\",P.eq(\"hoge\"))"
spec_has :: Spec
spec_has = do
describe "gHas1" $ do
specify "IsString Key" $ do
toGremlin (source "g" & sV' [] &. gHas1 "foo") `shouldBe` "g.V().has(\"foo\")"
describe "gHas2" $ do
specify "simple equality" $ do
toGremlin (source "g" & sV' [] &. gHas2 "name" ("hoge" :: Greskell Text))
`shouldBe` "g.V().has(\"name\",\"hoge\")"
describe "gHas2P" $ do
specify "IsString Key and P" $ do
toGremlin (source "g" & sV' [] &. gHas2P ("name" :: Key e Text) (pNeq "hoge"))
`shouldBe` "g.V().has(\"name\",P.neq(\"hoge\"))"
describe "gHasLabelP" $ do
specify "P" $ do
toGremlin (source "g" & sE' [] &. gHasLabelP (pNeq "friends_to"))
`shouldBe` "g.E().hasLabel(P.neq(\"friends_to\"))"
describe "gHasIdP" $ do
specify "P" $ do
toGremlin (source "g" & sV' [] &. gHasIdP (pInside (value $ Number 10) (value $ Number 20)))
`shouldBe` "g.V().hasId(P.inside(10.0,20.0))"
describe "gHasKeyP, gProperties" $ do
specify "P" $ do
toGremlin (source "g" & sV' [] &. gProperties [] &. gHasKeyP (pEq "hoge"))
`shouldBe` "g.V().properties().hasKey(P.eq(\"hoge\"))"
describe "gHasValueP, gProperties" $ do
specify "P" $ do
toGremlin (source "g" & sV' [] &. gProperties ["age" :: Key e Int] &. gHasValueP (pGte 20))
`shouldBe` "g.V().properties(\"age\").hasValue(P.gte(20))"