diff --git a/haskell-neo4j-client.cabal b/haskell-neo4j-client.cabal
--- a/haskell-neo4j-client.cabal
+++ b/haskell-neo4j-client.cabal
@@ -1,5 +1,5 @@
 name:                haskell-neo4j-client
-version:             0.3.0.15
+version:             0.3.1.0
 synopsis:            A Haskell neo4j client
 description:         
     Library to interact with Neo4j databases. 
@@ -12,8 +12,9 @@
     .
        -Batch calls for CRUD operations.
     .
+       -Traversal API
     .
-    All code has been tested with Neo4j versions 2.0.3,  2.1.5, 2.1.7 and 2.2.0
+    All code has been tested with Neo4j versions 2.0.3, 2.1.5, 2.1.7, 2.2.0 and 2.2.1
     .
     2.2.0 added authentication to the API this driver uses, this is not supported yet by this driver but it will be soon.
     In the meantime you will have to disable it.
@@ -61,6 +62,7 @@
                    , lifted-base                 == 0.2.*
                    , hashable                    == 1.2.*
                    , mtl                         >= 2.1        && < 2.3
+                   , network-uri                 == 2.6.*
 
 library
   hs-source-dirs:      src
@@ -89,3 +91,4 @@
                      , hashable              == 1.2.*
                      , transformers-base     == 0.4.*
                      , mtl                   >= 2.1        && < 2.3
+                     , network-uri           == 2.6.*
diff --git a/src/Database/Neo4j/Batch.hs b/src/Database/Neo4j/Batch.hs
--- a/src/Database/Neo4j/Batch.hs
+++ b/src/Database/Neo4j/Batch.hs
@@ -8,9 +8,10 @@
     -- * General
     Batch, runBatch, BatchFuture(..), NodeBatchIdentifier, RelBatchIdentifier, BatchEntity,
     -- * Nodes
-    createNode, getNode, deleteNode,
+    createNode, createNamedNode, getNode, getNamedNode, deleteNode,
     -- * Relationships
-    createRelationship, getRelationship, getRelationshipFrom, getRelationshipTo, deleteRelationship, getRelationships,
+    createRelationship, createNamedRelationship, getRelationship, getNamedRelationship, getRelationshipFrom,
+    getRelationshipTo, deleteRelationship, getRelationships,
     -- * Properties
     setProperties, setProperty, deleteProperties, deleteProperty,
     -- * Labels
diff --git a/src/Database/Neo4j/Batch/Node.hs b/src/Database/Neo4j/Batch/Node.hs
--- a/src/Database/Neo4j/Batch/Node.hs
+++ b/src/Database/Neo4j/Batch/Node.hs
@@ -35,11 +35,23 @@
     where cmd = defCmd{cmdMethod = HT.methodPost, cmdPath = "/node", cmdBody = J.toJSON props, cmdParse = parser}
           parser n = G.addNode (tryParseBody n)
 
+-- | Batch operation to create a node and assign it a name to easily retrieve it from the resulting graph of the batch
+createNamedNode :: String -> Properties -> Batch (BatchFuture Node)
+createNamedNode name props = nextState cmd
+    where cmd = defCmd{cmdMethod = HT.methodPost, cmdPath = "/node", cmdBody = J.toJSON props, cmdParse = parser}
+          parser n = G.addNamedNode name (tryParseBody n)
+
 -- | Batch operation to get a node from the DB
 getNode :: NodeBatchIdentifier a => a -> Batch (BatchFuture Node)
 getNode n = nextState cmd
     where cmd = defCmd{cmdMethod = HT.methodGet, cmdPath = getNodeBatchId n, cmdBody = "", cmdParse = parser}
           parser jn = G.addNode (tryParseBody jn)
+
+-- | Batch operation to get a node from the DB and assign it a name
+getNamedNode :: NodeBatchIdentifier a => String -> a -> Batch (BatchFuture Node)
+getNamedNode name n = nextState cmd
+    where cmd = defCmd{cmdMethod = HT.methodGet, cmdPath = getNodeBatchId n, cmdBody = "", cmdParse = parser}
+          parser jn = G.addNamedNode name (tryParseBody jn)
 
 -- | Batch operation to delete a node
 deleteNode :: NodeBatchIdentifier a => a -> Batch (BatchFuture ())
diff --git a/src/Database/Neo4j/Batch/Relationship.hs b/src/Database/Neo4j/Batch/Relationship.hs
--- a/src/Database/Neo4j/Batch/Relationship.hs
+++ b/src/Database/Neo4j/Batch/Relationship.hs
@@ -40,11 +40,26 @@
           body = J.object ["to" .= getNodeBatchId nodeto, "type" .= t, "data" .= J.toJSON props]
           parser r = G.addRelationship (tryParseBody r)
 
