From ddd1994d4225591f167c4194c11487c144d51de9 Mon Sep 17 00:00:00 2001 From: Andrea Di Lisio Date: Thu, 24 Aug 2023 12:54:04 +0200 Subject: [PATCH] fix(EWT-328): improperly formatted datetime string on transactions endpoint (#216) --- gradle.properties | 2 +- .../MerchantAccountsHandler.java | 8 ++-- .../MerchantAccountsAcceptanceTests.java | 38 ++++++++++++------- .../MerchantAccountsHandlerTests.java | 32 +++++++++++++--- 4 files changed, 55 insertions(+), 25 deletions(-) diff --git a/gradle.properties b/gradle.properties index 22492d31..47d730bd 100644 --- a/gradle.properties +++ b/gradle.properties @@ -1,7 +1,7 @@ # Main properties group=com.truelayer archivesBaseName=truelayer-java -version=9.0.0 +version=9.0.1 # Artifacts properties sonatype_repository_url=https://s01.oss.sonatype.org/service/local/ diff --git a/src/main/java/com/truelayer/java/merchantaccounts/MerchantAccountsHandler.java b/src/main/java/com/truelayer/java/merchantaccounts/MerchantAccountsHandler.java index 7ecc3d87..8db52c29 100644 --- a/src/main/java/com/truelayer/java/merchantaccounts/MerchantAccountsHandler.java +++ b/src/main/java/com/truelayer/java/merchantaccounts/MerchantAccountsHandler.java @@ -29,11 +29,9 @@ public CompletableFuture> getMerchantAccountById(St @Override public CompletableFuture> listTransactions( String merchantAccountId, ListTransactionsQuery query) { - return merchantAccountsApi.listTransactions( - merchantAccountId, - DateTimeFormatter.ISO_ZONED_DATE_TIME.format(query.from()), - DateTimeFormatter.ISO_ZONED_DATE_TIME.format(query.to()), - query.type()); + String from = DateTimeFormatter.ISO_OFFSET_DATE_TIME.format(query.from()); + String to = DateTimeFormatter.ISO_OFFSET_DATE_TIME.format(query.to()); + return merchantAccountsApi.listTransactions(merchantAccountId, from, to, query.type()); } @Override diff --git a/src/test/java/com/truelayer/java/acceptance/MerchantAccountsAcceptanceTests.java b/src/test/java/com/truelayer/java/acceptance/MerchantAccountsAcceptanceTests.java index fc790620..4967583f 100644 --- a/src/test/java/com/truelayer/java/acceptance/MerchantAccountsAcceptanceTests.java +++ b/src/test/java/com/truelayer/java/acceptance/MerchantAccountsAcceptanceTests.java @@ -10,11 +10,14 @@ import com.truelayer.java.merchantaccounts.entities.transactions.MerchantAccountPayment; import com.truelayer.java.merchantaccounts.entities.transactions.Transaction; import java.time.*; -import java.time.temporal.ChronoUnit; +import java.util.stream.Stream; import lombok.SneakyThrows; import lombok.Synchronized; import org.junit.jupiter.api.DisplayName; import org.junit.jupiter.api.Test; +import org.junit.jupiter.params.ParameterizedTest; +import org.junit.jupiter.params.provider.Arguments; +import org.junit.jupiter.params.provider.MethodSource; @DisplayName("Merchant accounts acceptance tests") public class MerchantAccountsAcceptanceTests extends AcceptanceTests { @@ -41,10 +44,11 @@ public void itShouldGetAMerchantAccountById() { } @SneakyThrows - @Test @DisplayName("It should get the list of transactions for a given merchant account") - public void itShouldGetTheListOfTransactions() { - ApiResponse transactionList = getTransactions(); + @ParameterizedTest(name = "with from={0} and to={1}") + @MethodSource("provideFromAndToParameters") + public void itShouldGetTheListOfTransactions(ZonedDateTime from, ZonedDateTime to) { + ApiResponse transactionList = getTransactions(from, to); assertNotError(transactionList); } @@ -99,10 +103,11 @@ public void itShouldDisableSweeping() { } @SneakyThrows - @Test @DisplayName("It should get the payment sources for the given merchant account") - public void itShouldGetPaymentSources() { - ApiResponse getTransactionsResponse = getTransactions(); + @ParameterizedTest(name = "with from={0} and to={1}") + @MethodSource("provideFromAndToParameters") + public void itShouldGetPaymentSources(ZonedDateTime from, ZonedDateTime to) { + ApiResponse getTransactionsResponse = getTransactions(from, to); assertNotError(getTransactionsResponse); MerchantAccountPayment merchantAccountPayment = getTransactionsResponse.getData().getItems().stream() .filter(t -> t.getType().equals(Transaction.Type.MERCHANT_ACCOUNT_PAYMENT)) @@ -125,15 +130,22 @@ public void itShouldGetPaymentSources() { @SneakyThrows @Synchronized - private ApiResponse getTransactions() { - ZonedDateTime from = ZonedDateTime.parse("2021-03-01T00:00:00Z"); + private ApiResponse getTransactions(ZonedDateTime from, ZonedDateTime to) { return tlClient.merchantAccounts() .listTransactions( getMerchantAccount(CurrencyCode.GBP).getId(), - ListTransactionsQuery.builder() - .from(from) - .to(from.plus(1, ChronoUnit.YEARS)) - .build()) + ListTransactionsQuery.builder().from(from).to(to).build()) .get(); } + + private static Stream provideFromAndToParameters() { + return Stream.of( + Arguments.of( + ZonedDateTime.of(LocalDate.of(2021, 3, 1), LocalTime.MIN, ZoneId.of("UTC")), + ZonedDateTime.of(LocalDate.of(2022, 3, 1), LocalTime.MIN, ZoneId.of("UTC"))), + Arguments.of( + ZonedDateTime.of(LocalDate.of(2021, 3, 1), LocalTime.MIN, ZoneId.of("Europe/Paris")), + ZonedDateTime.of(LocalDate.of(2022, 3, 1), LocalTime.MIN, ZoneId.of("Europe/Paris"))), + Arguments.of(ZonedDateTime.parse("2021-03-01T00:00:00Z"), ZonedDateTime.parse("2022-03-01T00:00:00Z"))); + } } diff --git a/src/test/java/com/truelayer/java/merchantaccounts/MerchantAccountsHandlerTests.java b/src/test/java/com/truelayer/java/merchantaccounts/MerchantAccountsHandlerTests.java index a0e01bf8..03ae4a2d 100644 --- a/src/test/java/com/truelayer/java/merchantaccounts/MerchantAccountsHandlerTests.java +++ b/src/test/java/com/truelayer/java/merchantaccounts/MerchantAccountsHandlerTests.java @@ -12,11 +12,17 @@ import com.truelayer.java.merchantaccounts.entities.ListTransactionsQuery; import com.truelayer.java.merchantaccounts.entities.UpdateSweepingRequest; import com.truelayer.java.merchantaccounts.entities.transactions.TransactionTypeQuery; +import java.time.LocalDate; +import java.time.LocalTime; import java.time.ZoneId; import java.time.ZonedDateTime; import java.time.format.DateTimeFormatter; +import java.util.stream.Stream; import org.junit.jupiter.api.DisplayName; import org.junit.jupiter.api.Test; +import org.junit.jupiter.params.ParameterizedTest; +import org.junit.jupiter.params.provider.Arguments; +import org.junit.jupiter.params.provider.MethodSource; import org.mockito.Mockito; class MerchantAccountsHandlerTests { @@ -45,16 +51,15 @@ public void shouldCallGetMerchantAccountByIdEndpoint() { verify(merchantsApi, times(1)).getMerchantAccountById(A_MERCHANT_ACCOUNT_ID); } - @Test @DisplayName("It should call the list transactions endpoint") - public void shouldCallListTransactionsEndpoint() { + @ParameterizedTest(name = "with from={0} and to={1}") + @MethodSource("provideFromAndToParameters") + public void shouldCallListTransactionsEndpoint(ZonedDateTime from, ZonedDateTime to) { IMerchantAccountsApi merchantsApi = Mockito.mock(IMerchantAccountsApi.class); MerchantAccountsHandler sut = new MerchantAccountsHandler(merchantsApi); - String fromStr = "2021-02-20T06:30:00Z"; - ZonedDateTime to = ZonedDateTime.now(ZoneId.of("UTC")); ListTransactionsQuery query = ListTransactionsQuery.builder() - .from(ZonedDateTime.parse(fromStr)) + .from(from) .to(to) .type(TransactionTypeQuery.PAYOUT) .build(); @@ -63,7 +68,10 @@ public void shouldCallListTransactionsEndpoint() { verify(merchantsApi, times(1)) .listTransactions( - A_MERCHANT_ACCOUNT_ID, fromStr, DateTimeFormatter.ISO_ZONED_DATE_TIME.format(to), query.type()); + A_MERCHANT_ACCOUNT_ID, + DateTimeFormatter.ISO_OFFSET_DATE_TIME.format(from), + DateTimeFormatter.ISO_OFFSET_DATE_TIME.format(to), + query.type()); } @Test @@ -139,4 +147,16 @@ public void shouldCallListPaymentSourcesEndpoint() { verify(merchantsApi, times(1)).listPaymentSources(A_MERCHANT_ACCOUNT_ID, query.userId()); } + + private static Stream provideFromAndToParameters() { + return Stream.of( + Arguments.of(ZonedDateTime.now(), ZonedDateTime.now().plusMonths(-12)), + Arguments.of( + ZonedDateTime.now(ZoneId.of("Europe/Paris")), + ZonedDateTime.now(ZoneId.of("Europe/Paris")).plusMonths(-12)), + Arguments.of( + ZonedDateTime.of(LocalDate.of(2021, 3, 1), LocalTime.MIN, ZoneId.of("UTC")), + ZonedDateTime.of(LocalDate.of(2022, 3, 1), LocalTime.MIN, ZoneId.of("UTC"))), + Arguments.of(ZonedDateTime.parse("2021-03-01T00:00:00Z"), ZonedDateTime.parse("2022-03-01T00:00:00Z"))); + } }