From 1d0f33856dc5c51bd7230dd8d72c896adba80ff5 Mon Sep 17 00:00:00 2001
From: thijsheijden <hi@thijsheijden.nl>
Date: Tue, 20 Apr 2021 14:57:16 +0200
Subject: [PATCH] Added convertquery unit tests to cover 91.1% of the
 conversion code

---
 internal/usecases/convertquery/aql.go      |  41 +-
 internal/usecases/convertquery/aql_test.go | 769 ++++++++++++++-------
 2 files changed, 575 insertions(+), 235 deletions(-)

diff --git a/internal/usecases/convertquery/aql.go b/internal/usecases/convertquery/aql.go
index 312a529..ef6ff1e 100644
--- a/internal/usecases/convertquery/aql.go
+++ b/internal/usecases/convertquery/aql.go
@@ -2,6 +2,7 @@ package convertquery
 
 import (
 	"encoding/json"
+	"errors"
 	"fmt"
 )
 
@@ -19,6 +20,34 @@ func (s *Service) ConvertQuery(jsonMsg *[]byte) (*string, error) {
 		return nil, err
 	}
 
+	// Check to make sure all indexes exist
+	// How many entities are there
+	numEntities := len(jsonStruct.Entities) - 1
+	// How many relations there are
+	numRelations := len(jsonStruct.Relations) - 1
+
+	// Make sure no entity should be returned that is outside the range of that list
+	for _, e := range jsonStruct.Return.Entities {
+		// If this entity references an entity that is outside the range
+		if e > numEntities || e < 0 {
+			return nil, errors.New("non-existing entity referenced in return")
+		}
+	}
+
+	// Make sure that no relation mentions a non-existing entity
+	for _, r := range jsonStruct.Relations {
+		if r.EntityFrom > numEntities || r.EntityTo > numEntities {
+			return nil, errors.New("non-exisiting entity referenced in relation")
+		}
+	}
+
+	// Make sure no non-existing relation is tried to be returned
+	for _, r := range jsonStruct.Return.Relations {
+		if r > numRelations || r < 0 {
+			return nil, errors.New("non-existing relation referenced in return")
+		}
+	}
+
 	result := createQuery(jsonStruct)
 	return result, nil
 }