+-- | Create a new relationship with a type and a set of properties and assign it an identifier
+createNamedRelationship :: (NodeBatchIdentifier a, NodeBatchIdentifier b) => String -> RelationshipType -> Properties
+                        -> a -> b -> Batch (BatchFuture Relationship)
+createNamedRelationship name t props nodefrom nodeto = nextState cmd
+    where cmd = defCmd{cmdMethod = HT.methodPost, cmdPath = path, cmdBody = J.toJSON body, cmdParse = parser}
+          path = getNodeBatchId nodefrom <> "/relationships"
+          body = J.object ["to" .= getNodeBatchId nodeto, "type" .= t, "data" .= J.toJSON props]
+          parser r = G.addNamedRelationship name (tryParseBody r)
+
 -- | Refresh a relationship entity with the contents in the DB
 getRelationship :: RelBatchIdentifier r => r -> Batch (BatchFuture Relationship)
 getRelationship rel = nextState cmd
     where cmd = defCmd{cmdMethod = HT.methodGet, cmdPath = getRelBatchId rel, cmdBody = "", cmdParse = parser}
           parser jr = G.addRelationship (tryParseBody jr)
+
+-- | Refresh a relationship entity with the contents in the DB and assign it an identifier
+getNamedRelationship :: RelBatchIdentifier r => String -> r -> Batch (BatchFuture Relationship)
+getNamedRelationship name rel = nextState cmd
+    where cmd = defCmd{cmdMethod = HT.methodGet, cmdPath = getRelBatchId rel, cmdBody = "", cmdParse = parser}
+          parser jr = G.addNamedRelationship name (tryParseBody jr)
 
 -- | Get the "node from" from a relationship from the DB
 getRelationshipFrom :: Relationship -> Batch (BatchFuture Node)
diff --git a/src/Database/Neo4j/Graph.hs b/src/Database/Neo4j/Graph.hs
--- a/src/Database/Neo4j/Graph.hs
+++ b/src/Database/Neo4j/Graph.hs
@@ -1,5 +1,6 @@
 {-# LANGUAGE OverloadedStrings  #-}
 
+
 -- | Module to handle 'Graph' objects. These have information about a group of nodes, relationships,
 --  and information about labels per node and nodes per label.
 --  Notice a graph can have relationships and at the same time not have some of the nodes of those
@@ -9,10 +10,10 @@
     -- * General objects
     Graph, LabelSet, empty,
     -- * Handling nodes in the graph object
-    addNode, hasNode, deleteNode, getNodes, getNode, getNodeFrom, getNodeTo,
+    addNode, addNamedNode, hasNode, deleteNode, getNodes, getNode, getNamedNode, getNodeFrom, getNodeTo,
     -- * Handling properties in the graph object
-    getRelationships, hasRelationship, addRelationship, deleteRelationship, getRelationshipNodeFrom,
-    getRelationshipNodeTo, getRelationship,
+    getRelationships, hasRelationship, addRelationship, addNamedRelationship, deleteRelationship,
+    getRelationshipNodeFrom, getRelationshipNodeTo, getRelationship, getNamedRelationship,
     -- ** Handling orphaned relationships #orphan#
     getOrphansFrom, getOrphansTo, cleanOrphanRelationships,
     -- * Handling properties
@@ -50,18 +51,27 @@
 type NodeRelIndex = M.HashMap NodePath RelSet
 
 data Graph = Graph {nodes :: NodeIndex, labels :: LabelNodeIndex, rels :: RelIndex,
-                    nodeLabels :: NodeLabelIndex, nodeFromRels :: NodeRelIndex, nodeToRels :: NodeRelIndex
+                    nodeLabels :: NodeLabelIndex, nodeFromRels :: NodeRelIndex, nodeToRels :: NodeRelIndex,
+                    namedNodes :: M.HashMap String NodePath, namedRels :: M.HashMap String RelPath,
+                    nodeNames :: M.HashMap NodePath String, relNames :: M.HashMap RelPath String
                     } deriving (Eq, Show)
 
 -- | Create an empty graph
 empty :: Graph
 empty = Graph {nodes = M.empty, labels = M.empty, rels = M.empty, nodeLabels = M.empty, nodeFromRels = M.empty,
-               nodeToRels = M.empty}
+               nodeToRels = M.empty, namedNodes = M.empty, namedRels = M.empty, nodeNames = M.empty,
+               relNames = M.empty}
 
 -- | Add a node to the graph
 addNode :: Node -> Graph -> Graph
 addNode n g = g {nodes = M.insert (getNodePath n) n (nodes g)}
 
+-- | Add a node to the graph with an identifier
+addNamedNode :: String -> Node -> Graph -> Graph
+addNamedNode name n g = addNode n $ g {nodeNames = M.insert _nodePath name $ nodeNames g,
+                                       namedNodes = M.insert name _nodePath $ namedNodes g}
+    where _nodePath = getNodePath n
+
 -- | Set the properties of a node or relationship in the graph, if not present it won't do anything
 setProperties :: EntityIdentifier a => a -> Properties -> Graph -> Graph
 setProperties ei props g = fromMaybe g $ (addEntity . newEntity) <$> entity
@@ -118,6 +128,12 @@
 getNode :: NodeIdentifier a => a -> Graph -> Maybe Node
 getNode n g = getNodePath n `M.lookup` nodes g
 
+-- | Get a node by name in the graph, if any
+getNamedNode :: String -> Graph -> Maybe Node
+getNamedNode name g = do
+    nodepath <- getNodePath <$> name `M.lookup` namedNodes g
+    nodepath `M.lookup` nodes g
+
 -- | Get outgoing relationships from a node
 getNodeFrom :: NodeIdentifier a => a -> Graph -> Maybe [Relationship]
 getNodeFrom n g = join $ sequence <$> filter (/=Nothing) <$> map getRel <$> fromrels
