From f58a05048d081bc66b3440850798291160a5f4c6 Mon Sep 17 00:00:00 2001 From: dawidniezgodka Date: Thu, 13 Oct 2022 16:17:55 +0200 Subject: [PATCH 1/4] added support for DateTime --- .../quick/gateway/GraphQLSchemaGenerator.java | 2 +- .../gateway/GraphQLSchemaGeneratorTest.java | 18 +++++++++++++++ .../shouldConvertSchemaWithDateTime.graphql | 22 +++++++++++++++++++ 3 files changed, 41 insertions(+), 1 deletion(-) create mode 100644 gateway/src/test/resources/schema/conversion/shouldConvertSchemaWithDateTime.graphql diff --git a/gateway/src/main/java/com/bakdata/quick/gateway/GraphQLSchemaGenerator.java b/gateway/src/main/java/com/bakdata/quick/gateway/GraphQLSchemaGenerator.java index e2a1ca3e..66a40b86 100644 --- a/gateway/src/main/java/com/bakdata/quick/gateway/GraphQLSchemaGenerator.java +++ b/gateway/src/main/java/com/bakdata/quick/gateway/GraphQLSchemaGenerator.java @@ -67,7 +67,7 @@ public GraphQLSchemaGenerator(final List directiveWirings, this.directiveWirings = directiveWirings; this.quickGraphQLTypes = quickGraphQLTypes; this.postProcessings = postProcessings; - this.customScalars = List.of(ExtendedScalars.GraphQLLong); + this.customScalars = List.of(ExtendedScalars.GraphQLLong, ExtendedScalars.DateTime); } // TODO: remove. Currently exists only for old tests diff --git a/gateway/src/test/java/com/bakdata/quick/gateway/GraphQLSchemaGeneratorTest.java b/gateway/src/test/java/com/bakdata/quick/gateway/GraphQLSchemaGeneratorTest.java index 582226d8..a048bdf2 100644 --- a/gateway/src/test/java/com/bakdata/quick/gateway/GraphQLSchemaGeneratorTest.java +++ b/gateway/src/test/java/com/bakdata/quick/gateway/GraphQLSchemaGeneratorTest.java @@ -32,6 +32,7 @@ import com.bakdata.quick.gateway.fetcher.subscription.MultiSubscriptionFetcher; import com.bakdata.quick.gateway.fetcher.subscription.SubscriptionFetcher; import graphql.Scalars; +import graphql.scalars.ExtendedScalars; import graphql.schema.DataFetcher; import graphql.schema.GraphQLArgument; import graphql.schema.GraphQLFieldDefinition; @@ -511,6 +512,23 @@ void shouldNotCovertIfReturnTypeOfRangeQueryIsNotList(final TestInfo testInfo) t this.assertQuickDirectiveExceptionMessage(testInfo, "The return type of range queries should be a list."); } + @Test + void shouldConvertSchemaWithDateTime(final TestInfo testInfo) throws IOException { + final Path schemaPath = workingDirectory.resolve(testInfo.getTestMethod().orElseThrow().getName() + ".graphql"); + final GraphQLSchema schema = this.generator.create(Files.readString(schemaPath)); + + assertThat(schema.getTypeMap()) + .containsKeys("Purchase", "Product", "Metadata", "Query"); + + final GraphQLFieldDefinition fieldDefinition = + GraphQLTestUtil.getFieldDefinition("Metadata", "created_at", schema); + assertThat(fieldDefinition) + .isNotNull() + .extracting(GraphQLFieldDefinition::getType) + .isInstanceOf(GraphQLScalarType.class) + .isExactlyInstanceOf(ExtendedScalars.DateTime.getClass()); + } + private void registerTopics() { this.registryClient.register( "purchase-topic", diff --git a/gateway/src/test/resources/schema/conversion/shouldConvertSchemaWithDateTime.graphql b/gateway/src/test/resources/schema/conversion/shouldConvertSchemaWithDateTime.graphql new file mode 100644 index 00000000..b1b36db9 --- /dev/null +++ b/gateway/src/test/resources/schema/conversion/shouldConvertSchemaWithDateTime.graphql @@ -0,0 +1,22 @@ +type Query { + findPurchases: [Purchase] @topic(name: "purchase-topic") +} + +type Purchase { + purchaseId: ID!, + productId: ID!, + userId: ID!, + amount: Int, + product: Product @topic(name: "product-topic", keyField: "productId") +} + +type Product { + productId: ID!, + name: String, + metadata: Metadata +} + +type Metadata { + created_at: DateTime, + source: String +} From f7785bf8d27181d63b645da5c57f664e67843f6f Mon Sep 17 00:00:00 2001 From: dawidniezgodka Date: Thu, 13 Oct 2022 17:03:32 +0200 Subject: [PATCH 2/4] added query but still have to fix time issue --- .../gateway/GraphQLQueryExecutionTest.java | 30 +++++++++++++++++++ .../gateway/GraphQLSchemaGeneratorTest.java | 2 +- .../shouldConvertSchemaWithDateTime.graphql | 2 +- .../shouldExecuteQueryWithDateTime.graphql | 9 ++++++ ...houldExecuteQueryWithDateTimeQuery.graphql | 5 ++++ 5 files changed, 46 insertions(+), 2 deletions(-) create mode 100644 gateway/src/test/resources/schema/execution/shouldExecuteQueryWithDateTime.graphql create mode 100644 gateway/src/test/resources/schema/execution/shouldExecuteQueryWithDateTimeQuery.graphql diff --git a/gateway/src/test/java/com/bakdata/quick/gateway/GraphQLQueryExecutionTest.java b/gateway/src/test/java/com/bakdata/quick/gateway/GraphQLQueryExecutionTest.java index 4ac2e42e..b2db325b 100644 --- a/gateway/src/test/java/com/bakdata/quick/gateway/GraphQLQueryExecutionTest.java +++ b/gateway/src/test/java/com/bakdata/quick/gateway/GraphQLQueryExecutionTest.java @@ -41,6 +41,8 @@ import java.io.IOException; import java.nio.file.Files; import java.nio.file.Path; +import java.time.ZoneId; +import java.time.ZonedDateTime; import java.util.Collections; import java.util.List; import java.util.Map; @@ -310,6 +312,26 @@ void shouldThrowErrorForNonNullableField() throws IOException { }); } + @Test + void shouldExecuteQueryWithDateTime(final TestInfo testInfo) throws IOException { + final String name = testInfo.getTestMethod().orElseThrow().getName(); + final Path schemaPath = workingDirectory.resolve(name + ".graphql"); + final Path queryPath = workingDirectory.resolve(name + "Query.graphql"); + + final TestClientSupplier testClientSupplier = new TestClientSupplier(); + final GraphQL graphQL = this.getGraphQL(schemaPath, testClientSupplier); + + final DataFetcherClient dataFetcherClient = testClientSupplier.getClient("metadata-topic"); + final Metadata meta = Metadata.builder().id("test").createdAt(ZonedDateTime.now(ZoneId.systemDefault())).source("s1").build(); + when(dataFetcherClient.fetchResult("test")).thenAnswer(invocation -> meta); + + final ExecutionResult executionResult = graphQL.execute(Files.readString(queryPath)); + final Map> data = executionResult.getData(); + assertThat(data.get("findMetadata")) + .containsEntry("createdAt", ZonedDateTime.now(ZoneId.systemDefault())); + + } + private GraphQL getGraphQL(final Path schemaPath, final ClientSupplier clientSupplier) throws IOException { final KafkaConfig kafkaConfig = new KafkaConfig("dummy", "dummy"); @@ -398,4 +420,12 @@ private static class UserRequest { int timestamp; int requests; } + + @Value + @Builder + private static class Metadata { + String id; + ZonedDateTime createdAt; + String source; + } } diff --git a/gateway/src/test/java/com/bakdata/quick/gateway/GraphQLSchemaGeneratorTest.java b/gateway/src/test/java/com/bakdata/quick/gateway/GraphQLSchemaGeneratorTest.java index a048bdf2..7f666a6a 100644 --- a/gateway/src/test/java/com/bakdata/quick/gateway/GraphQLSchemaGeneratorTest.java +++ b/gateway/src/test/java/com/bakdata/quick/gateway/GraphQLSchemaGeneratorTest.java @@ -521,7 +521,7 @@ void shouldConvertSchemaWithDateTime(final TestInfo testInfo) throws IOException .containsKeys("Purchase", "Product", "Metadata", "Query"); final GraphQLFieldDefinition fieldDefinition = - GraphQLTestUtil.getFieldDefinition("Metadata", "created_at", schema); + GraphQLTestUtil.getFieldDefinition("Metadata", "createdAt", schema); assertThat(fieldDefinition) .isNotNull() .extracting(GraphQLFieldDefinition::getType) diff --git a/gateway/src/test/resources/schema/conversion/shouldConvertSchemaWithDateTime.graphql b/gateway/src/test/resources/schema/conversion/shouldConvertSchemaWithDateTime.graphql index b1b36db9..7979c5ac 100644 --- a/gateway/src/test/resources/schema/conversion/shouldConvertSchemaWithDateTime.graphql +++ b/gateway/src/test/resources/schema/conversion/shouldConvertSchemaWithDateTime.graphql @@ -17,6 +17,6 @@ type Product { } type Metadata { - created_at: DateTime, + createdAt: DateTime, source: String } diff --git a/gateway/src/test/resources/schema/execution/shouldExecuteQueryWithDateTime.graphql b/gateway/src/test/resources/schema/execution/shouldExecuteQueryWithDateTime.graphql new file mode 100644 index 00000000..12b1a277 --- /dev/null +++ b/gateway/src/test/resources/schema/execution/shouldExecuteQueryWithDateTime.graphql @@ -0,0 +1,9 @@ +type Query { + findMetadata(id: String): Metadata @topic(name: "metadata-topic", keyArgument: "id") +} + +type Metadata { + id: String! + createdAt: DateTime!, + source: String +} diff --git a/gateway/src/test/resources/schema/execution/shouldExecuteQueryWithDateTimeQuery.graphql b/gateway/src/test/resources/schema/execution/shouldExecuteQueryWithDateTimeQuery.graphql new file mode 100644 index 00000000..c12b4651 --- /dev/null +++ b/gateway/src/test/resources/schema/execution/shouldExecuteQueryWithDateTimeQuery.graphql @@ -0,0 +1,5 @@ +{ + findMetadata(id: "test") { + createdAt + } +} From 5ff40e231cdaa57a8b0111150387bf9208f72d59 Mon Sep 17 00:00:00 2001 From: dawidniezgodka Date: Fri, 14 Oct 2022 12:46:55 +0200 Subject: [PATCH 3/4] date format fix --- .../gateway/GraphQLQueryExecutionTest.java | 31 ++++++++++++++++--- 1 file changed, 27 insertions(+), 4 deletions(-) diff --git a/gateway/src/test/java/com/bakdata/quick/gateway/GraphQLQueryExecutionTest.java b/gateway/src/test/java/com/bakdata/quick/gateway/GraphQLQueryExecutionTest.java index b2db325b..6310b657 100644 --- a/gateway/src/test/java/com/bakdata/quick/gateway/GraphQLQueryExecutionTest.java +++ b/gateway/src/test/java/com/bakdata/quick/gateway/GraphQLQueryExecutionTest.java @@ -16,6 +16,11 @@ package com.bakdata.quick.gateway; +import static java.time.format.DateTimeFormatter.ISO_LOCAL_DATE; +import static java.time.temporal.ChronoField.HOUR_OF_DAY; +import static java.time.temporal.ChronoField.MINUTE_OF_HOUR; +import static java.time.temporal.ChronoField.NANO_OF_SECOND; +import static java.time.temporal.ChronoField.SECOND_OF_MINUTE; import static org.assertj.core.api.Assertions.assertThat; import static org.mockito.Mockito.mock; import static org.mockito.Mockito.when; @@ -41,8 +46,9 @@ import java.io.IOException; import java.nio.file.Files; import java.nio.file.Path; -import java.time.ZoneId; import java.time.ZonedDateTime; +import java.time.format.DateTimeFormatter; +import java.time.format.DateTimeFormatterBuilder; import java.util.Collections; import java.util.List; import java.util.Map; @@ -52,7 +58,8 @@ import org.junit.jupiter.api.TestInfo; class GraphQLQueryExecutionTest { - private static final TypeReference> OBJECT_TYPE_REFERENCE = new TypeReference<>() {}; + private static final TypeReference> OBJECT_TYPE_REFERENCE = new TypeReference<>() { + }; private static final Path workingDirectory = Path.of("src", "test", "resources", "schema", "execution"); private final TopicRegistryClient registryClient = new TestTopicRegistryClient(); private final ObjectMapper mapper = new ObjectMapper(); @@ -321,17 +328,33 @@ void shouldExecuteQueryWithDateTime(final TestInfo testInfo) throws IOException final TestClientSupplier testClientSupplier = new TestClientSupplier(); final GraphQL graphQL = this.getGraphQL(schemaPath, testClientSupplier); + final ZonedDateTime zonedNow = ZonedDateTime.now(); final DataFetcherClient dataFetcherClient = testClientSupplier.getClient("metadata-topic"); - final Metadata meta = Metadata.builder().id("test").createdAt(ZonedDateTime.now(ZoneId.systemDefault())).source("s1").build(); + final Metadata meta = Metadata.builder().id("test").createdAt(zonedNow).source("s1").build(); when(dataFetcherClient.fetchResult("test")).thenAnswer(invocation -> meta); final ExecutionResult executionResult = graphQL.execute(Files.readString(queryPath)); final Map> data = executionResult.getData(); assertThat(data.get("findMetadata")) - .containsEntry("createdAt", ZonedDateTime.now(ZoneId.systemDefault())); + .containsEntry("createdAt", zonedNow.format(getCustomDateTimeFormatter())); } + private static DateTimeFormatter getCustomDateTimeFormatter() { + return new DateTimeFormatterBuilder() + .parseCaseInsensitive() + .append(ISO_LOCAL_DATE) + .appendLiteral('T') + .appendValue(HOUR_OF_DAY, 2) + .appendLiteral(':') + .appendValue(MINUTE_OF_HOUR, 2) + .appendLiteral(':') + .appendValue(SECOND_OF_MINUTE, 2) + .appendFraction(NANO_OF_SECOND, 3, 3, true) + .appendOffset("+HH:MM", "Z") + .toFormatter(); + } + private GraphQL getGraphQL(final Path schemaPath, final ClientSupplier clientSupplier) throws IOException { final KafkaConfig kafkaConfig = new KafkaConfig("dummy", "dummy"); From e25e2cb9d79bb772edae4b9db3b27b2a207741c5 Mon Sep 17 00:00:00 2001 From: dawidniezgodka Date: Fri, 14 Oct 2022 12:51:22 +0200 Subject: [PATCH 4/4] add note about formatter --- .../com/bakdata/quick/gateway/GraphQLQueryExecutionTest.java | 1 + 1 file changed, 1 insertion(+) diff --git a/gateway/src/test/java/com/bakdata/quick/gateway/GraphQLQueryExecutionTest.java b/gateway/src/test/java/com/bakdata/quick/gateway/GraphQLQueryExecutionTest.java index 6310b657..39b3abd3 100644 --- a/gateway/src/test/java/com/bakdata/quick/gateway/GraphQLQueryExecutionTest.java +++ b/gateway/src/test/java/com/bakdata/quick/gateway/GraphQLQueryExecutionTest.java @@ -340,6 +340,7 @@ void shouldExecuteQueryWithDateTime(final TestInfo testInfo) throws IOException } + // Taken from: {@link graphql.scalars.datetime.DateTimeScalar} private static DateTimeFormatter getCustomDateTimeFormatter() { return new DateTimeFormatterBuilder() .parseCaseInsensitive()