@@ -66,13 +95,21 @@ func createQuery(jsonQuery *parsedJSON) *string {
 			// if there is a from-node
 			// create the let for this node
 			fromName := fmt.Sprintf("n%v", relation.EntityFrom)
-			ret += *createNodeLet(&jsonQuery.Entities[relation.EntityFrom], &fromName)
+
+			// Check if this entity index exists
+			if entity := &jsonQuery.Entities[relation.EntityFrom]; entity != nil {
+				ret += *createNodeLet(entity, &fromName)
+			}
 
 			ret += *createRelationLetWithFromEntity(&relation, relationName, &jsonQuery.Entities, jsonQuery.Limit)
 		} else if relation.EntityTo != -1 {
 			// if there is only a to-node
 			toName := fmt.Sprintf("n%v", relation.EntityTo)
-			ret += *createNodeLet(&jsonQuery.Entities[relation.EntityTo], &toName)
+
+			// Check if this entity index exists
+			if entity := &jsonQuery.Entities[relation.EntityTo]; entity != nil {
+				ret += *createNodeLet(entity, &toName)
+			}
 
 			ret += *createRelationLetWithOnlyToEntity(&relation, relationName, &jsonQuery.Entities, jsonQuery.Limit)
 			// Add this relation to the list
diff --git a/internal/usecases/convertquery/aql_test.go b/internal/usecases/convertquery/aql_test.go
index 8df3168..d025bc5 100644
--- a/internal/usecases/convertquery/aql_test.go
+++ b/internal/usecases/convertquery/aql_test.go
@@ -1,249 +1,552 @@
 package convertquery
 
 import (
+	"errors"
+	"strings"
 	"testing"
 
 	"github.com/stretchr/testify/assert"
 )
 
-func TestMock(t *testing.T) {
+func TestEmptyQueryConversion(t *testing.T) {
+	// Setup for test
+	// Create query conversion service
+	service := NewService()
 
-	// s := `{"Return":{"Entities":[0,1],"Relations":[0]},"Entities":[{"Type":"airports","Constraints":[{"Attribute":"country","Value":"USA","DataType":"text","MatchType":"exact"}]},{"Type":"airports","Constraints":[{"Attribute":"city","Value":"New York","DataType":"text","MatchType":"exact"},{"Attribute":"vip","Value":"true","DataType":"bool","MatchType":"exact"}]}],"Relations":[{"Type":"flights","Depth":{"min":1,"max":1},"EntityFrom":0,"EntityTo":1,"Constraints":[{"Attribute":"Month","Value":"1","DataType":"number","MatchType":"exact"},{"Attribute":"Day","Value":"15","DataType":"number","MatchType":"exact"}]}]}`
+	query := []byte(`{
+		"return": {
+			"entities": [],
+			"relations": []
+		},
+		"entities": [],
+		"relations": [],
+		"limit": 5000
+	}`)
 
-	// s3 := []byte(s)
+	convertedResult, err := service.ConvertQuery(&query)
 
-	// // Convert the json byte msg to a query string
-	// convertQueryService := NewService()
-	// query, err := convertQueryService.ConvertQuery(&s3)
-	// if err != nil {
-	// 	errorhandler.LogError(err, "failed to parse incoming msg to query language") // TODO: send error message to client
-	// 	return
-	// }
-	// fmt.Println("Query: " + *query)
+	// Assert that there is no error
+	assert.NoError(t, err)
 
-	// // Make request to database
-	// // TODO : Generate database seperately
-	// // execute and retrieve result
-	// // convert result to general (node-link (?)) format
-	// requestService := request.NewService()
-	// result, err := requestService.SendAQLQuery(*query)
-	// if err != nil {
-	// 	logger.Log(err.Error())
-	// 	return // TODO: Send message in queue notifying of error
-	// }
+	// Assert that the result and the expected result are the same
+	correctConvertedResult := `
+LET nodes = first(RETURN UNION_DISTINCT([],[]))
+LET edges = first(RETURN UNION_DISTINCT([],[]))
+RETURN {"vertices":nodes, "edges":edges }`
+	assert.Equal(t, correctConvertedResult, *convertedResult)
+}
+
+func TestEntityOneAttributeQuery(t *testing.T) {
+	// Setup for test
+	// Create query conversion service
+	service := NewService()
+
+	query := []byte(`{
+		"return": {
+			"entities": [
+				0
+			],
+			"relations": []
+		},
+		"entities": [
+			{
+				"type": "airports",
+				"constraints": [
+					{
+						"attribute": "state",
+						"value": "HI",
+						"dataType": "text",
+						"matchType": "exact"
+					}
+				]
+			}
+		],
+		"relations": [],
+		"limit": 5000
+	}`)
+
+	convertedResult, err := service.ConvertQuery(&query)
+
+	// Assert that there is no error
+	assert.NoError(t, err)
+
+	// Assert that the result and the expected result are the same
+	correctConvertedResult := `LET n0 = (FOR x IN airports FILTER x.state == "HI" RETURN x)LET nodes = first(RETURN UNION_DISTINCT(n0,[],[]))LET edges = first(RETURN UNION_DISTINCT([],[]))RETURN {"vertices":nodes, "edges":edges }`
+	cleanedResult := strings.ReplaceAll(*convertedResult, "\n", "")
+	cleanedResult = strings.ReplaceAll(cleanedResult, "\t", "")
+	assert.Equal(t, correctConvertedResult, cleanedResult)
+}
+
+func TestRelationWithConstraint(t *testing.T) {
+	// Setup for test
+	// Create query conversion service
+	service := NewService()
+
+	query := []byte(`{
+		"return": {
+			"entities": [
+				0
+			],
+			"relations": [
+				0
+			]
+		},
+		"entities": [
+			{
+				"type": "airports",
+				"constraints": [
+					{
+						"attribute": "state",
+						"value": "HI",
+						"dataType": "text",
+						"matchType": "exact"
+					}
+				]
+			}
+		],
+		"relations": [
+			{
+				"type": "flights",
+				"depth": {
+					"min": 1,
+					"max": 1
+				},
+				"entityFrom": 0,
+				"entityTo": -1,
+				"constraints": [
+					{
+						"attribute": "Day",
+						"value": "15",
+						"dataType": "number",
+						"matchType": "EQ"
+					}
+				]
+			}
+		],
+		"limit": 5000
+	}`)
+
+	convertedResult, err := service.ConvertQuery(&query)
+
+	// Assert that there is no error
+	assert.NoError(t, err)
+
+	// Assert that the result and the expected result are the same
+	correctConvertedResult := `LET n0 = (FOR x IN airports FILTER x.state == "HI" RETURN x)LET r0 = (FOR x IN n0 FOR v, e, p IN 1..1 OUTBOUND x flights OPTIONS { uniqueEdges: "path" }FILTER p.edges[*].Day ALL == 15 LIMIT 5000 RETURN DISTINCT p )LET nodes = first(RETURN UNION_DISTINCT(flatten(r0[**].vertices), [],[]))LET edges = first(RETURN UNION_DISTINCT(flatten(r0[**].edges), [],[]))RETURN {"vertices":nodes, "edges":edges }`
+	cleanedResult := strings.ReplaceAll(*convertedResult, "\n", "")
+	cleanedResult = strings.ReplaceAll(cleanedResult, "\t", "")
+	assert.Equal(t, correctConvertedResult, cleanedResult)
+}
+
+func TestRelationWithInOutConstraint(t *testing.T) {
+	// Setup for test
+	// Create query conversion service
+	service := NewService()
+
+	query := []byte(`{
+		"return": {
+			"entities": [
+				0,
+				1
+			],
+			"relations": [
+				0
+			]
+		},
+		"entities": [
+			{
+				"type": "airports",
+				"constraints": [
+					{
+						"attribute": "city",
+						"value": "San Francisco",
+						"dataType": "text",
+						"matchType": "exact"
+					}
+				]
+			},
+			{
+				"type": "airports",
+				"constraints": [
+					{
+						"attribute": "state",
+						"value": "HI",
+						"dataType": "text",
+						"matchType": "exact"
+					}
+				]
+			}
+		],
+		"relations": [
+			{
+				"type": "flights",
+				"depth": {
+					"min": 1,
+					"max": 3
+				},
+				"entityFrom": 1,
+				"entityTo": 0,
+				"constraints": [
+					{
+						"attribute": "Day",
+						"value": "15",
+						"dataType": "number",
+						"matchType": "EQ"
+					}
+				]
+			}
+		],
+		"limit": 5000
+	}`)
+
+	convertedResult, err := service.ConvertQuery(&query)
+
+	// Assert that there is no error
+	assert.NoError(t, err)
+
+	// Assert that the result and the expected result are the same
+	correctConvertedResult := `LET n1 = (FOR x IN airports FILTER x.state == "HI" RETURN x)LET r0 = (FOR x IN n1 FOR v, e, p IN 1..3 OUTBOUND x flights OPTIONS { uniqueEdges: "path" }FILTER v.city == "San Francisco" FILTER p.edges[*].Day ALL == 15 LIMIT 5000 RETURN DISTINCT p )LET nodes = first(RETURN UNION_DISTINCT(flatten(r0[**].vertices), [],[]))LET edges = first(RETURN UNION_DISTINCT(flatten(r0[**].edges), [],[]))RETURN {"vertices":nodes, "edges":edges }`
+	cleanedResult := strings.ReplaceAll(*convertedResult, "\n", "")
+	cleanedResult = strings.ReplaceAll(cleanedResult, "\t", "")
+	assert.Equal(t, correctConvertedResult, cleanedResult)
+}
+
+func TestTwoRelations(t *testing.T) {
+	// Setup for test
+	// Create query conversion service
+	service := NewService()
+
+	query := []byte(`{
+		"return": {
+			"entities": [
+				0,
+				1,
+				2
+			],
+			"relations": [
+				0,
+				1
+			]
+		},
+		"entities": [
+			{
+				"type": "airports",
+				"constraints": [
+					{
+						"attribute": "city",
+						"value": "New York",
+						"dataType": "text",
+						"matchType": "exact"
+					}
+				]
+			},
+			{
+				"type": "airports",
+				"constraints": [
+					{
+						"attribute": "city",
+						"value": "San Francisco",
+						"dataType": "text",
+						"matchType": "exact"
+					}
+				]
+			},
+			{
+				"type": "airports",
+				"constraints": [
+					{
+						"attribute": "state",
+						"value": "HI",
+						"dataType": "text",
+						"matchType": "exact"
+					}
+				]
+			}
+		],
+		"relations": [
+			{
+				"type": "flights",
+				"depth": {
+					"min": 1,
+					"max": 3
+				},
+				"entityFrom": 2,
+				"entityTo": 1,
+				"constraints": [
+					{
+						"attribute": "Day",
+						"value": "15",
+						"dataType": "number",
+						"matchType": "EQ"
+					}
+				]
+			},
+			{
+				"type": "flights",
+				"depth": {
+					"min": 1,
+					"max": 1
+				},
+				"entityFrom": 0,
+				"entityTo": -1,
+				"constraints": []
+			}
+		],
+		"limit": 5000
+	}`)
+
+	convertedResult, err := service.ConvertQuery(&query)
+
+	// Assert that there is no error
+	assert.NoError(t, err)
+
+	// Assert that the result and the expected result are the same
+	correctConvertedResult := `LET n2 = (FOR x IN airports FILTER x.state == "HI" RETURN x)LET r0 = (FOR x IN n2 FOR v, e, p IN 1..3 OUTBOUND x flights OPTIONS { uniqueEdges: "path" }FILTER v.city == "San Francisco" FILTER p.edges[*].Day ALL == 15 LIMIT 5000 RETURN DISTINCT p )LET n0 = (FOR x IN airports FILTER x.city == "New York" RETURN x)LET r1 = (FOR x IN n0 FOR v, e, p IN 1..1 OUTBOUND x flights OPTIONS { uniqueEdges: "path" }LIMIT 5000 RETURN DISTINCT p )LET nodes = first(RETURN UNION_DISTINCT(flatten(r0[**].vertices), flatten(r1[**].vertices), [],[]))LET edges = first(RETURN UNION_DISTINCT(flatten(r0[**].edges), flatten(r1[**].edges), [],[]))RETURN {"vertices":nodes, "edges":edges }`
+	cleanedResult := strings.ReplaceAll(*convertedResult, "\n", "")
+	cleanedResult = strings.ReplaceAll(cleanedResult, "\t", "")
+	assert.Equal(t, correctConvertedResult, cleanedResult)
+}
+
+func TestRelationWithOnlyToNode(t *testing.T) {
+	// Setup for test
+	// Create query conversion service
+	service := NewService()
+
+	query := []byte(`{
+			"return": {
+				"entities": [
+					0
+				],
+				"relations": [
+					0
+				]
+			},
+			"entities": [
+				{
+					"type": "airports",
+					"constraints": [
+						{
+							"attribute": "city",
+							"value": "San Francisco",
+							"dataType": "text",
+							"matchType": "exact"
+						}
+					]
+				}
+			],
+			"relations": [
+				{
+					"type": "flights",
+					"depth": {
+						"min": 1,
+						"max": 1
+					},
+					"entityFrom": -1,
+					"entityTo": 0,
+					"constraints": []
+				}
+			],
+			"limit": 5000
+		}`)
+
+	convertedResult, err := service.ConvertQuery(&query)
+
+	// Assert that there is no error
+	assert.NoError(t, err)
+
+	// Assert that the result and the expected result are the same
+	correctConvertedResult := `LET n0 = (FOR x IN airports FILTER x.city == "San Francisco" RETURN x)LET r0 = (FOR x IN n0 FOR v, e, p IN 1..1 INBOUND x flights OPTIONS { uniqueEdges: "path" }LIMIT 5000 RETURN DISTINCT p )LET nodes = first(RETURN UNION_DISTINCT(flatten(r0[**].vertices), [],[]))LET edges = first(RETURN UNION_DISTINCT(flatten(r0[**].edges), [],[]))RETURN {"vertices":nodes, "edges":edges }`
+	cleanedResult := strings.ReplaceAll(*convertedResult, "\n", "")
+	cleanedResult = strings.ReplaceAll(cleanedResult, "\t", "")
+	assert.Equal(t, correctConvertedResult, cleanedResult)
+}
+
+func TestTooManyReturnEntities(t *testing.T) {
+	// Setup for test
+	// Create query conversion service
+	service := NewService()
+
+	query := []byte(`{
+			"return": {
+				"entities": [
+					0,
+					1,
+					2
+				],
+				"relations": [
+					0
+				]
+			},
+			"entities": [
+				{
+					"type": "airports",
+					"constraints": [
+						{
+							"attribute": "city",
+							"value": "San Francisco",
+							"dataType": "text",
+							"matchType": "exact"
+						}
+					]
+				}
+			],
+			"relations": [
+				{
+					"type": "flights",
+					"depth": {
+						"min": 1,
+						"max": 1
+					},
+					"entityFrom": -1,
+					"entityTo": 0,
+					"constraints": []
+				}
+			],
+			"limit": 5000
+		}`)
+
+	_, err := service.ConvertQuery(&query)
+
+	// Assert that there is no error
+	assert.Equal(t, errors.New("non-existing entity referenced in return"), err)
+}
 
-	// fmt.Print("QueryResult: ")
-	// fmt.Println(*result)
+func TestTooManyReturnRelations(t *testing.T) {
+	// Setup for test
+	// Create query conversion service
+	service := NewService()
 
-	assert.True(t, true, true)
+	query := []byte(`{
+			"return": {
+				"entities": [
+					0
+				],
+				"relations": [
+					0,
+					1,
+					2
+				]
+			},
+			"entities": [
+				{
+					"type": "airports",
+					"constraints": [
+						{
+							"attribute": "city",
+							"value": "San Francisco",
+							"dataType": "text",
+							"matchType": "exact"
+						}
+					]
+				}
+			],
+			"relations": [
+				{
+					"type": "flights",
+					"depth": {
+						"min": 1,
+						"max": 1
+					},
+					"entityFrom": -1,
+					"entityTo": 0,
+					"constraints": []
+				}
+			],
+			"limit": 5000
+		}`)
+
+	_, err := service.ConvertQuery(&query)
+
+	// Assert that there is no error
+	assert.Equal(t, errors.New("non-existing relation referenced in return"), err)
+}
+
+func TestNegativeReturnEntities(t *testing.T) {
+	// Setup for test
+	// Create query conversion service
+	service := NewService()
+
+	query := []byte(`{
+			"return": {
+				"entities": [
+					0,
+					-1
+				],
+				"relations": [
+					0,
+					1,
+					2
+				]
+			},
+			"entities": [
+				{
+					"type": "airports",
+					"constraints": [
+						{
+							"attribute": "city",
+							"value": "San Francisco",
+							"dataType": "text",
+							"matchType": "exact"
+						}
+					]
+				}
+			],
+			"relations": [
+				{
+					"type": "flights",
+					"depth": {
+						"min": 1,
+						"max": 1
+					},
+					"entityFrom": -1,
+					"entityTo": 0,
+					"constraints": []
+				}
+			],
+			"limit": 5000
+		}`)
+
+	_, err := service.ConvertQuery(&query)
+
+	// Assert that there is no error
+	assert.Equal(t, errors.New("non-existing entity referenced in return"), err)
 }
 
-// func TestHugeQuery(t *testing.T) {
-
-// 	s := `{
-// 		"Return": {
-// 		  "Entities": [
-// 			0,
-// 			1
-// 		  ],
-// 		  "Relations": [
-// 			0
-// 		  ]
-// 		},
-// 		"Entities": [
-// 		  {
-// 			"Type": "airports",
-// 			"Constraints": [
-// 			  {
-// 				"Attribute": "country",
-// 				"Value": "USA",
-// 				"DataType": "text",
-// 				"MatchType": "exact"
-// 			  }
-// 			]
-// 		  },
-// 		  {
-// 			"Type": "airports",
-// 			"Constraints": [
-// 			  {
-// 				"Attribute": "city",
-// 				"Value": "New York",
-// 				"DataType": "text",
-// 				"MatchType": "exact"
-// 			  },
-// 			  {
-// 				"Attribute": "vip",
-// 				"Value": "true",
-// 				"DataType": "bool",
-// 				"MatchType": "exact"
-// 			  }
-// 			]
-// 		  }
-// 		],
-// 		"Relations": [
-// 		  {
-// 			"Type": "flights",
-// 			"Depth": {
-// 			  "min": 1,
-// 			  "max": 1
-// 			},
-// 			"EntityFrom": 0,
-// 			"EntityTo": 1,
-// 			"Constraints": [
-// 			  {
-// 				"Attribute": "Month",
-// 				"Value": "1",
-// 				"DataType": "number",
-// 				"MatchType": "exact"
-// 			  },
-// 			  {
-// 				"Attribute": "Day",
-// 				"Value": "15",
-// 				"DataType": "number",
-// 				"MatchType": "exact"
-// 			  }
-// 			]
-// 		  }
-// 		]
-// 	  }`
-
-// 	s3 := []byte(s)
-// 	convertQueryService := NewService()
-// 	j, _ := convertQueryService.ConvertQuery(&s3)
-
-// 	expected := `LET n0 = (
-// 		FOR x IN airports
-// 		FILTER x.country == "USA"
-// 		RETURN x
-// 	)
-// 	LET r0 = (
-// 		FOR x IN n0
-// 		FOR v, e, p IN 1..1 OUTBOUND x flights
-// 		OPTIONS { uniqueEdges: "path" }
-// 		FILTER v.city == "New York"
-// 		AND v.vip == true
-// 		FILTER p.edges[*].Month ALL == 1
-// 		AND p.edges[*].Day ALL == 15
-// 		LIMIT 1000
-// 	RETURN DISTINCT p )
-
-// 	LET nodes = first(RETURN UNION_DISTINCT(flatten(r0[**].vertices), [],[]))
-// 	LET edges = first(RETURN UNION_DISTINCT(flatten(r0[**].edges), [],[]))
-// 	RETURN {"vertices":nodes, "edges":edges }`
-
-// 	assert.Equal(t, *j, expected)
-// }
-// func TestOnlyEntitiesQuery(t *testing.T) {
-
-// 	s := `{
-// 		"Return": {
-// 		  "Entities": [
-// 			0
-// 		  ],
-// 		  "Relations": []
-// 		},
-// 		"Entities": [
-// 		  {
-// 			"Type": "airports",
-// 			"Constraints": [
-// 			  {
-// 				"Attribute": "city",
-// 				"Value": "New York",
-// 				"DataType": "text",
-// 				"MatchType": "exact"
-// 			  },
-// 			  {
-// 				"Attribute": "country",
-// 				"Value": "USA",
-// 				"DataType": "text",
-// 				"MatchType": "exact"
-// 			  }
-// 			]
-// 		  }
-// 		],
-// 		"Relations": []
-// 	  }`
-
-// 	s3 := []byte(s)
-// 	convertQueryService := NewService()
-// 	j, _ := convertQueryService.ConvertQuery(&s3)
-
-// 	expected := `LET n0 = (
-// 		FOR x IN airports
-// 		FILTER x.city == "New York"
-// 		AND x.country == "USA"
-// 		RETURN x
-// 	)
-
-// 	LET nodes = first(RETURN UNION_DISTINCT(n0,[],[]))
-// 	LET edges = first(RETURN UNION_DISTINCT([],[]))
-// 	RETURN {"vertices":nodes, "edges":edges }`
-
-// 	assert.Equal(t, expected, *j)
-// }
-// func TestInboundQuery(t *testing.T) {
-
-// 	s := `{
-// 		"Return": {
-// 		  "Entities": [
-// 			0
-// 		  ],
-// 		  "Relations": [
-// 			0
-// 		  ]
-// 		},
-// 		"Entities": [
-// 		  {
-// 			"Type": "airports",
-// 			"Constraints": [
-// 					{
-// 						"Attribute": "city",
-// 						"Value": "New York",
-// 						"DataType": "text",
-// 						"MatchType": "exact"
-// 					}
-// 				]
-// 		  }
-// 		],
-// 		"Relations": [
-// 		  {
-// 			"Type": "flights",
-// 			"Depth": {
-// 			  "min": 1,
-// 			  "max": 1
-// 			},
-// 			"EntityFrom": -1,
-// 			"EntityTo": 0,
-// 			"Constraints": [{
-// 				"Attribute": "Day",
-// 				"Value": "15",
-// 				"DataType": "number",
-// 				"MatchType": "exact"
-// 			  }]
-// 		  }
-// 		]
-// 	  }`
-
-// 	s3 := []byte(s)
-// 	convertQueryService := NewService()
-// 	j, _ := convertQueryService.ConvertQuery(&s3)
-
-// 	expected := `LET n0 = (
-// 		FOR x IN airports
-// 		FILTER x.city == "New York"
-// 		RETURN x
-// 	)
-// 	LET r0 = (
-// 		FOR x IN n0
-// 		FOR v, e, p IN 1..1 INBOUND x flights
-// 		OPTIONS { uniqueEdges: "path" }
-// 		FILTER p.edges[*].Day ALL == 15
-// 		LIMIT 1000
-// 	RETURN DISTINCT p )
-
-// 	LET nodes = first(RETURN UNION_DISTINCT(flatten(r0[**].vertices), [],[]))
-// 	LET edges = first(RETURN UNION_DISTINCT(flatten(r0[**].edges), [],[]))
-// 	RETURN {"vertices":nodes, "edges":edges }`
-
-// 	assert.Equal(t, expected, *j)
-// }
+func TestNoRelationsField(t *testing.T) {
+	// Setup for test
+	// Create query conversion service
+	service := NewService()
+
+	query := []byte(`{
+			"return": {
+				"entities": [
+					0
+				]
+			},
+			"entities": [
+				{
+					"type": "airports",
+					"constraints": [
+						{
+							"attribute": "city",
+							"value": "San Francisco",
+							"dataType": "text",
+							"matchType": "exact"
+						}
+					]
+				}
+			],
+			"limit": 5000
+		}`)
+
+	convertedResult, err := service.ConvertQuery(&query)
+
+	// Assert that there is no error
+	assert.NoError(t, err)
+
+	// Assert that the result and the expected result are the same
+	correctConvertedResult := `LET n0 = (FOR x IN airports FILTER x.city == "San Francisco" RETURN x)LET nodes = first(RETURN UNION_DISTINCT(n0,[],[]))LET edges = first(RETURN UNION_DISTINCT([],[]))RETURN {"vertices":nodes, "edges":edges }`
+	cleanedResult := strings.ReplaceAll(*convertedResult, "\n", "")
+	cleanedResult = strings.ReplaceAll(cleanedResult, "\t", "")
+	assert.Equal(t, correctConvertedResult, cleanedResult)
+}
-- 
GitLab