@@ -142,11 +158,23 @@
 deleteNode :: NodeIdentifier a => a -> Graph -> Graph
 deleteNode n g = g {nodes = M.delete nodeLoc (nodes g),
                  labels = cleanLabelNodeIndex $ removeNodeFromLabels (labels g) labelsForNode,
-                 nodeLabels = M.delete nodeLoc (nodeLabels g)}
+                 nodeLabels = M.delete nodeLoc (nodeLabels g), nodeNames = newNodeNames, namedNodes = newNamedNodes}
     where labelsForNode = M.lookupDefault HS.empty nodeLoc (nodeLabels g)
+          nodepath = getNodePath n
           nodeLoc = getNodePath n
           removeNodeFromLabels = HS.foldl' (\acc x -> M.insertWith (\_ -> HS.delete nodeLoc) x HS.empty acc)
           cleanLabelNodeIndex = M.filter (/=HS.empty) 
+          nodenames = nodeNames g
+          (mNodeName, newNodeNames) = fromMaybe (Nothing, nodenames) $ do
+              name <- nodepath `M.lookup` nodenames
+              return (Just name, nodepath `M.delete` nodenames)
+          namednodes = namedNodes g
+          newNamedNodes = fromMaybe namednodes $ do
+              nodename <- mNodeName
+              _nodepath <- nodename `M.lookup` namednodes
+              return $ if nodepath == _nodepath
+                          then nodename `M.delete` namednodes
+                          else namednodes
 
 -- | Add a relationship to the graph
 addRelationship :: Relationship -> Graph -> Graph
@@ -157,6 +185,12 @@
           pathTo = getNodePath . relTo
           relpath = getRelPath r
 
+-- | Add a relationship to the graph with an identified
+addNamedRelationship :: String -> Relationship -> Graph -> Graph
+addNamedRelationship name r g = addRelationship r $ g {relNames = M.insert _relPath name $ relNames g,
+                                                       namedRels = M.insert name _relPath $ namedRels g}
+    where _relPath = getRelPath r
+
 -- | Get a list with all the relationships in the graph
 getRelationships :: Graph -> [Relationship]
 getRelationships g = M.elems $ rels g
@@ -165,6 +199,12 @@
 getRelationship :: RelIdentifier a => a -> Graph -> Maybe Relationship
 getRelationship r g = getRelPath r `M.lookup` rels g
 
+-- | Get a relationship by name in the graph, if any
+getNamedRelationship :: String -> Graph -> Maybe Relationship
+getNamedRelationship name g = do
+    relpath <- getRelPath <$> name `M.lookup` namedRels g
+    relpath `M.lookup` rels g
+
 -- | Get relationships missing their "from" node
 getOrphansFrom :: Graph -> [Relationship]
 getOrphansFrom g = M.elems $ M.filter noNode (rels g)
@@ -183,14 +223,26 @@
 deleteRelationship :: RelIdentifier a => a -> Graph -> Graph
 deleteRelationship r g = g {rels = M.delete (getRelPath r) (rels g),
                             nodeFromRels = removeNodeRef (nodeFromRels g) pathFrom,
-                            nodeToRels = removeNodeRef (nodeToRels g) pathTo}
+                            nodeToRels = removeNodeRef (nodeToRels g) pathTo,
+                            relNames = newRelNames, namedRels = newNamedRels}
     where updNodeRel = const $ HS.delete (getRelPath r)
-          rel = M.lookup (getRelPath r) (rels g)
+          relpath = getRelPath r
+          rel = M.lookup relpath (rels g)
           pathFrom = (getNodePath . relFrom) <$> rel
           pathTo = (getNodePath . relTo) <$> rel
           removeNodeRef nodeRel (Just nodepath) = M.insertWith updNodeRel nodepath HS.empty nodeRel
           removeNodeRef nodeRel Nothing = nodeRel
-
+          relnames = relNames g
+          (mRelName, newRelNames) = fromMaybe (Nothing, relnames) $ do
+              name <- relpath `M.lookup` relnames
+              return (Just name, relpath `M.delete` relnames)
+          namedrels = namedRels g
+          newNamedRels = fromMaybe namedrels $ do
+              relname <- mRelName
+              _relpath <- relname `M.lookup` namedrels
+              return $ if relpath == _relpath
+                 then  relname `M.delete` namedrels
+                 else namedrels
 
 -- | Get the "node from" from a relationship
 getRelationshipNodeFrom :: Relationship -> Graph -> Maybe Node
@@ -241,22 +293,36 @@
 -- | Add two graphs resulting in a graph with all the nodes, labels and relationships of both
 -- | If a node/entity is present in both the second one will be chosen
 union :: Graph -> Graph -> Graph
-union ga gb = addLabels (addRels (addNodes ga gb) gb) gb
+union ga gb = mergeRelNames (mergeNodeNames (addLabels (addRels (addNodes ga gb) gb) gb) gb) gb
     where addRels g1 g2 = foldl (\gacc r -> addRelationship r gacc) g1 (getRelationships g2)
           addNodes g1 g2 = foldl (flip addNode) g1 (getNodes g2)
           addLabels g1 g2 = foldl (\gacc n -> setNodeLabels n (HS.toList $ getNodeLabels n g2) gacc) g1 (getNodes g2)
