Skip to content

Commit

Permalink
Cleanup (#106)
Browse files Browse the repository at this point in the history
  • Loading branch information
wbaldoumas authored Apr 29, 2023
1 parent 6f64b58 commit 383c0d4
Show file tree
Hide file tree
Showing 13 changed files with 119 additions and 68 deletions.
3 changes: 3 additions & 0 deletions .editorconfig
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,9 @@ dotnet_diagnostic.SA1000.severity = none
dotnet_diagnostic.SA1009.severity = none
dotnet_diagnostic.SA1111.severity = none

# add trailing commas
dotnet_diagnostic.MA0007.severity = none

# format provider is missing
dotnet_diagnostic.MA0011.severity = none

Expand Down
5 changes: 5 additions & 0 deletions resources/blog.graphql
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
scalar DateTime
scalar URL

type Query {
userById(id: ID!): User!
Expand Down Expand Up @@ -45,6 +46,10 @@ type BlogPost implements Node {
id: ID!
}

extend type BlogPost {
uri: URL!
}

type Comment implements Node {
content: String!
author: User!
Expand Down
3 changes: 2 additions & 1 deletion resources/configuration.json
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@
"queryOperationFilter": [],
"mutationOperationFilter": [],
"customScalarMapping": {
"DateTime": "string"
"DateTime": "string",
"URL": "string"
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,8 @@ public sealed class GraphQLToKarateConverterBuilder :

private readonly IGraphQLCyclicToAcyclicConverter _graphQLCyclicToAcyclicConverter;

private readonly IGraphQLSchemaParser _graphQLSchemaParser;

private IGraphQLTypeConverter _graphQLTypeConverter = new GraphQLTypeConverter();

private bool _excludeQueriesSetting;
Expand All @@ -37,15 +39,20 @@ public sealed class GraphQLToKarateConverterBuilder :

private ICustomScalarMapping _customScalarMapping = new CustomScalarMapping();

public GraphQLToKarateConverterBuilder(ILogger<GraphQLToKarateConverter> graphQLToKarateConverterLogger, IGraphQLCyclicToAcyclicConverter graphQLCyclicToAcyclicConverter)
public GraphQLToKarateConverterBuilder(
ILogger<GraphQLToKarateConverter> graphQLToKarateConverterLogger,
IGraphQLCyclicToAcyclicConverter graphQLCyclicToAcyclicConverter,
IGraphQLSchemaParser graphQLSchemaParser)
{
_graphQLToKarateConverterLogger = graphQLToKarateConverterLogger;
_graphQLCyclicToAcyclicConverter = graphQLCyclicToAcyclicConverter;
_graphQLSchemaParser = graphQLSchemaParser;
}

public IConfigurableGraphQLToKarateConverterBuilder Configure() => new GraphQLToKarateConverterBuilder(
_graphQLToKarateConverterLogger,
_graphQLCyclicToAcyclicConverter
_graphQLCyclicToAcyclicConverter,
_graphQLSchemaParser
);

public IConfigurableGraphQLToKarateConverterBuilder WithCustomScalarMapping(
Expand Down Expand Up @@ -121,7 +128,7 @@ public IGraphQLToKarateConverter Build()
var graphQLTypeConverterFactory = new GraphQLTypeConverterFactory(_graphQLTypeConverter);

return new GraphQLToKarateConverter(
new GraphQLSchemaParser(),
_graphQLSchemaParser,
new GraphQLTypeDefinitionConverter(graphQLTypeConverterFactory),
new GraphQLFieldDefinitionConverter(
new GraphQLInputValueDefinitionConverterFactory(
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -88,7 +88,7 @@ private static void Convert(

fieldRelationshipsGraph.AddEdge(edge);

if (fieldRelationshipsGraph.IsCyclic())
if (fieldRelationshipsGraph.IsCyclicGraph())
{
typesCausingCycles.Add(unwrappedChildTypeName);
fieldRelationshipsGraph.RemoveEdge(edge);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -197,7 +197,7 @@ private static void HandleFields(
fieldRelationshipsGraph.AddEdge(edge);

// if adding the child field creates a cyclic graph, remove it and skip it.
if (fieldRelationshipsGraph.IsCyclic())
if (fieldRelationshipsGraph.IsCyclicGraph())
{
fieldRelationshipsGraph.RemoveEdge(edge);

Expand Down Expand Up @@ -307,7 +307,7 @@ private static void HandleOperation(

operationStringBuilder.AppendLine($"{SchemaToken.Space}{SchemaToken.OpenBrace}");

stringBuilder.Insert(0, operationStringBuilder.ToString());
stringBuilder.Insert(0, operationStringBuilder);
stringBuilder.Append(SchemaToken.CloseBrace);
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -73,7 +73,7 @@ private string Convert(
inputValueRelationships.AddEdge(edge);

// If adding the edge generates a cycle, remove it and generate a placeholder value to prevent infinite recursion...
if (inputValueRelationships.IsCyclic())
if (inputValueRelationships.IsCyclicGraph())
{
inputValueRelationships.RemoveEdge(edge);

Expand Down
130 changes: 75 additions & 55 deletions src/GraphQLToKarate.Library/Converters/GraphQLToKarateConverter.cs
Original file line number Diff line number Diff line change
Expand Up @@ -44,6 +44,69 @@ public string Convert(string schema)
var graphQLDocument = _graphQLSchemaParser.Parse(schema);
var graphQLDocumentAdapter = new GraphQLDocumentAdapter(graphQLDocument, _graphQLToKarateSettings);

RemoveTypeCycles(graphQLDocumentAdapter);

var karateObjects = GenerateKarateObjects(graphQLDocumentAdapter);
IEnumerable<GraphQLOperation> graphQLOperations = new List<GraphQLOperation>();

if (!_graphQLToKarateSettings.ExcludeQueries)
{
if (graphQLDocumentAdapter.GraphQLQueryTypeDefinition?.Fields is null)
{
_logger.LogWarning(
message: """Unable to find query type by the name of "{queryName}". If your query type exists and is named something other than "{queryName}", you will need to set the correct {queryNameOption} option for correct Karate scenario generation.""",
_graphQLToKarateSettings.QueryName,
_graphQLToKarateSettings.QueryName,
"--query-name"
);
}
else
{
graphQLOperations = graphQLOperations.Concat(
GenerateGraphQLOperations(
graphQLDocumentAdapter,
graphQLDocumentAdapter.GraphQLQueryTypeDefinition.Fields,
_graphQLToKarateSettings.QueryOperationFilter,
GraphQLOperationType.Query
)
);
}
}

// ReSharper disable once InvertIf - this is easier to read.
if (_graphQLToKarateSettings.IncludeMutations)
{
if (graphQLDocumentAdapter.GraphQLMutationTypeDefinition?.Fields is null)
{
_logger.LogWarning(
message: """Unable to find mutation type by the name of "{mutationName}". If your mutation type exists and is named something other than "{mutationName}", you will need to set the correct {mutationNameOption} option for correct Karate scenario generation.""",
_graphQLToKarateSettings.MutationName,
_graphQLToKarateSettings.MutationName,
"--mutation-name"
);
}
else
{
graphQLOperations = graphQLOperations.Concat(
GenerateGraphQLOperations(
graphQLDocumentAdapter,
graphQLDocumentAdapter.GraphQLMutationTypeDefinition.Fields,
_graphQLToKarateSettings.MutationOperationFilter,
GraphQLOperationType.Mutation
)
);
}
}

return _karateFeatureBuilder.Build(
karateObjects,
graphQLOperations,
graphQLDocumentAdapter
);
}

private void RemoveTypeCycles(IGraphQLDocumentAdapter graphQLDocumentAdapter)
{
var defaultFieldsDefinitions = new GraphQLFieldsDefinition(new List<GraphQLFieldDefinition>());

foreach (var hasFieldsDefinition in graphQLDocumentAdapter.GraphQLQueryTypeDefinition?.Fields ?? defaultFieldsDefinitions)
Expand All @@ -55,8 +118,10 @@ public string Convert(string schema)
{
_graphQLCyclicToAcyclicConverter.Convert(hasFieldsDefinition, graphQLDocumentAdapter);
}
}

var karateObjects = graphQLDocumentAdapter.GraphQLObjectTypeDefinitions.Select(
private IEnumerable<KarateObject> GenerateKarateObjects(IGraphQLDocumentAdapter graphQLDocumentAdapter) =>
graphQLDocumentAdapter.GraphQLObjectTypeDefinitions.Select(
graphQLObjectTypeDefinition => _graphQLTypeDefinitionConverter.Convert(
graphQLObjectTypeDefinition,
graphQLDocumentAdapter
Expand All @@ -70,59 +135,14 @@ public string Convert(string schema)
)
);

if (graphQLDocumentAdapter.GraphQLQueryTypeDefinition?.Fields is null)
{
_logger.LogWarning(
message: """Unable to find query type by the name of "{queryName}". If your query type exists and is named something other than "{queryName}", you will need to set the correct {queryNameOption} option for correct Karate scenario generation.""",
_graphQLToKarateSettings.QueryName,
_graphQLToKarateSettings.QueryName,
"--query-name"
private IEnumerable<GraphQLOperation> GenerateGraphQLOperations(
IGraphQLDocumentAdapter graphQLDocumentAdapter,
GraphQLFieldsDefinition graphQLFieldsDefinition,
ICollection<string> operationFilter,
GraphQLOperationType operationType) =>
graphQLFieldsDefinition
.Where(definition => operationFilter.NoneOrContains(definition.NameValue()))
.Select(definition =>
_graphQLFieldDefinitionConverter.Convert(definition, graphQLDocumentAdapter, operationType)
);
}

if (graphQLDocumentAdapter.GraphQLMutationTypeDefinition?.Fields is null)
{
_logger.LogWarning(
message: """Unable to find mutation type by the name of "{mutationName}". If your mutation type exists and is named something other than "{mutationName}", you will need to set the correct {mutationNameOption} option for correct Karate scenario generation.""",
_graphQLToKarateSettings.MutationName,
_graphQLToKarateSettings.MutationName,
"--mutation-name"
);
}

var graphQLOperations = new List<GraphQLOperation>();

if (!_graphQLToKarateSettings.ExcludeQueries)
{
var graphQLQueryOperations = graphQLDocumentAdapter.GraphQLQueryTypeDefinition?.Fields?
.Where(definition =>
_graphQLToKarateSettings.QueryOperationFilter.NoneOrContains(definition.NameValue())
)
.Select(definition =>
_graphQLFieldDefinitionConverter.Convert(definition, graphQLDocumentAdapter, GraphQLOperationType.Query)
) ?? new List<GraphQLOperation>();

graphQLOperations = graphQLOperations.Concat(graphQLQueryOperations).ToList();
}

// ReSharper disable once InvertIf - this is easier to read.
if (_graphQLToKarateSettings.IncludeMutations)
{
var graphQLMutationOperations = graphQLDocumentAdapter.GraphQLMutationTypeDefinition?.Fields?
.Where(definition =>
_graphQLToKarateSettings.MutationOperationFilter.NoneOrContains(definition.NameValue())
)
.Select(definition =>
_graphQLFieldDefinitionConverter.Convert(definition, graphQLDocumentAdapter, GraphQLOperationType.Mutation)
) ?? new List<GraphQLOperation>();

graphQLOperations = graphQLOperations.Concat(graphQLMutationOperations).ToList();
}

return _karateFeatureBuilder.Build(
karateObjects,
graphQLOperations,
graphQLDocumentAdapter
);
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,6 @@ internal static class AdjacencyGraphExtensions
/// <typeparam name="TEdge">The edge type.</typeparam>
/// <param name="adjacencyGraph">The <see cref="AdjacencyGraph{TVertex,TEdge}"/> to check.</param>
/// <returns><c>true</c> if the given <see cref="AdjacencyGraph{TVertex,TEdge}"/> is cyclic; otherwise, <c>false</c>.</returns>
public static bool IsCyclic<TVertex, TEdge>(this AdjacencyGraph<TVertex, TEdge> adjacencyGraph)
public static bool IsCyclicGraph<TVertex, TEdge>(this AdjacencyGraph<TVertex, TEdge> adjacencyGraph)
where TEdge : IEdge<TVertex> => !adjacencyGraph.IsDirectedAcyclicGraph();
}
3 changes: 2 additions & 1 deletion tests/GraphQLToKarate.Integration.Api/Program.cs
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,8 @@
.AddType<PageInfo>()
.AddType<UserConnection>()
.AddType<BlogPostConnection>()
.AddType<CommentConnection>();
.AddType<CommentConnection>()
.AddTypeExtension<BlogPostExtensions>();

var app = builder.Build();

Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
namespace GraphQLToKarate.Integration.Api.Types;

[ExtendObjectType(typeof(BlogPost))]
public sealed class BlogPostExtensions
{
public required Uri Uri { get; set; } = new ("https://my-awesome-api.com");
}
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@
using GraphQLToKarate.Library.Builders;
using GraphQLToKarate.Library.Converters;
using GraphQLToKarate.Library.Mappings;
using GraphQLToKarate.Library.Parsers;
using Microsoft.Extensions.Logging;
using NSubstitute;
using NUnit.Framework;
Expand All @@ -13,12 +14,14 @@ internal sealed class GraphQLToKarateConverterBuilderTests
{
private ILogger<GraphQLToKarateConverter>? _mockLogger;
private IGraphQLCyclicToAcyclicConverter? _mockGraphQLCyclicToAcyclicConverter;
private IGraphQLSchemaParser? _mockGraphQLSchemaParser;

[SetUp]
public void SetUp()
{
_mockLogger = Substitute.For<ILogger<GraphQLToKarateConverter>>();
_mockGraphQLCyclicToAcyclicConverter = Substitute.For<IGraphQLCyclicToAcyclicConverter>();
_mockGraphQLSchemaParser = Substitute.For<IGraphQLSchemaParser>();
}

[Test]
Expand All @@ -33,7 +36,11 @@ public void Build_builds_expected_converter(bool populateCustomScalarMapping)
: new Dictionary<string, string>()
);

var subjectUnderTest = new GraphQLToKarateConverterBuilder(_mockLogger!, _mockGraphQLCyclicToAcyclicConverter!);
var subjectUnderTest = new GraphQLToKarateConverterBuilder(
_mockLogger!,
_mockGraphQLCyclicToAcyclicConverter!,
_mockGraphQLSchemaParser!
);

// act
var graphQLToKarateConverter = subjectUnderTest
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -9,8 +9,8 @@ namespace GraphQLToKarate.Tests.Extensions;
internal sealed class AdjacencyGraphExtensionsTests
{
[TestCaseSource(nameof(IsCyclicTestCases))]
public void IsCyclic_should_return_expected_result(AdjacencyGraph<int, Edge<int>> graph, bool expectedResult) =>
graph.IsCyclic().Should().Be(expectedResult);
public void IsCyclicGraph_should_return_expected_result(AdjacencyGraph<int, Edge<int>> graph, bool expectedResult) =>
graph.IsCyclicGraph().Should().Be(expectedResult);

private static IEnumerable<TestCaseData> IsCyclicTestCases
{
Expand Down

0 comments on commit 383c0d4

Please sign in to comment.