This is an automated email from the ASF dual-hosted git repository. vorburger pushed a commit to branch FINERACT-1234 in repository https://gitbox.apache.org/repos/asf/fineract.git
commit 11d3ef04f118f1daa61d6fcda41f8b54c5ca691e Author: Michael Vorburger <[email protected]> AuthorDate: Wed Oct 21 03:06:08 2020 +0200 client: serialize LocalDate as 2009-01-01 (FINERACT-1234) --- fineract-client/dependencies.gradle | 3 +- .../fineract/client/util/FineractClient.java | 9 ++ .../java/org/apache/fineract/client/util/JSON.java | 13 +- .../fineract/client/testutil/CallSubject.java | 55 +++++++++ .../integrationtests/newstyle/IntegrationTest.java | 134 +++++++++++++++++++++ .../integrationtests/newstyle/OfficeTest.java | 48 ++++++++ 6 files changed, 254 insertions(+), 8 deletions(-) diff --git a/fineract-client/dependencies.gradle b/fineract-client/dependencies.gradle index 320dfee..02baf8d 100644 --- a/fineract-client/dependencies.gradle +++ b/fineract-client/dependencies.gradle @@ -37,7 +37,8 @@ dependencies { testImplementation( 'org.junit.jupiter:junit-jupiter-api:5.7.0', - 'com.google.truth:truth:1.0.1' + 'com.google.truth:truth:1.0.1', + 'com.google.truth.extensions:truth-java8-extension:1.0.1' ) testRuntimeOnly( 'org.junit.jupiter:junit-jupiter-engine:5.7.0' diff --git a/fineract-client/src/main/java/org/apache/fineract/client/util/FineractClient.java b/fineract-client/src/main/java/org/apache/fineract/client/util/FineractClient.java index 41c77b9..c76c7a4 100644 --- a/fineract-client/src/main/java/org/apache/fineract/client/util/FineractClient.java +++ b/fineract-client/src/main/java/org/apache/fineract/client/util/FineractClient.java @@ -148,6 +148,15 @@ import retrofit2.converter.scalars.ScalarsConverterFactory; */ public final class FineractClient { + /** + * Constant to be used in requests where Fineract's API requires a dateFormat to be given. This matches the format + * in which LocalDate instances are serialized. (BTW: In a Java client API, it seems weird to have strong LocalDate + * (not String) instances, and then have to specify its format, see + * https://issues.apache.org/jira/browse/FINERACT-1233.) + */ + // Matching org.apache.fineract.client.util.JSON.LocalDateTypeAdapter.formatter + public static final String DATE_FORMAT = "yyyy-mm-dd"; + private final Retrofit retrofit; public final AccountingClosureApi glClosures; diff --git a/fineract-client/src/main/java/org/apache/fineract/client/util/JSON.java b/fineract-client/src/main/java/org/apache/fineract/client/util/JSON.java index 034c8b3..c1751bc 100644 --- a/fineract-client/src/main/java/org/apache/fineract/client/util/JSON.java +++ b/fineract-client/src/main/java/org/apache/fineract/client/util/JSON.java @@ -97,22 +97,21 @@ class JSON { } /** - * GSON TypeAdapter for JSR-310 LocalDate type in Fineract API Format (<tt>[2009,1,1]</tt>). + * GSON TypeAdapter for JSR-310 LocalDate type, which Fineract API's RETURNS as JSON array in the + * <tt>[2009,1,1]</tt> format, but EXPECTS as String not Array and with a locale and dateFormat. Weird, but so it is + * (see FINERACT-1220 & FINERACT-1233). */ public static class LocalDateTypeAdapter extends TypeAdapter<LocalDate> { - // Now unused: private final DateTimeFormatter formatter = DateTimeFormatter.ISO_LOCAL_DATE; + // NB this format is referenced from org.apache.fineract.client.util.FineractClient.DATE_FORMAT + private final DateTimeFormatter formatter = DateTimeFormatter.ISO_LOCAL_DATE; @Override public void write(JsonWriter out, LocalDate date) throws IOException { if (date == null) { out.nullValue(); } else { - out.beginArray(); - out.value(date.getYear()); - out.value(date.getMonthValue()); - out.value(date.getDayOfMonth()); - out.endArray(); + out.value(formatter.format(date)); } } diff --git a/fineract-client/src/test/java/org/apache/fineract/client/testutil/CallSubject.java b/fineract-client/src/test/java/org/apache/fineract/client/testutil/CallSubject.java new file mode 100644 index 0000000..edd4fae --- /dev/null +++ b/fineract-client/src/test/java/org/apache/fineract/client/testutil/CallSubject.java @@ -0,0 +1,55 @@ +/** + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ +package org.apache.fineract.client.testutil; + +import com.google.common.truth.FailureMetadata; +import com.google.common.truth.Subject; +import com.google.common.truth.Truth; +import java.io.IOException; +import javax.annotation.Nullable; +import retrofit2.Call; + +/** + * Google Truth Extension for Retrofit Call. + * + * @author Michael Vorburger.ch + */ +public class CallSubject extends Subject { + + // as per https://truth.dev/extension + + public static CallSubject assertThat(@Nullable Call<?> actual) { + return Truth.assertAbout(calls()).that(actual); + } + + public static Factory<CallSubject, Call<?>> calls() { + return CallSubject::new; + } + + private final Call<?> actual; + + protected CallSubject(FailureMetadata metadata, @Nullable Call<?> actual) { + super(metadata, actual); + this.actual = actual; + } + + public void hasHttpStatus(int expectedHttpStatus) throws IOException { + check("httpStatus").that(actual.execute().code()).isEqualTo(expectedHttpStatus); + } +} diff --git a/fineract-client/src/test/java/org/apache/fineract/integrationtests/newstyle/IntegrationTest.java b/fineract-client/src/test/java/org/apache/fineract/integrationtests/newstyle/IntegrationTest.java new file mode 100644 index 0000000..81559ee --- /dev/null +++ b/fineract-client/src/test/java/org/apache/fineract/integrationtests/newstyle/IntegrationTest.java @@ -0,0 +1,134 @@ +/** + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ +package org.apache.fineract.integrationtests.newstyle; + +import com.google.common.truth.BigDecimalSubject; +import com.google.common.truth.BooleanSubject; +import com.google.common.truth.ComparableSubject; +import com.google.common.truth.DoubleSubject; +import com.google.common.truth.FloatSubject; +import com.google.common.truth.IntegerSubject; +import com.google.common.truth.IterableSubject; +import com.google.common.truth.LongSubject; +import com.google.common.truth.OptionalSubject; +import com.google.common.truth.StringSubject; +import com.google.common.truth.Subject; +import com.google.common.truth.Truth; +import com.google.common.truth.Truth8; +import java.math.BigDecimal; +import java.util.Optional; +import java.util.Random; +import okhttp3.logging.HttpLoggingInterceptor.Level; +import org.apache.fineract.client.testutil.CallSubject; +import org.apache.fineract.client.util.Calls; +import org.apache.fineract.client.util.FineractClient; +import org.junit.jupiter.api.MethodOrderer; +import org.junit.jupiter.api.TestMethodOrder; +import retrofit2.Call; + +/** + * Integration Test for /documents API. + * + * @author Michael Vorburger.ch + */ +// TODO Remove @TestMethodOrder when https://github.com/junit-team/junit5/issues/1919 is available +@TestMethodOrder(MethodOrderer.OrderAnnotation.class) +public abstract class IntegrationTest { + + private static final Random random = new Random(); + + private FineractClient fineract; + + protected FineractClient fineract() { + if (fineract == null) { + // TODO change from Fineract.dev to https://localhost:8443/fineract-provider/api/v1/ after FINERACT-1209 + String url = System.getProperty("fineract.it.url", "https://demo.fineract.dev/fineract-provider/api/v1/"); + fineract = FineractClient.builder().baseURL(url).tenant("default").basicAuth("mifos", "password").insecure(true) + .logging(Level.BODY).build(); + } + return fineract; + } + + /** + * See {@link FineractClient#DATE_FORMAT}. + */ + protected String dateFormat() { + return FineractClient.DATE_FORMAT; + } + + protected String random() { + return Long.toString(random.nextLong()); + } + + // This method just makes it easier to use Calls.ok() in tests (it avoids having to static import) + protected <T> T ok(Call<T> call) { + return Calls.ok(call); + } + + // as above, avoids import static CallSubject.assertThat + protected <T> CallSubject assertThat(Call<T> call) { + return CallSubject.assertThat(call); + } + + // as above, this avoids issues with e.g. the Eclipse compiler getting confused which assertThat is which + public static IterableSubject assertThat(Iterable<?> actual) { + return Truth.assertThat(actual); + } + + public static <T extends Comparable<?>> ComparableSubject<T> assertThat(T actual) { + return Truth.assertThat(actual); + } + + public static BigDecimalSubject assertThat(BigDecimal actual) { + return Truth.assertThat(actual); + } + + public static Subject assertThat(Object actual) { + return Truth.assertThat(actual); + } + + public static LongSubject assertThat(Long actual) { + return Truth.assertThat(actual); + } + + public static DoubleSubject assertThat(Double actual) { + return Truth.assertThat(actual); + } + + public static FloatSubject assertThat(Float actual) { + return Truth.assertThat(actual); + } + + public static IntegerSubject assertThat(Integer actual) { + return Truth.assertThat(actual); + } + + public static BooleanSubject assertThat(Boolean actual) { + return Truth.assertThat(actual); + } + + public static StringSubject assertThat(String actual) { + return Truth.assertThat(actual); + } + + // from truth-java8-extension + public static OptionalSubject assertThat(Optional<?> actual) { + return Truth8.assertThat(actual); + } +} diff --git a/fineract-client/src/test/java/org/apache/fineract/integrationtests/newstyle/OfficeTest.java b/fineract-client/src/test/java/org/apache/fineract/integrationtests/newstyle/OfficeTest.java new file mode 100644 index 0000000..ddfe5db --- /dev/null +++ b/fineract-client/src/test/java/org/apache/fineract/integrationtests/newstyle/OfficeTest.java @@ -0,0 +1,48 @@ +/** + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ +package org.apache.fineract.integrationtests.newstyle; + +import java.time.LocalDate; +import org.apache.fineract.client.models.PostOfficesRequest; +import org.junit.jupiter.api.Order; +import org.junit.jupiter.api.Test; + +/** + * Integration Test for /offices API. + * + * @author Michael Vorburger.ch + */ +public class OfficeTest extends IntegrationTest { + + @Test + @Order(1) + void createOne() { + // NB parentId(1) always exists (Head Office) + // NB name random() because Office Names have to be unique + // TODO requiring dateFormat(..).locale(..) is dumb :( see https://issues.apache.org/jira/browse/FINERACT-1233 + assertThat(ok(fineract().offices.createOffice(new PostOfficesRequest().name("TestOffice-" + random()).parentId(1L) + .openingDate(LocalDate.now()).dateFormat(dateFormat()).locale("en_US"))).getOfficeId()).isGreaterThan(0); + } + + @Test + @Order(2) + void retrieveOneExisting() { + assertThat(ok(fineract().offices.retrieveOffices(true, null, null)).size()).isAtLeast(2); + } +}