+          mergeNodeNames g1 g2 = g1 {nodeNames = nodeNames g2 `M.union` nodeNames g1,
+                                     namedNodes = namedNodes g2 `M.union` namedNodes g1}
+          mergeRelNames g1 g2 = g1 {relNames = relNames g2 `M.union` relNames g1,
+                                    namedRels = namedRels g2 `M.union` namedRels g1}
 
 -- | Remove the nodes and relationships in the first graph that appear in the second
 difference :: Graph -> Graph -> Graph
-difference ga gb = relationshipFilter relFilterFunc (nodeFilter nodeFilterFunc ga)
+difference ga gb = relationshipFilter relFilterFunc (nodeFilter nodeFilterFunc ga) {
+        nodeNames = newNodeNames, namedNodes = newNamedNodes, relNames = newRelNames, namedRels = newNamedRels}
     where relFilterFunc r = not $ hasRelationship r gb
           nodeFilterFunc n = not $ hasNode n gb
+          newNodeNames = nodeNames ga `M.difference` nodeNames gb
+          newNamedNodes = namedNodes ga `M.difference` namedNodes gb
+          newRelNames = relNames ga `M.difference` relNames gb
+          newNamedRels = namedRels ga `M.difference` namedRels gb
 
 -- | Have a graph that only has nodes and relationships that are present in both
 intersection :: Graph -> Graph -> Graph
-intersection ga gb = relationshipFilter relFilterFunc (nodeFilter nodeFilterFunc ga)
+intersection ga gb = relationshipFilter relFilterFunc (nodeFilter nodeFilterFunc ga) {
+        nodeNames = newNodeNames, namedNodes = newNamedNodes, relNames = newRelNames, namedRels = newNamedRels}
     where relFilterFunc r = hasRelationship r gb
           nodeFilterFunc n = hasNode n gb
+          newNodeNames = nodeNames ga `M.intersection` nodeNames gb
+          newNamedNodes = namedNodes ga `M.intersection` namedNodes gb
+          newRelNames = relNames ga `M.intersection` relNames gb
+          newNamedRels = namedRels ga `M.intersection` namedRels gb
 
 -- | Feed a cypher result (from the old API) into a graph (looks for nodes and relationships and inserts them)
 addCypher :: C.Response -> Graph -> Graph
diff --git a/src/Database/Neo4j/Types.hs b/src/Database/Neo4j/Types.hs
--- a/src/Database/Neo4j/Types.hs
+++ b/src/Database/Neo4j/Types.hs
@@ -137,6 +137,8 @@
 
 -- | Representation of a Neo4j node, has a location URI and a set of properties
 data Node = Node {nodePath :: NodePath, nodeProperties :: Properties} deriving (Show, Eq)
+instance Ord Node where
+    a <= b = nodePath a <= nodePath b
 
 -- | Get the properties of a node
 getNodeProperties :: Node -> Properties
@@ -160,7 +162,7 @@
 nodeAPITxt :: T.Text
 nodeAPITxt = "/db/data/node"
 
-newtype NodePath = NodePath {runNodePath :: T.Text} deriving (Show, Eq, Generic)
+newtype NodePath = NodePath {runNodePath :: T.Text} deriving (Show, Ord, Eq, Generic)
 instance Hashable NodePath
 
 class NodeIdentifier a where
@@ -188,7 +190,7 @@
 type RelationshipType = T.Text
 
 -- | Relationship direction
-data Direction = Outgoing | Incoming | Any
+data Direction = Outgoing | Incoming | Any deriving (Eq, Show)
 
 -- | Type for a relationship location
 newtype RelUrl = RelUrl {runRelUrl :: T.Text} deriving (Show, Eq, Generic)
@@ -200,6 +202,8 @@
                                   relProperties :: Properties,
                                   relFrom :: NodePath,
                                   relTo :: NodePath} deriving (Show, Eq)
+instance Ord Relationship where
+    a <= b = relPath a <= relPath b
 
 -- | Get the properties of a relationship
 getRelProperties :: Relationship -> Properties
@@ -240,7 +244,7 @@
 relationshipAPITxt :: T.Text
 relationshipAPITxt = "/db/data/relationship"
 
-newtype RelPath = RelPath {runRelPath :: T.Text} deriving (Show, Eq, Generic)
+newtype RelPath = RelPath {runRelPath :: T.Text} deriving (Show, Eq, Ord, Generic)
 instance Hashable RelPath
 
 class RelIdentifier a where
