From df6208a518744e2b41353219f295dc6941e51147 Mon Sep 17 00:00:00 2001 From: espenvis <160905037+espenvis@users.noreply.github.com> Date: Thu, 3 Oct 2024 14:45:07 +0200 Subject: [PATCH] fix: upgrades to std uri template and additional date formats management * add condition for value instanceof OffsetDateTime and LocalDate in RequestInformation#getSanitizedValues, add test for LocalDate pathParameter resolution * Add support for types LocalTime and PeriodAndDuration, add tests * Bump std-uritemplate version to 2.0.0 * fix: csv formatting for rendering in GitHub * fix additional coma fixes * style: remove additional space to make lint happy * fix: remove OffsetDateTime test in UriTemplateTest and accompanying template in data.csv resource, no longer applicable in std-uritemplate 2 * fix: switch CsvFileSource delimiter to ',' in accordance with data.csv formatting changes --------- Co-authored-by: Vincent Biret --- .../abstractions/gradle/dependencies.gradle | 2 +- .../microsoft/kiota/RequestInformation.java | 9 +++ .../kiota/RequestInformationTest.java | 62 ++++++++++++++++++- .../com/microsoft/kiota/UriTemplateTest.java | 8 +-- .../abstractions/src/test/resources/data.csv | 13 ++-- 5 files changed, 78 insertions(+), 16 deletions(-) diff --git a/components/abstractions/gradle/dependencies.gradle b/components/abstractions/gradle/dependencies.gradle index 0974823cd..81d7c3c98 100644 --- a/components/abstractions/gradle/dependencies.gradle +++ b/components/abstractions/gradle/dependencies.gradle @@ -8,7 +8,7 @@ dependencies { testRuntimeOnly 'org.junit.jupiter:junit-jupiter-engine' // This dependency is used internally, and not exposed to consumers on their own compile classpath. - implementation 'io.github.std-uritemplate:std-uritemplate:1.0.6' + implementation 'io.github.std-uritemplate:std-uritemplate:2.0.0' implementation 'io.opentelemetry:opentelemetry-api:1.42.1' implementation 'jakarta.annotation:jakarta.annotation-api:2.1.1' } diff --git a/components/abstractions/src/main/java/com/microsoft/kiota/RequestInformation.java b/components/abstractions/src/main/java/com/microsoft/kiota/RequestInformation.java index 615d368ba..6ef770bc5 100644 --- a/components/abstractions/src/main/java/com/microsoft/kiota/RequestInformation.java +++ b/components/abstractions/src/main/java/com/microsoft/kiota/RequestInformation.java @@ -20,6 +20,7 @@ import java.time.LocalDate; import java.time.LocalTime; import java.time.OffsetDateTime; +import java.time.format.DateTimeFormatter; import java.util.ArrayList; import java.util.Arrays; import java.util.Collection; @@ -473,6 +474,14 @@ private static Object getSanitizedValues(Object value) { return ((ValuedEnum) value).getValue(); } else if (value instanceof UUID) { return value.toString(); + } else if (value instanceof OffsetDateTime) { + return ((OffsetDateTime) value).format(DateTimeFormatter.ISO_OFFSET_DATE_TIME); + } else if (value instanceof LocalDate) { + return ((LocalDate) value).format(DateTimeFormatter.ISO_LOCAL_DATE); + } else if (value instanceof LocalTime) { + return ((LocalTime) value).format(DateTimeFormatter.ISO_LOCAL_TIME); + } else if (value instanceof PeriodAndDuration) { + return ((PeriodAndDuration) value).toString(); } else { return value; } diff --git a/components/abstractions/src/test/java/com/microsoft/kiota/RequestInformationTest.java b/components/abstractions/src/test/java/com/microsoft/kiota/RequestInformationTest.java index bf1c29142..24931ef5e 100644 --- a/components/abstractions/src/test/java/com/microsoft/kiota/RequestInformationTest.java +++ b/components/abstractions/src/test/java/com/microsoft/kiota/RequestInformationTest.java @@ -17,8 +17,7 @@ import java.net.URI; import java.net.URISyntaxException; -import java.time.OffsetDateTime; -import java.time.ZoneOffset; +import java.time.*; import java.util.ArrayList; import java.util.HashMap; import java.util.Map; @@ -73,6 +72,65 @@ void SetsPathParametersOfDateTimeOffsetType() { assertTrue(uriResult.toString().contains("toDateTime='2022-08-02T00%3A00%3A00Z'")); } + @Test + void SetsPathParametersOfLocalDateType() { + final RequestInformation requestInfo = new RequestInformation(); + requestInfo.httpMethod = HttpMethod.GET; + requestInfo.urlTemplate = + "http://localhost/getCalendarView(startLocalDate='{startLocalDate}',endLocalDate='{endLocalDate}')"; + + final LocalDate startLocalDate = LocalDate.of(2022, 8, 1); + final LocalDate endLocalDate = LocalDate.of(2022, 8, 2); + + requestInfo.pathParameters.put("startLocalDate", startLocalDate); + requestInfo.pathParameters.put("endLocalDate", endLocalDate); + + var uriResult = assertDoesNotThrow(() -> requestInfo.getUri()); + assertTrue(uriResult.toString().contains("startLocalDate='2022-08-01'")); + assertTrue(uriResult.toString().contains("endLocalDate='2022-08-02'")); + } + + @Test + void SetsPathParametersOfLocalTimeType() { + // Arrange as the request builders would + final RequestInformation requestInfo = new RequestInformation(); + requestInfo.httpMethod = HttpMethod.GET; + requestInfo.urlTemplate = + "http://localhost/getDailyCalendarView(startTime='{startTime}',endTime='{endTime}')"; + + // Act + final LocalTime startLocalTime = LocalTime.of(0, 1, 1); + final LocalTime endLocalTime = LocalTime.of(2, 2, 0); + requestInfo.pathParameters.put("startTime", startLocalTime); + requestInfo.pathParameters.put("endTime", endLocalTime); + + // Assert + var uriResult = assertDoesNotThrow(() -> requestInfo.getUri()); + assertTrue(uriResult.toString().contains("startTime='00%3A01%3A01'")); + assertTrue(uriResult.toString().contains("endTime='02%3A02%3A00'")); + } + + @Test + void SetsPathParametersOfPeriodAndDurationType() { + // Arrange as the request builders would + final RequestInformation requestInfo = new RequestInformation(); + requestInfo.httpMethod = HttpMethod.GET; + requestInfo.urlTemplate = + "http://localhost/getRestaurantSeating(mealDuration='{mealDuration}',seatingDuration='{seatingDuration}')"; + + // Act + final PeriodAndDuration startLocalTime = + PeriodAndDuration.of(Period.of(1, 2, 3), Duration.ofHours(10)); + final PeriodAndDuration endLocalTime = PeriodAndDuration.parse("PT30M"); + requestInfo.pathParameters.put("mealDuration", startLocalTime); + requestInfo.pathParameters.put("seatingDuration", endLocalTime); + + // Assert + var uriResult = assertDoesNotThrow(() -> requestInfo.getUri()); + assertTrue(uriResult.toString().contains("mealDuration='P1Y2M3DT10H'")); + assertTrue(uriResult.toString().contains("seatingDuration='PT30M'")); + } + @Test void ExpandQueryParametersAfterPathParams() { // Arrange as the request builders would diff --git a/components/abstractions/src/test/java/com/microsoft/kiota/UriTemplateTest.java b/components/abstractions/src/test/java/com/microsoft/kiota/UriTemplateTest.java index e2207adf1..23f565c58 100644 --- a/components/abstractions/src/test/java/com/microsoft/kiota/UriTemplateTest.java +++ b/components/abstractions/src/test/java/com/microsoft/kiota/UriTemplateTest.java @@ -7,8 +7,6 @@ import org.junit.jupiter.params.ParameterizedTest; import org.junit.jupiter.params.provider.CsvFileSource; -import java.time.OffsetDateTime; -import java.time.ZoneOffset; import java.util.Map; public class UriTemplateTest { @@ -24,14 +22,12 @@ public class UriTemplateTest { "async", true, "page", - 10, - "date", - OffsetDateTime.of(2023, 2, 13, 18, 49, 00, 00, ZoneOffset.UTC)); + 10); // Tests inspired from: // https://github.com/micronaut-projects/micronaut-core/blob/02992a905cf9a2279b7fe8e49927ff080cb937d5/http/src/test/groovy/io/micronaut/http/uri/UriTemplateSpec.groovy @ParameterizedTest - @CsvFileSource(resources = "/data.csv", numLinesToSkip = 1, delimiter = ';') + @CsvFileSource(resources = "/data.csv", numLinesToSkip = 1, delimiter = ',') void shouldProduceExpectedOutput(String template, String expected) { String result = StdUriTemplate.expand(template, params); diff --git a/components/abstractions/src/test/resources/data.csv b/components/abstractions/src/test/resources/data.csv index 1d73a014f..b9379522f 100644 --- a/components/abstractions/src/test/resources/data.csv +++ b/components/abstractions/src/test/resources/data.csv @@ -1,8 +1,7 @@ template, result -{+baseurl}/users; http://localhost:8080/users -{+baseurl}/users/{id}/list; http://localhost:8080/users/1/list -{+baseurl}/users/{id}/list{?async*}; http://localhost:8080/users/1/list?async=true -{+baseurl}/users/{id}/list{?async*,unmatched*}; http://localhost:8080/users/1/list?async=true -{+baseurl}/users/{id}/list{?async*,unmatched*,page*}; http://localhost:8080/users/1/list?async=true&page=10 -{+baseurl}/users/{id}/name/{name}/list{?async*,unmatched*,page*}; http://localhost:8080/users/1/name/foo/list?async=true&page=10 -{+baseurl}/users/{id}/list{?async*,unmatched*,page*,date*}; http://localhost:8080/users/1/list?async=true&page=10&date=2023-02-13T18%3A49%3A00Z +"{+baseurl}/users", http://localhost:8080/users +"{+baseurl}/users/{id}/list", http://localhost:8080/users/1/list +"{+baseurl}/users/{id}/list{?async*}", http://localhost:8080/users/1/list?async=true +"{+baseurl}/users/{id}/list{?async*,unmatched*}", http://localhost:8080/users/1/list?async=true +"{+baseurl}/users/{id}/list{?async*,unmatched*,page*}", http://localhost:8080/users/1/list?async=true&page=10 +"{+baseurl}/users/{id}/name/{name}/list{?async*,unmatched*,page*}", http://localhost:8080/users/1/name/foo/list?async=true&page=10