From 3534a7904287224b16dea361480d3e9b32f4a884 Mon Sep 17 00:00:00 2001
From: tarazou9 <40870773+tarazou9@users.noreply.github.com>
Date: Sun, 8 May 2022 22:15:20 -0400
Subject: [PATCH 01/10] Add unit tests and fix a few issues
---
.../MetadataStoreProviderForTest.cs | 8 ++
.../CosmosTests/MutationTests.cs | 55 +++++++++++
.../CosmosTests/QueryTests.cs | 95 +++++++++++++++++++
.../CosmosTests/TestBase.cs | 22 ++++-
.../CosmosTests/TestHelper.cs | 1 +
.../Resolvers/CosmosMutationEngine.cs | 4 +-
.../Resolvers/CosmosQueryEngine.cs | 14 +--
.../Services/GraphQLService.cs | 1 +
8 files changed, 188 insertions(+), 12 deletions(-)
diff --git a/DataGateway.Service.Tests/CosmosTests/MetadataStoreProviderForTest.cs b/DataGateway.Service.Tests/CosmosTests/MetadataStoreProviderForTest.cs
index a3115d85ff..685a004a90 100644
--- a/DataGateway.Service.Tests/CosmosTests/MetadataStoreProviderForTest.cs
+++ b/DataGateway.Service.Tests/CosmosTests/MetadataStoreProviderForTest.cs
@@ -37,6 +37,14 @@ public void StoreMutationResolver(MutationResolver mutationResolver)
MutationResolvers.Add(mutationResolver.Id, mutationResolver);
}
+ public void RemoveMutationResolver(string mutationResolverId)
+ {
+ if(MutationResolvers.ContainsKey(mutationResolverId))
+ {
+ MutationResolvers.Remove(mutationResolverId);
+ }
+ }
+
public void StoreGraphQLType(string name, GraphQLType graphQLType)
{
GraphQLTypes.Add(name, graphQLType);
diff --git a/DataGateway.Service.Tests/CosmosTests/MutationTests.cs b/DataGateway.Service.Tests/CosmosTests/MutationTests.cs
index 9621df58e9..5b1b3ab5f9 100644
--- a/DataGateway.Service.Tests/CosmosTests/MutationTests.cs
+++ b/DataGateway.Service.Tests/CosmosTests/MutationTests.cs
@@ -116,6 +116,61 @@ public async Task CanDeleteItemWithoutVariables()
Assert.IsNull(response.GetProperty("id").GetString());
}
+ [TestMethod]
+ public async Task MutationMissingInputReturnError()
+ {
+ // Run mutation Add planet without any input
+ string mutation = $@"
+mutation {{
+ addPlanet () {{
+ id
+ name
+ }}
+}}";
+ JsonElement response = await ExecuteGraphQLRequestAsync("addPlanet", mutation, new());
+ Assert.AreEqual("inputDict is missing", response[0].GetProperty("message").ToString());
+ }
+
+ [TestMethod]
+ public async Task MutationMissingRequiredIdReturnError()
+ {
+ // Run mutation Add planet without id
+ const string name = "test_name";
+ string mutation = $@"
+mutation {{
+ addPlanet ( name: ""{name}"") {{
+ id
+ name
+ }}
+}}";
+ JsonElement response = await ExecuteGraphQLRequestAsync("addPlanet", mutation, new());
+ Assert.AreEqual("id field is mandatory", response[0].GetProperty("message").ToString());
+ }
+
+ [TestMethod]
+ public async Task InvalidResolverOperationTypeReturnError()
+ {
+ //Register invalid operation type resolver
+ RemoveMutationResolver("addPlanet");
+ RegisterMutationResolver("addPlanet", DATABASE_NAME, _containerName, "None");
+
+ string id = Guid.NewGuid().ToString();
+ const string name = "test_name";
+ string addMutation = $@"
+mutation {{
+ addPlanet (id: ""{id}"", name: ""{name}"") {{
+ id
+ name
+ }}
+}}";
+ JsonElement response = await ExecuteGraphQLRequestAsync("addPlanet", addMutation, new());
+ Assert.AreEqual("unsupported operation type: None", response[0].GetProperty("message").ToString());
+
+ //Register valid mutation resolver back after testing invalid senario
+ RemoveMutationResolver("addPlanet");
+ RegisterMutationResolver("addPlanet", DATABASE_NAME, _containerName);
+ }
+
///
/// Runs once after all tests in this class are executed
///
diff --git a/DataGateway.Service.Tests/CosmosTests/QueryTests.cs b/DataGateway.Service.Tests/CosmosTests/QueryTests.cs
index 8d111d7c1f..a28b410158 100644
--- a/DataGateway.Service.Tests/CosmosTests/QueryTests.cs
+++ b/DataGateway.Service.Tests/CosmosTests/QueryTests.cs
@@ -1,8 +1,10 @@
using System;
using System.Collections.Generic;
+using System.Linq;
using System.Text.Json;
using System.Threading.Tasks;
using Microsoft.VisualStudio.TestTools.UnitTesting;
+using Newtonsoft.Json.Linq;
namespace Azure.DataGateway.Service.Tests.CosmosTests
{
@@ -69,10 +71,14 @@ public async Task GetPaginatedWithVariables()
// Run query
JsonElement response = await ExecuteGraphQLRequestAsync("planetList", PlanetListQuery);
int actualElements = response.GetArrayLength();
+ JArray responseTotal = new();
+ ConvertJsonElementToJArray(response, responseTotal);
+
// Run paginated query
int totalElementsFromPaginatedQuery = 0;
string continuationToken = null;
const int pagesize = 5;
+ JArray pagedResponse = new();
do
{
@@ -80,10 +86,12 @@ public async Task GetPaginatedWithVariables()
JsonElement continuation = page.GetProperty("endCursor");
continuationToken = continuation.ToString();
totalElementsFromPaginatedQuery += page.GetProperty("items").GetArrayLength();
+ ConvertJsonElementToJArray(page.GetProperty("items"), pagedResponse);
} while (!string.IsNullOrEmpty(continuationToken));
// Validate results
Assert.AreEqual(actualElements, totalElementsFromPaginatedQuery);
+ Assert.IsTrue(JArray.DeepEquals(responseTotal, pagedResponse));
}
[TestMethod]
@@ -110,10 +118,14 @@ public async Task GetPaginatedWithoutVariables()
// Run query
JsonElement response = await ExecuteGraphQLRequestAsync("planetList", PlanetListQuery);
int actualElements = response.GetArrayLength();
+ JArray responseTotal = new();
+ ConvertJsonElementToJArray(response, responseTotal);
+
// Run paginated query
int totalElementsFromPaginatedQuery = 0;
string continuationToken = null;
const int pagesize = 5;
+ JArray pagedResponse = new();
do
{
@@ -133,12 +145,95 @@ public async Task GetPaginatedWithoutVariables()
JsonElement continuation = page.GetProperty("endCursor");
continuationToken = continuation.ToString();
totalElementsFromPaginatedQuery += page.GetProperty("items").GetArrayLength();
+ ConvertJsonElementToJArray(page.GetProperty("items"), pagedResponse);
} while (!string.IsNullOrEmpty(continuationToken));
// Validate results
Assert.AreEqual(actualElements, totalElementsFromPaginatedQuery);
}
+ ///
+ /// Query List Type with input parameters
+ ///
+ ///
+ [TestMethod]
+ public async Task GetListTypeWithParameters()
+ {
+ string id = _idList[0];
+ string query = @$"
+query {{
+ getPlanetListById (id: ""{id}"") {{
+ id
+ name
+ }}
+}}";
+
+ JsonElement response = await ExecuteGraphQLRequestAsync("getPlanetListById", query);
+
+ // Validate results
+ Assert.AreEqual(1, response.GetArrayLength());
+ Assert.AreEqual(id, response[0].GetProperty("id").ToString());
+ }
+
+ ///
+ /// Query single item by non-primary key field, found no match
+ ///
+ ///
+ [TestMethod]
+ public async Task GetByNonePrimaryFieldResultNotFound()
+ {
+ //string name = "test name";
+ string name = "non-existed name";
+ string query = @$"
+query {{
+ getPlanetByName (name: ""{name}"") {{
+ id
+ name
+ }}
+}}";
+
+ JsonElement response = await ExecuteGraphQLRequestAsync("getPlanetByName", query);
+
+ // Validate results
+ Assert.IsNull(response.Deserialize());
+ }
+
+ ///
+ /// Query single item by non-primary key field, found no match
+ ///
+ ///
+ [TestMethod]
+ public async Task GetByNonePrimaryFieldReturnsResult()
+ {
+ string name = "test name";
+ string query = @$"
+query {{
+ getPlanetByName (name: ""{name}"") {{
+ id
+ name
+ }}
+}}";
+
+ JsonElement response = await ExecuteGraphQLRequestAsync("getPlanetByName", query);
+
+ // Validate results
+ Assert.AreEqual(name, response.GetProperty("name").ToString());
+ }
+
+ private static void ConvertJsonElementToJArray(JsonElement ele, JArray jObj)
+ {
+ if (ele.ValueKind == JsonValueKind.Array)
+ {
+ JsonElement.ArrayEnumerator enumerator = ele.EnumerateArray();
+
+ while (enumerator.MoveNext())
+ {
+ JsonElement prop = enumerator.Current;
+ jObj.Add(prop.ToString());
+ }
+ }
+ }
+
///
/// Runs once after all tests in this class are executed
///
diff --git a/DataGateway.Service.Tests/CosmosTests/TestBase.cs b/DataGateway.Service.Tests/CosmosTests/TestBase.cs
index 834dbc0ea1..a21d00fd7b 100644
--- a/DataGateway.Service.Tests/CosmosTests/TestBase.cs
+++ b/DataGateway.Service.Tests/CosmosTests/TestBase.cs
@@ -2,6 +2,7 @@
using System.Collections.Generic;
using System.IO;
using System.Net.Http;
+using System.Security.Claims;
using System.Text;
using System.Text.Json;
using System.Threading.Tasks;
@@ -42,6 +43,8 @@ type Query {
getPlanet(id: ID, name: String): Planet
planetList: [Planet]
planets(first: Int, after: String): PlanetConnection
+ getPlanetListById(id: ID): [Planet]
+ getPlanetByName(name: String): Planet
}
type Mutation {
@@ -66,7 +69,8 @@ type Character {
type Planet {
id : ID,
name : String
-}";
+}
+";
_metadataStoreProvider.GraphQLSchema = jsonString;
_queryEngine = new CosmosQueryEngine(_clientProvider, _metadataStoreProvider);
_mutationEngine = new CosmosMutationEngine(_clientProvider, _metadataStoreProvider);
@@ -101,9 +105,11 @@ private static DefaultHttpContext GetHttpContextWithBody(string data)
HttpRequestMessage request = new();
MemoryStream stream = new(Encoding.UTF8.GetBytes(data));
request.Method = HttpMethod.Post;
+ ClaimsPrincipal user = new(new ClaimsIdentity(new Claim[] { new Claim(ClaimTypes.Name, "test@microsoft.com") }, "TestAuthentication"));
DefaultHttpContext httpContext = new()
{
- Request = { Body = stream, ContentLength = stream.Length }
+ Request = { Body = stream, ContentLength = stream.Length },
+ User = user
};
return httpContext;
}
@@ -131,6 +137,15 @@ internal static void RegisterMutationResolver(string id,
_metadataStoreProvider.StoreMutationResolver(mutationResolver);
}
+ ///
+ ///
+ ///
+ /// name of the mutation
+ internal static void RemoveMutationResolver(string id)
+ {
+ _metadataStoreProvider.RemoveMutationResolver(id);
+ }
+
///
/// Creates and registers a GraphQLType
///
@@ -174,7 +189,8 @@ internal static async Task ExecuteGraphQLRequestAsync(string queryN
if (graphQLResult.TryGetProperty("errors", out JsonElement errors))
{
- Assert.Fail(errors.GetRawText());
+ // to validate expected errors and error message
+ return errors;
}
return graphQLResult.GetProperty("data").GetProperty(queryName);
diff --git a/DataGateway.Service.Tests/CosmosTests/TestHelper.cs b/DataGateway.Service.Tests/CosmosTests/TestHelper.cs
index cc932c1e83..c4313a2fc3 100644
--- a/DataGateway.Service.Tests/CosmosTests/TestHelper.cs
+++ b/DataGateway.Service.Tests/CosmosTests/TestHelper.cs
@@ -43,6 +43,7 @@ public static object GetItem(string id)
return new
{
id = id,
+ name = "test name",
myProp = "a value",
myIntProp = 4,
myBooleanProp = true,
diff --git a/DataGateway.Service/Resolvers/CosmosMutationEngine.cs b/DataGateway.Service/Resolvers/CosmosMutationEngine.cs
index bdba73fbf6..66ee4e18ba 100644
--- a/DataGateway.Service/Resolvers/CosmosMutationEngine.cs
+++ b/DataGateway.Service/Resolvers/CosmosMutationEngine.cs
@@ -32,7 +32,7 @@ private async Task ExecuteAsync(IDictionary inputDict,
JObject jObject;
- if (inputDict != null)
+ if (inputDict != null && inputDict.Count > 0)
{
// TODO: optimize this multiple round of serialization/deserialization
string json = JsonConvert.SerializeObject(inputDict);
@@ -75,7 +75,7 @@ private async Task ExecuteAsync(IDictionary inputDict,
break;
default:
- throw new NotSupportedException($"unsupprted operation type: {resolver.OperationType.ToString()}");
+ throw new NotSupportedException($"unsupported operation type: {resolver.OperationType.ToString()}");
}
return response.Resource;
diff --git a/DataGateway.Service/Resolvers/CosmosQueryEngine.cs b/DataGateway.Service/Resolvers/CosmosQueryEngine.cs
index dd32aec7e4..3f9619cec0 100644
--- a/DataGateway.Service/Resolvers/CosmosQueryEngine.cs
+++ b/DataGateway.Service/Resolvers/CosmosQueryEngine.cs
@@ -94,14 +94,14 @@ public async Task> ExecuteAsync(IMiddlewareContex
return new Tuple(JsonDocument.Parse(res.ToString()), null);
}
- static JObject FindFirstItem(IEnumerator iterator)
+ if (firstPage.Count == 0)
{
- JObject firstItem;
- if (iterator.MoveNext() && (firstItem = iterator.Current) == null)
- {
- return FindFirstItem(iterator);
- }
+ return new Tuple(null, null);
+ }
+ static JObject FindFirstItem(IEnumerator iterator)
+ {
+ iterator.MoveNext();
return iterator.Current;
}
@@ -126,7 +126,7 @@ public async Task, IMetadata>> ExecuteListAsync(
if (parameters != null)
{
- foreach (KeyValuePair parameterEntry in parameters)
+ foreach (KeyValuePair parameterEntry in structure.Parameters)
{
querySpec.WithParameter("@" + parameterEntry.Key, parameterEntry.Value);
}
diff --git a/DataGateway.Service/Services/GraphQLService.cs b/DataGateway.Service/Services/GraphQLService.cs
index 0d766e88f4..9cc0014072 100644
--- a/DataGateway.Service/Services/GraphQLService.cs
+++ b/DataGateway.Service/Services/GraphQLService.cs
@@ -60,6 +60,7 @@ public void ParseAsync(string data)
{
Console.Error.WriteLine(error.Exception.Message);
Console.Error.WriteLine(error.Exception.StackTrace);
+ return error.WithMessage(error.Exception!.Message);
}
return error;
From cd9138e09cfff1e2225b5419a14e2d7081bec41e Mon Sep 17 00:00:00 2001
From: tarazou9 <40870773+tarazou9@users.noreply.github.com>
Date: Sun, 8 May 2022 22:19:25 -0400
Subject: [PATCH 02/10] Add more assert
---
DataGateway.Service.Tests/CosmosTests/QueryTests.cs | 1 +
1 file changed, 1 insertion(+)
diff --git a/DataGateway.Service.Tests/CosmosTests/QueryTests.cs b/DataGateway.Service.Tests/CosmosTests/QueryTests.cs
index a28b410158..ec9932ee8f 100644
--- a/DataGateway.Service.Tests/CosmosTests/QueryTests.cs
+++ b/DataGateway.Service.Tests/CosmosTests/QueryTests.cs
@@ -150,6 +150,7 @@ public async Task GetPaginatedWithoutVariables()
// Validate results
Assert.AreEqual(actualElements, totalElementsFromPaginatedQuery);
+ Assert.IsTrue(JArray.DeepEquals(responseTotal, pagedResponse));
}
///
From fe3eb55f9f1f89a51dae2570c1858498efa041a7 Mon Sep 17 00:00:00 2001
From: tarazou9 <40870773+tarazou9@users.noreply.github.com>
Date: Mon, 9 May 2022 11:11:14 -0400
Subject: [PATCH 03/10] Fix format
---
.../CosmosTests/MetadataStoreProviderForTest.cs | 2 +-
DataGateway.Service.Tests/CosmosTests/QueryTests.cs | 1 -
2 files changed, 1 insertion(+), 2 deletions(-)
diff --git a/DataGateway.Service.Tests/CosmosTests/MetadataStoreProviderForTest.cs b/DataGateway.Service.Tests/CosmosTests/MetadataStoreProviderForTest.cs
index 685a004a90..d9b36623c3 100644
--- a/DataGateway.Service.Tests/CosmosTests/MetadataStoreProviderForTest.cs
+++ b/DataGateway.Service.Tests/CosmosTests/MetadataStoreProviderForTest.cs
@@ -39,7 +39,7 @@ public void StoreMutationResolver(MutationResolver mutationResolver)
public void RemoveMutationResolver(string mutationResolverId)
{
- if(MutationResolvers.ContainsKey(mutationResolverId))
+ if (MutationResolvers.ContainsKey(mutationResolverId))
{
MutationResolvers.Remove(mutationResolverId);
}
diff --git a/DataGateway.Service.Tests/CosmosTests/QueryTests.cs b/DataGateway.Service.Tests/CosmosTests/QueryTests.cs
index ec9932ee8f..bff83f63ea 100644
--- a/DataGateway.Service.Tests/CosmosTests/QueryTests.cs
+++ b/DataGateway.Service.Tests/CosmosTests/QueryTests.cs
@@ -1,6 +1,5 @@
using System;
using System.Collections.Generic;
-using System.Linq;
using System.Text.Json;
using System.Threading.Tasks;
using Microsoft.VisualStudio.TestTools.UnitTesting;
From 41e392531407af40db6da54684ce281e7d15282b Mon Sep 17 00:00:00 2001
From: tarazou9 <40870773+tarazou9@users.noreply.github.com>
Date: Tue, 10 May 2022 09:45:24 -0400
Subject: [PATCH 04/10] Add tests for inner objects and fix an issue related to
query with inner object, also address PR comments
---
.../CosmosTests/MutationTests.cs | 2 +-
.../CosmosTests/QueryTests.cs | 53 ++++++++++++++-----
.../CosmosTests/TestBase.cs | 5 +-
.../CosmosTests/TestHelper.cs | 8 +++
.../Resolvers/CosmosQueryEngine.cs | 23 ++------
.../Resolvers/CosmosQueryStructure.cs | 4 +-
.../Services/GraphQLService.cs | 2 +-
7 files changed, 58 insertions(+), 39 deletions(-)
diff --git a/DataGateway.Service.Tests/CosmosTests/MutationTests.cs b/DataGateway.Service.Tests/CosmosTests/MutationTests.cs
index 5b1b3ab5f9..bb001888ca 100644
--- a/DataGateway.Service.Tests/CosmosTests/MutationTests.cs
+++ b/DataGateway.Service.Tests/CosmosTests/MutationTests.cs
@@ -122,7 +122,7 @@ public async Task MutationMissingInputReturnError()
// Run mutation Add planet without any input
string mutation = $@"
mutation {{
- addPlanet () {{
+ addPlanet {{
id
name
}}
diff --git a/DataGateway.Service.Tests/CosmosTests/QueryTests.cs b/DataGateway.Service.Tests/CosmosTests/QueryTests.cs
index bff83f63ea..f827c74109 100644
--- a/DataGateway.Service.Tests/CosmosTests/QueryTests.cs
+++ b/DataGateway.Service.Tests/CosmosTests/QueryTests.cs
@@ -1,9 +1,9 @@
using System;
using System.Collections.Generic;
+using System.Linq;
using System.Text.Json;
using System.Threading.Tasks;
using Microsoft.VisualStudio.TestTools.UnitTesting;
-using Newtonsoft.Json.Linq;
namespace Azure.DataGateway.Service.Tests.CosmosTests
{
@@ -70,14 +70,14 @@ public async Task GetPaginatedWithVariables()
// Run query
JsonElement response = await ExecuteGraphQLRequestAsync("planetList", PlanetListQuery);
int actualElements = response.GetArrayLength();
- JArray responseTotal = new();
- ConvertJsonElementToJArray(response, responseTotal);
+ List responseTotal = new();
+ ConvertJsonElementToStringList(response, responseTotal);
// Run paginated query
int totalElementsFromPaginatedQuery = 0;
string continuationToken = null;
const int pagesize = 5;
- JArray pagedResponse = new();
+ List pagedResponse = new();
do
{
@@ -85,12 +85,12 @@ public async Task GetPaginatedWithVariables()
JsonElement continuation = page.GetProperty("endCursor");
continuationToken = continuation.ToString();
totalElementsFromPaginatedQuery += page.GetProperty("items").GetArrayLength();
- ConvertJsonElementToJArray(page.GetProperty("items"), pagedResponse);
+ ConvertJsonElementToStringList(page.GetProperty("items"), pagedResponse);
} while (!string.IsNullOrEmpty(continuationToken));
// Validate results
Assert.AreEqual(actualElements, totalElementsFromPaginatedQuery);
- Assert.IsTrue(JArray.DeepEquals(responseTotal, pagedResponse));
+ Assert.IsTrue(responseTotal.SequenceEqual(pagedResponse));
}
[TestMethod]
@@ -117,14 +117,14 @@ public async Task GetPaginatedWithoutVariables()
// Run query
JsonElement response = await ExecuteGraphQLRequestAsync("planetList", PlanetListQuery);
int actualElements = response.GetArrayLength();
- JArray responseTotal = new();
- ConvertJsonElementToJArray(response, responseTotal);
+ List responseTotal = new();
+ ConvertJsonElementToStringList(response, responseTotal);
// Run paginated query
int totalElementsFromPaginatedQuery = 0;
string continuationToken = null;
const int pagesize = 5;
- JArray pagedResponse = new();
+ List pagedResponse = new();
do
{
@@ -144,12 +144,12 @@ public async Task GetPaginatedWithoutVariables()
JsonElement continuation = page.GetProperty("endCursor");
continuationToken = continuation.ToString();
totalElementsFromPaginatedQuery += page.GetProperty("items").GetArrayLength();
- ConvertJsonElementToJArray(page.GetProperty("items"), pagedResponse);
+ ConvertJsonElementToStringList(page.GetProperty("items"), pagedResponse);
} while (!string.IsNullOrEmpty(continuationToken));
// Validate results
Assert.AreEqual(actualElements, totalElementsFromPaginatedQuery);
- Assert.IsTrue(JArray.DeepEquals(responseTotal, pagedResponse));
+ Assert.IsTrue(responseTotal.SequenceEqual(pagedResponse));
}
///
@@ -182,7 +182,6 @@ public async Task GetListTypeWithParameters()
[TestMethod]
public async Task GetByNonePrimaryFieldResultNotFound()
{
- //string name = "test name";
string name = "non-existed name";
string query = @$"
query {{
@@ -220,7 +219,33 @@ public async Task GetByNonePrimaryFieldReturnsResult()
Assert.AreEqual(name, response.GetProperty("name").ToString());
}
- private static void ConvertJsonElementToJArray(JsonElement ele, JArray jObj)
+ ///
+ /// Query result with nested object
+ ///
+ ///
+ [TestMethod]
+ public async Task GetByPrimaryKeyWithInnerObject()
+ {
+ // Run query
+ string id = _idList[0];
+ string query = @$"
+query {{
+ planetById (id: ""{id}"") {{
+ id
+ name
+ character {{
+ id
+ name
+ }}
+ }}
+}}";
+ JsonElement response = await ExecuteGraphQLRequestAsync("planetById", query);
+
+ // Validate results
+ Assert.AreEqual(id, response.GetProperty("id").GetString());
+ }
+
+ private static void ConvertJsonElementToStringList(JsonElement ele, List strList)
{
if (ele.ValueKind == JsonValueKind.Array)
{
@@ -229,7 +254,7 @@ private static void ConvertJsonElementToJArray(JsonElement ele, JArray jObj)
while (enumerator.MoveNext())
{
JsonElement prop = enumerator.Current;
- jObj.Add(prop.ToString());
+ strList.Add(prop.ToString());
}
}
}
diff --git a/DataGateway.Service.Tests/CosmosTests/TestBase.cs b/DataGateway.Service.Tests/CosmosTests/TestBase.cs
index a21d00fd7b..f8e387d73c 100644
--- a/DataGateway.Service.Tests/CosmosTests/TestBase.cs
+++ b/DataGateway.Service.Tests/CosmosTests/TestBase.cs
@@ -68,7 +68,8 @@ type Character {
type Planet {
id : ID,
- name : String
+ name : String,
+ character: Character
}
";
_metadataStoreProvider.GraphQLSchema = jsonString;
@@ -105,7 +106,7 @@ private static DefaultHttpContext GetHttpContextWithBody(string data)
HttpRequestMessage request = new();
MemoryStream stream = new(Encoding.UTF8.GetBytes(data));
request.Method = HttpMethod.Post;
- ClaimsPrincipal user = new(new ClaimsIdentity(new Claim[] { new Claim(ClaimTypes.Name, "test@microsoft.com") }, "TestAuthentication"));
+ ClaimsPrincipal user = new(new ClaimsIdentity(authenticationType: "Bearer"));
DefaultHttpContext httpContext = new()
{
Request = { Body = stream, ContentLength = stream.Length },
diff --git a/DataGateway.Service.Tests/CosmosTests/TestHelper.cs b/DataGateway.Service.Tests/CosmosTests/TestHelper.cs
index c4313a2fc3..31900f1b2b 100644
--- a/DataGateway.Service.Tests/CosmosTests/TestHelper.cs
+++ b/DataGateway.Service.Tests/CosmosTests/TestHelper.cs
@@ -57,6 +57,14 @@ public static object GetItem(string id)
lastName = "the last name",
zipCode = 784298
}
+ },
+ character = new
+ {
+ id = id,
+ name = "planet character",
+ type = "Mars",
+ homePlanet = 1,
+ primaryFunction = "test function"
}
};
}
diff --git a/DataGateway.Service/Resolvers/CosmosQueryEngine.cs b/DataGateway.Service/Resolvers/CosmosQueryEngine.cs
index 3f9619cec0..b97fdd95e9 100644
--- a/DataGateway.Service/Resolvers/CosmosQueryEngine.cs
+++ b/DataGateway.Service/Resolvers/CosmosQueryEngine.cs
@@ -1,6 +1,7 @@
# nullable disable
using System;
using System.Collections.Generic;
+using System.Linq;
using System.Text;
using System.Text.Json;
using System.Threading.Tasks;
@@ -94,20 +95,7 @@ public async Task> ExecuteAsync(IMiddlewareContex
return new Tuple(JsonDocument.Parse(res.ToString()), null);
}
- if (firstPage.Count == 0)
- {
- return new Tuple(null, null);
- }
-
- static JObject FindFirstItem(IEnumerator iterator)
- {
- iterator.MoveNext();
- return iterator.Current;
- }
-
- JObject firstItem = FindFirstItem(firstPage.GetEnumerator());
-
- JsonDocument jsonDocument = JsonDocument.Parse(firstItem.ToString());
+ JsonDocument jsonDocument = (firstPage.Count == 0) ? null : JsonDocument.Parse(firstPage.FirstOrDefault().ToString());
return new Tuple(jsonDocument, null);
}
@@ -124,12 +112,9 @@ public async Task, IMetadata>> ExecuteListAsync(
Container container = _clientProvider.Client.GetDatabase(structure.Database).GetContainer(structure.Container);
QueryDefinition querySpec = new(_queryBuilder.Build(structure));
- if (parameters != null)
+ foreach (KeyValuePair parameterEntry in structure.Parameters)
{
- foreach (KeyValuePair parameterEntry in structure.Parameters)
- {
- querySpec.WithParameter("@" + parameterEntry.Key, parameterEntry.Value);
- }
+ querySpec.WithParameter("@" + parameterEntry.Key, parameterEntry.Value);
}
FeedIterator resultSetIterator = container.GetItemQueryIterator(querySpec);
diff --git a/DataGateway.Service/Resolvers/CosmosQueryStructure.cs b/DataGateway.Service/Resolvers/CosmosQueryStructure.cs
index 6b9aaedd9f..d033b6b048 100644
--- a/DataGateway.Service/Resolvers/CosmosQueryStructure.cs
+++ b/DataGateway.Service/Resolvers/CosmosQueryStructure.cs
@@ -46,12 +46,12 @@ private void Init(IDictionary queryParams)
if (fieldNode != null)
{
- Columns.AddRange(fieldNode.SelectionSet!.Selections.Select(x => new LabelledColumn(_containerAlias, "", x.ToString())));
+ Columns.AddRange(fieldNode.SelectionSet!.Selections.Select(x => new LabelledColumn(_containerAlias, "", x.GetNodes().First().ToString())));
}
}
else
{
- Columns.AddRange(selection.SyntaxNode.SelectionSet!.Selections.Select(x => new LabelledColumn(_containerAlias, "", x.ToString())));
+ Columns.AddRange(selection.SyntaxNode.SelectionSet!.Selections.Select(x => new LabelledColumn(_containerAlias, "", x.GetNodes().First().ToString())));
}
Container = graphqlType.ContainerName;
diff --git a/DataGateway.Service/Services/GraphQLService.cs b/DataGateway.Service/Services/GraphQLService.cs
index 9cc0014072..6433f0f3f8 100644
--- a/DataGateway.Service/Services/GraphQLService.cs
+++ b/DataGateway.Service/Services/GraphQLService.cs
@@ -60,7 +60,7 @@ public void ParseAsync(string data)
{
Console.Error.WriteLine(error.Exception.Message);
Console.Error.WriteLine(error.Exception.StackTrace);
- return error.WithMessage(error.Exception!.Message);
+ return error.WithMessage(error.Exception.Message);
}
return error;
From b70f0384e643cddc4cb79b1cd94140b50825e539 Mon Sep 17 00:00:00 2001
From: tarazou9 <40870773+tarazou9@users.noreply.github.com>
Date: Tue, 10 May 2022 14:29:45 -0400
Subject: [PATCH 05/10] add named argument for tests
---
.../CosmosTests/MutationTests.cs | 12 ++++++------
DataGateway.Service.Tests/CosmosTests/QueryTests.cs | 2 +-
2 files changed, 7 insertions(+), 7 deletions(-)
diff --git a/DataGateway.Service.Tests/CosmosTests/MutationTests.cs b/DataGateway.Service.Tests/CosmosTests/MutationTests.cs
index bb001888ca..6b82c0a396 100644
--- a/DataGateway.Service.Tests/CosmosTests/MutationTests.cs
+++ b/DataGateway.Service.Tests/CosmosTests/MutationTests.cs
@@ -81,7 +81,7 @@ public async Task CanCreateItemWithoutVariables()
name
}}
}}";
- JsonElement response = await ExecuteGraphQLRequestAsync("addPlanet", mutation, new());
+ JsonElement response = await ExecuteGraphQLRequestAsync("addPlanet", mutation, variables: new());
// Validate results
Assert.AreEqual(id, response.GetProperty("id").GetString());
@@ -100,7 +100,7 @@ public async Task CanDeleteItemWithoutVariables()
name
}}
}}";
- _ = await ExecuteGraphQLRequestAsync("addPlanet", addMutation, new());
+ _ = await ExecuteGraphQLRequestAsync("addPlanet", addMutation, variables: new());
// Run mutation delete item;
string deleteMutation = $@"
@@ -110,7 +110,7 @@ public async Task CanDeleteItemWithoutVariables()
name
}}
}}";
- JsonElement response = await ExecuteGraphQLRequestAsync("deletePlanet", deleteMutation, new());
+ JsonElement response = await ExecuteGraphQLRequestAsync("deletePlanet", deleteMutation, variables: new());
// Validate results
Assert.IsNull(response.GetProperty("id").GetString());
@@ -127,7 +127,7 @@ public async Task MutationMissingInputReturnError()
name
}}
}}";
- JsonElement response = await ExecuteGraphQLRequestAsync("addPlanet", mutation, new());
+ JsonElement response = await ExecuteGraphQLRequestAsync("addPlanet", mutation, variables: new());
Assert.AreEqual("inputDict is missing", response[0].GetProperty("message").ToString());
}
@@ -143,7 +143,7 @@ public async Task MutationMissingRequiredIdReturnError()
name
}}
}}";
- JsonElement response = await ExecuteGraphQLRequestAsync("addPlanet", mutation, new());
+ JsonElement response = await ExecuteGraphQLRequestAsync("addPlanet", mutation, variables: new());
Assert.AreEqual("id field is mandatory", response[0].GetProperty("message").ToString());
}
@@ -163,7 +163,7 @@ public async Task InvalidResolverOperationTypeReturnError()
name
}}
}}";
- JsonElement response = await ExecuteGraphQLRequestAsync("addPlanet", addMutation, new());
+ JsonElement response = await ExecuteGraphQLRequestAsync("addPlanet", addMutation, variables: new());
Assert.AreEqual("unsupported operation type: None", response[0].GetProperty("message").ToString());
//Register valid mutation resolver back after testing invalid senario
diff --git a/DataGateway.Service.Tests/CosmosTests/QueryTests.cs b/DataGateway.Service.Tests/CosmosTests/QueryTests.cs
index f827c74109..53fd0f79fc 100644
--- a/DataGateway.Service.Tests/CosmosTests/QueryTests.cs
+++ b/DataGateway.Service.Tests/CosmosTests/QueryTests.cs
@@ -140,7 +140,7 @@ public async Task GetPaginatedWithoutVariables()
}}
}}";
- JsonElement page = await ExecuteGraphQLRequestAsync("planets", planetConnectionQueryStringFormat, new());
+ JsonElement page = await ExecuteGraphQLRequestAsync("planets", planetConnectionQueryStringFormat, variables: new());
JsonElement continuation = page.GetProperty("endCursor");
continuationToken = continuation.ToString();
totalElementsFromPaginatedQuery += page.GetProperty("items").GetArrayLength();
From 867d6ef3af117fbc851fc85815194a30429eb2c0 Mon Sep 17 00:00:00 2001
From: tarazou9 <40870773+tarazou9@users.noreply.github.com>
Date: Wed, 11 May 2022 10:08:04 -0400
Subject: [PATCH 06/10] Check empty page for querying single item
---
.../Resolvers/CosmosQueryEngine.cs | 63 +++++++++++--------
1 file changed, 38 insertions(+), 25 deletions(-)
diff --git a/DataGateway.Service/Resolvers/CosmosQueryEngine.cs b/DataGateway.Service/Resolvers/CosmosQueryEngine.cs
index b97fdd95e9..223509df5b 100644
--- a/DataGateway.Service/Resolvers/CosmosQueryEngine.cs
+++ b/DataGateway.Service/Resolvers/CosmosQueryEngine.cs
@@ -68,36 +68,49 @@ public async Task> ExecuteAsync(IMiddlewareContex
requestContinuation = Base64Decode(structure.Continuation);
}
- FeedResponse firstPage = await container.GetItemQueryIterator(querySpec, requestContinuation, queryRequestOptions).ReadNextAsync();
-
- if (structure.IsPaginated)
+ using (FeedIterator query = container.GetItemQueryIterator(querySpec, requestContinuation, queryRequestOptions))
{
- JArray jarray = new();
- IEnumerator enumerator = firstPage.GetEnumerator();
- while (enumerator.MoveNext())
- {
- JObject item = enumerator.Current;
- jarray.Add(item);
- }
-
- string responseContinuation = firstPage.ContinuationToken;
- if (string.IsNullOrEmpty(responseContinuation))
+ do
{
- responseContinuation = null;
+ FeedResponse page = await query.ReadNextAsync();
+
+ // For connection type, return first page result directly
+ if (structure.IsPaginated)
+ {
+ JArray jarray = new();
+ IEnumerator enumerator = page.GetEnumerator();
+ while (enumerator.MoveNext())
+ {
+ JObject item = enumerator.Current;
+ jarray.Add(item);
+ }
+
+ string responseContinuation = page.ContinuationToken;
+ if (string.IsNullOrEmpty(responseContinuation))
+ {
+ responseContinuation = null;
+ }
+
+ JObject res = new(
+ new JProperty("endCursor", Base64Encode(responseContinuation)),
+ new JProperty("hasNextPage", responseContinuation != null),
+ new JProperty("items", jarray));
+
+ // This extra deserialize/serialization will be removed after moving to Newtonsoft from System.Text.Json
+ return new Tuple(JsonDocument.Parse(res.ToString()), null);
+ }
+
+ // For non-connection, check if it's an empty page from partition, return first item when non-empty, otherwise getting next page
+ if (page.Count > 0)
+ {
+ return new Tuple(JsonDocument.Parse(page.FirstOrDefault().ToString()), null);
+ }
}
-
- JObject res = new(
- new JProperty("endCursor", Base64Encode(responseContinuation)),
- new JProperty("hasNextPage", responseContinuation != null),
- new JProperty("items", jarray));
-
- // This extra deserialize/serialization will be removed after moving to Newtonsoft from System.Text.Json
- return new Tuple(JsonDocument.Parse(res.ToString()), null);
+ while (query.HasMoreResults);
}
- JsonDocument jsonDocument = (firstPage.Count == 0) ? null : JsonDocument.Parse(firstPage.FirstOrDefault().ToString());
-
- return new Tuple(jsonDocument, null);
+ // Return empty list when query gets no result back
+ return new Tuple(null, null);
}
public async Task, IMetadata>> ExecuteListAsync(IMiddlewareContext context, IDictionary parameters)
From 94456c6369b456b676b35cc87f41ca6c01e02c13 Mon Sep 17 00:00:00 2001
From: tarazou9 <40870773+tarazou9@users.noreply.github.com>
Date: Wed, 11 May 2022 10:19:14 -0400
Subject: [PATCH 07/10] Fix formatting error
---
DataGateway.Service/Resolvers/CosmosQueryEngine.cs | 1 -
1 file changed, 1 deletion(-)
diff --git a/DataGateway.Service/Resolvers/CosmosQueryEngine.cs b/DataGateway.Service/Resolvers/CosmosQueryEngine.cs
index 223509df5b..ae9552e282 100644
--- a/DataGateway.Service/Resolvers/CosmosQueryEngine.cs
+++ b/DataGateway.Service/Resolvers/CosmosQueryEngine.cs
@@ -100,7 +100,6 @@ public async Task> ExecuteAsync(IMiddlewareContex
return new Tuple(JsonDocument.Parse(res.ToString()), null);
}
- // For non-connection, check if it's an empty page from partition, return first item when non-empty, otherwise getting next page
if (page.Count > 0)
{
return new Tuple(JsonDocument.Parse(page.FirstOrDefault().ToString()), null);
From a4e31d8e1f7edf459d94efec2fdf60c30c10e7b5 Mon Sep 17 00:00:00 2001
From: tarazou9 <40870773+tarazou9@users.noreply.github.com>
Date: Wed, 11 May 2022 13:12:58 -0400
Subject: [PATCH 08/10] Address PR comments
---
.../MetadataStoreProviderForTest.cs | 8 -------
.../CosmosTests/MutationTests.cs | 24 -------------------
.../CosmosTests/TestBase.cs | 9 -------
.../Resolvers/CosmosQueryEngine.cs | 4 ++--
4 files changed, 2 insertions(+), 43 deletions(-)
diff --git a/DataGateway.Service.Tests/CosmosTests/MetadataStoreProviderForTest.cs b/DataGateway.Service.Tests/CosmosTests/MetadataStoreProviderForTest.cs
index d9b36623c3..a3115d85ff 100644
--- a/DataGateway.Service.Tests/CosmosTests/MetadataStoreProviderForTest.cs
+++ b/DataGateway.Service.Tests/CosmosTests/MetadataStoreProviderForTest.cs
@@ -37,14 +37,6 @@ public void StoreMutationResolver(MutationResolver mutationResolver)
MutationResolvers.Add(mutationResolver.Id, mutationResolver);
}
- public void RemoveMutationResolver(string mutationResolverId)
- {
- if (MutationResolvers.ContainsKey(mutationResolverId))
- {
- MutationResolvers.Remove(mutationResolverId);
- }
- }
-
public void StoreGraphQLType(string name, GraphQLType graphQLType)
{
GraphQLTypes.Add(name, graphQLType);
diff --git a/DataGateway.Service.Tests/CosmosTests/MutationTests.cs b/DataGateway.Service.Tests/CosmosTests/MutationTests.cs
index 6b82c0a396..f3abe6e78a 100644
--- a/DataGateway.Service.Tests/CosmosTests/MutationTests.cs
+++ b/DataGateway.Service.Tests/CosmosTests/MutationTests.cs
@@ -147,30 +147,6 @@ public async Task MutationMissingRequiredIdReturnError()
Assert.AreEqual("id field is mandatory", response[0].GetProperty("message").ToString());
}
- [TestMethod]
- public async Task InvalidResolverOperationTypeReturnError()
- {
- //Register invalid operation type resolver
- RemoveMutationResolver("addPlanet");
- RegisterMutationResolver("addPlanet", DATABASE_NAME, _containerName, "None");
-
- string id = Guid.NewGuid().ToString();
- const string name = "test_name";
- string addMutation = $@"
-mutation {{
- addPlanet (id: ""{id}"", name: ""{name}"") {{
- id
- name
- }}
-}}";
- JsonElement response = await ExecuteGraphQLRequestAsync("addPlanet", addMutation, variables: new());
- Assert.AreEqual("unsupported operation type: None", response[0].GetProperty("message").ToString());
-
- //Register valid mutation resolver back after testing invalid senario
- RemoveMutationResolver("addPlanet");
- RegisterMutationResolver("addPlanet", DATABASE_NAME, _containerName);
- }
-
///
/// Runs once after all tests in this class are executed
///
diff --git a/DataGateway.Service.Tests/CosmosTests/TestBase.cs b/DataGateway.Service.Tests/CosmosTests/TestBase.cs
index 1671042608..d4068e0250 100644
--- a/DataGateway.Service.Tests/CosmosTests/TestBase.cs
+++ b/DataGateway.Service.Tests/CosmosTests/TestBase.cs
@@ -148,15 +148,6 @@ internal static void RegisterMutationResolver(string id,
_metadataStoreProvider.StoreMutationResolver(mutationResolver);
}
- ///
- ///
- ///
- /// name of the mutation
- internal static void RemoveMutationResolver(string id)
- {
- _metadataStoreProvider.RemoveMutationResolver(id);
- }
-
///
/// Creates and registers a GraphQLType
///
diff --git a/DataGateway.Service/Resolvers/CosmosQueryEngine.cs b/DataGateway.Service/Resolvers/CosmosQueryEngine.cs
index ae9552e282..9a881167ea 100644
--- a/DataGateway.Service/Resolvers/CosmosQueryEngine.cs
+++ b/DataGateway.Service/Resolvers/CosmosQueryEngine.cs
@@ -98,11 +98,11 @@ public async Task> ExecuteAsync(IMiddlewareContex
// This extra deserialize/serialization will be removed after moving to Newtonsoft from System.Text.Json
return new Tuple(JsonDocument.Parse(res.ToString()), null);
- }
+ }
if (page.Count > 0)
{
- return new Tuple(JsonDocument.Parse(page.FirstOrDefault().ToString()), null);
+ return new Tuple(JsonDocument.Parse(page.First().ToString()), null);
}
}
while (query.HasMoreResults);
From d7d96a78bd04197cebf7b7d6661431134ead72e8 Mon Sep 17 00:00:00 2001
From: tarazou9 <40870773+tarazou9@users.noreply.github.com>
Date: Wed, 11 May 2022 14:26:04 -0400
Subject: [PATCH 09/10] Fix typo
---
DataGateway.Service.Tests/CosmosTests/QueryTests.cs | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/DataGateway.Service.Tests/CosmosTests/QueryTests.cs b/DataGateway.Service.Tests/CosmosTests/QueryTests.cs
index 53fd0f79fc..661e001235 100644
--- a/DataGateway.Service.Tests/CosmosTests/QueryTests.cs
+++ b/DataGateway.Service.Tests/CosmosTests/QueryTests.cs
@@ -202,7 +202,7 @@ public async Task GetByNonePrimaryFieldResultNotFound()
///
///
[TestMethod]
- public async Task GetByNonePrimaryFieldReturnsResult()
+ public async Task GetByNonPrimaryFieldReturnsResult()
{
string name = "test name";
string query = @$"
From d0346ba94d280fe8932ae8b31cc8d482d065f477 Mon Sep 17 00:00:00 2001
From: tarazou9 <40870773+tarazou9@users.noreply.github.com>
Date: Wed, 11 May 2022 14:28:01 -0400
Subject: [PATCH 10/10] Fix comment
---
DataGateway.Service.Tests/CosmosTests/QueryTests.cs | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/DataGateway.Service.Tests/CosmosTests/QueryTests.cs b/DataGateway.Service.Tests/CosmosTests/QueryTests.cs
index 661e001235..9445926038 100644
--- a/DataGateway.Service.Tests/CosmosTests/QueryTests.cs
+++ b/DataGateway.Service.Tests/CosmosTests/QueryTests.cs
@@ -198,7 +198,7 @@ public async Task GetByNonePrimaryFieldResultNotFound()
}
///
- /// Query single item by non-primary key field, found no match
+ /// Query single item by non-primary key field, found record back
///
///
[TestMethod]