diff --git a/tests/IntegrationTests.hs b/tests/IntegrationTests.hs
--- a/tests/IntegrationTests.hs
+++ b/tests/IntegrationTests.hs
@@ -2,11 +2,14 @@
 {-# LANGUAGE FlexibleInstances, TemplateHaskell #-}
 module Main where
 
+import Control.Applicative ((<$>))
 import Control.Monad (void, join)
 import Control.Monad.IO.Class (MonadIO, liftIO)
+import Data.Default
 import Data.Monoid (Monoid, mappend)
 import Data.Int (Int64)
 import Data.Maybe (fromJust)
+import Data.String (fromString)
 
 import qualified Data.Aeson as J
 import qualified Data.ByteString as S
@@ -15,6 +18,8 @@
 import qualified Data.Text as T
 import qualified Data.Text.Encoding as TE
 import qualified Data.Vector as V
+import qualified Data.List as L
+import qualified Network.HTTP.Types as HT
 
 import Control.Exception (handle)
 import Test.Framework.TH (defaultMainGenerator)
@@ -26,6 +31,7 @@
 import qualified Database.Neo4j.Cypher as C
 import qualified Database.Neo4j.Graph as G
 import qualified Database.Neo4j.Transactional.Cypher as TC
+import qualified Database.Neo4j.Traversal as T
 
 (<>) :: Monoid a => a -> a -> a
 (<>) = mappend
@@ -1590,3 +1596,335 @@
                 neo4jEqual 1 (length $ G.getNodes g4)
                 neo4jEqual (head $ G.getRelationships g) (head $ G.getRelationships g4)
                 neo4jEqual (head $ G.getNodes g) (head $ G.getNodes g4)
+
+-- | Environment for traversal tests
+setUpTraversalTest :: Neo4j G.Graph
+setUpTraversalTest = B.runBatch $ do
+                            root <- _createNode "Root"
+                            johan <- _createNode "Johan"
+                            mattias <- _createNode "Mattias"
+                            emil <- _createNode "Emil"
+                            peter <- _createNode "Peter"
+                            tobias <- _createNode "Tobias"
+                            sara <- _createNode "Sara"
+                            gumersindo <- _createNode "Gumersindo"
+                            _createRel "Root-Johan" "knows" root johan
+                            _createRel "Root-Mattias" "knows" root mattias 
+                            _createRel "Johan-Emil" "knows" johan emil 
+                            _createRel "Emil-Peter" "knows" emil peter
+                            _createRel "Emil-Tobias" "knows" emil tobias
+                            _createRel "Tobias-Sara" "loves" tobias sara
+                            _createRel "Gumersindo-Tobias" "hates" gumersindo tobias
+                            _createRel "Gumersindo-Sara" "admires" sara gumersindo
+    where _createNode name = B.createNamedNode name $ M.fromList ["name" |: (fromString name :: T.Text)]
+          _createRel name t from to = void $ B.createNamedRelationship name t M.empty from to
+
+-- | clean up a traversal test
+cleanUpTraversalTest :: G.Graph -> Neo4j ()
+cleanUpTraversalTest g = void $ B.runBatch $ do
+                            mapM_ B.deleteRelationship (G.getRelationships g)
+                            mapM_ B.deleteNode (G.getNodes g)
+
+
+-- | Test a traversal with an unexisting start
+case_traversalNotFound :: Assertion
+case_traversalNotFound = do
+        g <- withConnection host port $ setUpTraversalTest
+        let start = fromJust $ G.getNamedNode "Root" g
+        let expException = Neo4jNoEntityException $ (TE.encodeUtf8 . runNodePath . nodePath) start
+        assertException expException $ withConnection host port $ do
+            let rels = map (\n -> fromJust $ G.getNamedRelationship n g) ["Root-Johan", "Root-Mattias"]
+            mapM_ deleteRelationship rels
+            deleteNode start
+            void $ T.traverseGetNodes def start
+        withConnection host port $ cleanUpTraversalTest g
+
+-- | Test a default traversal returning nodes
+case_defaultTraversalNodes :: Assertion
+case_defaultTraversalNodes = withConnection host port $ do
+    g <- setUpTraversalTest
+    let start = fromJust $ G.getNamedNode "Root" g
+    ns <- T.traverseGetNodes def start
+    let expected = map (\n -> fromJust $ G.getNamedNode n g) ["Root", "Mattias", "Johan"]
+    neo4jEqual (L.sort expected) (L.sort ns)
+    cleanUpTraversalTest g
+
+-- | Test a default traversal returning relationships
+case_defaultTraversalRels :: Assertion
+case_defaultTraversalRels = withConnection host port $ do
+    g <- setUpTraversalTest
+    let start = fromJust $ G.getNamedNode "Root" g
+    rs <- T.traverseGetRels def start
+    let expected = map (\n -> fromJust $ G.getNamedRelationship n g) ["Root-Mattias", "Root-Johan"]
+    neo4jEqual (L.sort expected) (L.sort rs)
+    cleanUpTraversalTest g
+
+-- | Test a default traversal returning id paths
+case_defaultTraversalIdPath :: Assertion
+case_defaultTraversalIdPath = withConnection host port $ do
+    g <- setUpTraversalTest
+    let start = fromJust $ G.getNamedNode "Root" g
+    ps <- L.sort <$> T.traverseGetPath def start
+    neo4jEqual 3 (length ps)
+    -- check we've received the expected paths
+    let _getNodePath = \name -> nodePath $ fromJust $ G.getNamedNode name g
+    let _getRelPath = \name -> relPath $ fromJust $ G.getNamedRelationship name g
+    let checkPath = \p nodes rels -> do
+        neo4jEqual (map _getNodePath nodes) (T.pathNodes p)
+        let resRels = T.pathRels p
+        neo4jEqual (map _getRelPath (map fst rels)) (map fst resRels)
+        neo4jEqual (map snd rels) (map snd resRels)
+    checkPath (ps !! 0) ["Root"] []
+    checkPath (ps !! 1) ["Root", "Johan"] [("Root-Johan", T.Out)]
+    checkPath (ps !! 2) ["Root", "Mattias"] [("Root-Mattias", T.Out)]
+    cleanUpTraversalTest g
+
+-- | Test a default traversal returning full paths
+case_defaultTraversalFullPath :: Assertion
+case_defaultTraversalFullPath = withConnection host port $ do
+    g <- setUpTraversalTest
+    let start = fromJust $ G.getNamedNode "Root" g
+    ps <- L.sort <$> T.traverseGetFullPath def start
+    neo4jEqual 3 (length ps)
+    -- check we've received the expected paths
+    let _getNode = \name -> fromJust $ G.getNamedNode name g
+    let _getRel = \name -> fromJust $ G.getNamedRelationship name g
+    let checkPath = \p nodes rels -> do
+        neo4jEqual (L.sort $ map _getNode nodes) (L.sort $ T.pathNodes p)
+        neo4jEqual (L.sort $ map _getRel rels) (L.sort $ T.pathRels p)
+    checkPath (ps !! 0) ["Root"] []
+    checkPath (ps !! 1) ["Root", "Johan"] ["Root-Johan"]
+    checkPath (ps !! 2) ["Root", "Mattias"] ["Root-Mattias"]
+    cleanUpTraversalTest g
+
+-- | Test a traversal with an unexisting start
+case_pagedTraversalNotFound :: Assertion
+case_pagedTraversalNotFound = do
+        g <- withConnection host port $ setUpTraversalTest
+        let start = fromJust $ G.getNamedNode "Root" g
+        let expException = Neo4jNoEntityException $ (TE.encodeUtf8 . runNodePath . nodePath) start
+        assertException expException $ withConnection host port $ do
+            let rels = map (\n -> fromJust $ G.getNamedRelationship n g) ["Root-Johan", "Root-Mattias"]
+            mapM_ deleteRelationship rels
+            deleteNode start
+            void $ T.pagedTraverseGetNodes def def start
+        withConnection host port $ cleanUpTraversalTest g
+
+-- | Test a paged traversal returning nodes
+case_pagedTraversalNodes :: Assertion
+case_pagedTraversalNodes = withConnection host port $ do
+    g <- setUpTraversalTest
+    let start = fromJust $ G.getNamedNode "Root" g
+    let desc = def {T.travDepth = Left 2}
+    let paging = def {T.pageSize = 1}
+    pg <- T.pagedTraverseGetNodes desc paging start
+    let _getNode = \name -> fromJust $ G.getNamedNode name g
+    neo4jEqual False (T.pagedTraversalDone pg)
+    neo4jEqual [_getNode "Root"] (T.getPagedValues pg)
+    pg2 <- T.nextTraversalPage pg
+    neo4jEqual False (T.pagedTraversalDone pg2)
+    pg3 <- T.nextTraversalPage pg2
+    neo4jEqual False (T.pagedTraversalDone pg3)
+    neo4jEqual (L.sort $ map _getNode ["Johan", "Mattias"]) (L.sort $ T.getPagedValues pg2 ++ T.getPagedValues pg3)
+    pg4 <- T.nextTraversalPage pg3
+    neo4jEqual False (T.pagedTraversalDone pg4)
+    neo4jEqual [_getNode "Emil"] (T.getPagedValues pg4)
+    pg5 <- T.nextTraversalPage pg4
+    neo4jEqual True (T.pagedTraversalDone pg5)
+    pg6 <- T.nextTraversalPage pg5
+    neo4jEqual True (T.pagedTraversalDone pg6)
+    cleanUpTraversalTest g
+
+-- | Test a paged traversal returning relationships
+case_pagedTraversalRels :: Assertion
+case_pagedTraversalRels = withConnection host port $ do
+    g <- setUpTraversalTest
+    let start = fromJust $ G.getNamedNode "Root" g
+    let desc = def
+    let paging = def {T.pageSize = 1}
+    pg <- T.pagedTraverseGetRels desc paging start
+    let _getRel = \name -> fromJust $ G.getNamedRelationship name g
+    neo4jEqual False (T.pagedTraversalDone pg)
+    pg2 <- T.nextTraversalPage pg
+    neo4jEqual False (T.pagedTraversalDone pg2)
+    pg3 <- T.nextTraversalPage pg2
+    neo4jEqual False (T.pagedTraversalDone pg3)
+    neo4jEqual (L.sort $ map _getRel ["Root-Johan", "Root-Mattias"]) (
+        L.sort $ T.getPagedValues pg ++ T.getPagedValues pg2 ++ T.getPagedValues pg3)
+    pg4 <- T.nextTraversalPage pg3
+    neo4jEqual True (T.pagedTraversalDone pg4)
+    cleanUpTraversalTest g
+
+-- | Test a paged traversal returning id paths 
+case_pagedTraversalIdPaths :: Assertion
+case_pagedTraversalIdPaths = withConnection host port $ do
+    g <- setUpTraversalTest
+    let start = fromJust $ G.getNamedNode "Root" g
+    let desc = def
+    let paging = def {T.pageSize = 1}
+    let _getNodePath = \name -> nodePath $ fromJust $ G.getNamedNode name g
+    let _getRelPath = \name -> relPath $ fromJust $ G.getNamedRelationship name g
+    let checkPath = \p nodes rels -> do
+        neo4jEqual (map _getNodePath nodes) (T.pathNodes p)
+        let resRels = T.pathRels p
+        neo4jEqual (map _getRelPath (map fst rels)) (map fst resRels)
+        neo4jEqual (map snd rels) (map snd resRels)
+    pg <- T.pagedTraverseGetPath desc paging start
+    neo4jEqual False (T.pagedTraversalDone pg)
+    checkPath (T.getPagedValues pg !! 0) ["Root"] []
+    pg2 <- T.nextTraversalPage pg
+    neo4jEqual False (T.pagedTraversalDone pg2)
+    pg3 <- T.nextTraversalPage pg2
+    neo4jEqual False (T.pagedTraversalDone pg3)
+    let ps = L.sort $ T.getPagedValues pg2 ++ T.getPagedValues pg3
+    checkPath (ps !! 0) ["Root", "Johan"] [("Root-Johan", T.Out)]
+    checkPath (ps !! 1) ["Root", "Mattias"] [("Root-Mattias", T.Out)]
+    pg4 <- T.nextTraversalPage pg3
+    neo4jEqual True (T.pagedTraversalDone pg4)
+    cleanUpTraversalTest g
+
+-- | Test a paged traversal returning full paths 
+case_pagedTraversalFullPaths :: Assertion
+case_pagedTraversalFullPaths = withConnection host port $ do
+    g <- setUpTraversalTest
+    let start = fromJust $ G.getNamedNode "Root" g
+    let desc = def
+    let paging = def {T.pageSize = 1}
+    let _getNode = \name -> fromJust $ G.getNamedNode name g
+    let _getRel = \name -> fromJust $ G.getNamedRelationship name g
+    let checkPath = \p nodes rels -> do
+        neo4jEqual (L.sort $ map _getNode nodes) (L.sort $ T.pathNodes p)
+        neo4jEqual (L.sort $ map _getRel rels) (L.sort $ T.pathRels p)
+    pg <- T.pagedTraverseGetFullPath desc paging start
+    neo4jEqual False (T.pagedTraversalDone pg)
+    checkPath (T.getPagedValues pg !! 0) ["Root"] []
+    pg2 <- T.nextTraversalPage pg
+    neo4jEqual False (T.pagedTraversalDone pg2)
+    pg3 <- T.nextTraversalPage pg2
+    neo4jEqual False (T.pagedTraversalDone pg3)
+    let ps = L.sort $ T.getPagedValues pg2 ++ T.getPagedValues pg3
+    checkPath (ps !! 0) ["Root", "Johan"] ["Root-Johan"]
+    checkPath (ps !! 1) ["Root", "Mattias"] ["Root-Mattias"]
+    pg4 <- T.nextTraversalPage pg3
+    neo4jEqual True (T.pagedTraversalDone pg4)
+    cleanUpTraversalTest g
+
+-- | Test traversal depth first search
+case_dfsTraversalNodes :: Assertion
+case_dfsTraversalNodes = withConnection host port $ do
+    g <- setUpTraversalTest
+    let start = fromJust $ G.getNamedNode "Root" g
+    let desc = def {T.travDepth = Left 2, T.travOrder = T.DepthFirst}
+    ns <- T.traverseGetNodes desc start
+    let expected = map (\n -> fromJust $ G.getNamedNode n g) ["Root", "Johan", "Emil", "Mattias"]
+    neo4jEqual (L.sort expected) (L.sort ns)
+    cleanUpTraversalTest g
+
+-- | Test traversal with a relation filter
+case_relFilterTraversalNodes :: Assertion
+case_relFilterTraversalNodes = withConnection host port $ do
+    g <- setUpTraversalTest
+    let start = fromJust $ G.getNamedNode "Tobias" g
+    let desc = def {T.travRelFilter = [("loves", Outgoing)]}
+    ns <- T.traverseGetNodes desc start
+    let expected = map (\n -> fromJust $ G.getNamedNode n g) ["Tobias", "Sara"]
+    neo4jEqual (L.sort expected) (L.sort ns)
+    let desc2 = def {T.travRelFilter = [("hates", Incoming)]}
+    ns2 <- T.traverseGetNodes desc2 start
+    let expected2 = map (\n -> fromJust $ G.getNamedNode n g) ["Tobias", "Gumersindo"]
+    neo4jEqual (L.sort expected2) (L.sort ns2)
+    let desc3 = def {T.travRelFilter = [("hates", Any)]}
+    ns3 <- T.traverseGetNodes desc3 start
+    let expected3 = map (\n -> fromJust $ G.getNamedNode n g) ["Tobias", "Gumersindo"]
+    neo4jEqual (L.sort expected3) (L.sort ns3)
+    let desc4 = def {T.travRelFilter = [("hates", Incoming), ("loves", Outgoing)]}
+    ns4 <- T.traverseGetNodes desc4 start
+    let expected4 = map (\n -> fromJust $ G.getNamedNode n g) ["Tobias", "Sara", "Gumersindo"]
+    neo4jEqual (L.sort expected4) (L.sort ns4)
+    let desc5 = def {T.travRelFilter = [("htes", Incoming)]}
+    ns5 <- T.traverseGetNodes desc5 start
+    let expected5 = map (\n -> fromJust $ G.getNamedNode n g) ["Tobias"]
+    neo4jEqual (L.sort expected5) (L.sort ns5)
+    cleanUpTraversalTest g
+
+-- | Test traversal with a uniqueness constraint
+case_uniquenessTraversalNodes :: Assertion
+case_uniquenessTraversalNodes = withConnection host port $ do
+    g <- setUpTraversalTest
+    let start = fromJust $ G.getNamedNode "Tobias" g
+    let desc = def {T.travDepth = Left 2, T.travRelFilter = [("loves", Any), ("hates", Any), ("admires", Any)]}
+    ns <- T.traverseGetNodes desc start
+    let expected = map (\n -> fromJust $ G.getNamedNode n g) ["Tobias", "Sara", "Gumersindo", "Sara", "Gumersindo"]
+    neo4jEqual (L.sort expected) (L.sort ns)
+    let desc2 = desc {T.travUniqueness = Just T.NodeGlobal}
+    ns2 <- T.traverseGetNodes desc2 start
+    let expected2 = map (\n -> fromJust $ G.getNamedNode n g) ["Tobias", "Sara", "Gumersindo"]
+    neo4jEqual (L.sort expected2) (L.sort ns2)
+    let desc3 = desc {T.travUniqueness = Just T.RelationshipGlobal}
+    ns3 <- T.traverseGetNodes desc3 start
+    let expected3 = map (\n -> fromJust $ G.getNamedNode n g) ["Tobias", "Gumersindo", "Sara", "Gumersindo"]
+    neo4jEqual (L.sort expected3) (L.sort ns3)
+    let desc4 = desc {T.travUniqueness = Just T.NodePathUnique}
+    ns4 <- T.traverseGetNodes desc4 start
+    let expected4 = map (\n -> fromJust $ G.getNamedNode n g) ["Tobias", "Sara", "Gumersindo", "Sara", "Gumersindo"]
+    neo4jEqual (L.sort expected4) (L.sort ns4)
+    let desc5 = desc {T.travUniqueness = Just T.RelationshipPath}
+    ns5 <- T.traverseGetNodes desc5 start
+    let expected5 = map (\n -> fromJust $ G.getNamedNode n g) ["Tobias", "Sara", "Gumersindo", "Sara", "Gumersindo"]
+    neo4jEqual (L.sort expected5) (L.sort ns5)
+    cleanUpTraversalTest g
+
+-- | Test traversal with a javascript depth expression
+case_progDepthTraversalNodes :: Assertion
+case_progDepthTraversalNodes = withConnection host port $ do
+    g <- setUpTraversalTest
+    let start = fromJust $ G.getNamedNode "Root" g
+    let desc = def {T.travDepth = Right "position.length() >= 2;"}
+    ns <- T.traverseGetNodes desc start
+    let expected = map (\n -> fromJust $ G.getNamedNode n g) ["Root", "Johan", "Mattias", "Emil"]
+    neo4jEqual (L.sort expected) (L.sort ns)
+    cleanUpTraversalTest g
+
+-- | Test traversal with a wrong javascript depth expression
+case_wrongProgDepthTraversalNodes :: Assertion
+case_wrongProgDepthTraversalNodes = do
+        g <- withConnection host port $ setUpTraversalTest
+        assertException expException $ withConnection host port $ do
+            let start = fromJust $ G.getNamedNode "Root" g
+            let desc = def {T.travDepth = Right "positionlength() >= 2;"}
+            void $ T.traverseGetNodes desc start
+        withConnection host port $ cleanUpTraversalTest g
+      where expException = Neo4jUnexpectedResponseException HT.status400
+
+-- | Test traversal without initial node
+case_returnButFirstTraversal :: Assertion
+case_returnButFirstTraversal = withConnection host port $ do
+    g <- setUpTraversalTest
+    let start = fromJust $ G.getNamedNode "Root" g
+    let desc = def {T.travNodeFilter = Left T.ReturnAllButStartNode}
+    ns <- T.traverseGetNodes desc start
+    let expected = map (\n -> fromJust $ G.getNamedNode n g) ["Johan", "Mattias"]
+    neo4jEqual (L.sort expected) (L.sort ns)
+    cleanUpTraversalTest g
+
+-- | Test filter nodes without initial node
+case_filterNodesTraversal :: Assertion
+case_filterNodesTraversal = withConnection host port $ do
+    g <- setUpTraversalTest
+    let start = fromJust $ G.getNamedNode "Root" g
+    let desc = def {T.travNodeFilter = Right "position.endNode().getProperty('name').toLowerCase().contains('t');"}
+    ns <- T.traverseGetNodes desc start
+    let expected = map (\n -> fromJust $ G.getNamedNode n g) ["Root", "Mattias"]
+    neo4jEqual (L.sort expected) (L.sort ns)
+    cleanUpTraversalTest g
+
+-- | Test traversal with a filter expression
+case_wrongFilterNodesTraversal :: Assertion
+case_wrongFilterNodesTraversal = do
+        g <- withConnection host port $ setUpTraversalTest
+        assertException expException $ withConnection host port $ do
+            let start = fromJust $ G.getNamedNode "Root" g
+            let desc = def {T.travNodeFilter = Right "posiiiitionlength() >= 2;"}
+            void $ T.traverseGetNodes desc start
+        withConnection host port $ cleanUpTraversalTest g
+      where expException = Neo4jUnexpectedResponseException HT.status400
