From 014144f61475b6e6b1d053b723dac206f6b2c89b Mon Sep 17 00:00:00 2001 From: Aleksandar Vidakovic Date: Mon, 25 Mar 2024 05:55:29 +0100 Subject: [PATCH] FINERACT-2070: Integrate the new test framework into the public build pipeline --- .github/workflows/build-mariadb.yml | 4 +- .github/workflows/build-mysql.yml | 4 +- .github/workflows/build-postgresql.yml | 4 +- .github/workflows/build-tests.yml | 42 ++++++ build.gradle | 7 +- fineract-e2e-tests-core/build.gradle | 64 +++++++++ .../fineract/test/api/ApiConfiguration.java | 49 +++++++ .../fineract/test/api/ApiProperties.java | 37 +++++ .../test/api/FineractClientConfiguration.java | 47 +++++++ .../config/TestApplicationConfiguration.java | 29 ++++ .../test/factory/ClientRequestFactory.java | 49 +++++++ .../fineract/test/helper/CodeHelper.java | 61 +++++++++ .../fineract/test/helper/ErrorHelper.java | 37 +++++ .../test/helper/ErrorMessageHelper.java | 35 +++++ .../apache/fineract/test/helper/Utils.java | 45 ++++++ .../test/stepdef/AbstractStepDef.java | 28 ++++ .../test/stepdef/common/ClientStepDef.java | 118 ++++++++++++++++ .../fineract/test/support/TestContext.java | 49 +++++++ .../fineract/test/support/TestContextKey.java | 129 ++++++++++++++++++ .../fineract-test-application.properties | 39 ++++++ fineract-e2e-tests-runner/build.gradle | 91 ++++++++++++ .../org/apache/fineract/test/TestRunner.java | 29 ++++ .../config/TestCucumberConfiguration.java | 26 ++++ .../resources/META-INF/fineract-test.config | 2 + .../src/test/resources/allure.properties | 20 +++ .../src/test/resources/cucumber.properties | 20 +++ .../test/resources/features/Client.feature | 29 ++++ .../src/test/resources/logback.xml | 35 +++++ .../integrationtests/common/Utils.java | 4 +- settings.gradle | 2 + 30 files changed, 1124 insertions(+), 11 deletions(-) create mode 100644 .github/workflows/build-tests.yml create mode 100644 fineract-e2e-tests-core/build.gradle create mode 100644 fineract-e2e-tests-core/src/test/java/org/apache/fineract/test/api/ApiConfiguration.java create mode 100644 fineract-e2e-tests-core/src/test/java/org/apache/fineract/test/api/ApiProperties.java create mode 100644 fineract-e2e-tests-core/src/test/java/org/apache/fineract/test/api/FineractClientConfiguration.java create mode 100644 fineract-e2e-tests-core/src/test/java/org/apache/fineract/test/config/TestApplicationConfiguration.java create mode 100644 fineract-e2e-tests-core/src/test/java/org/apache/fineract/test/factory/ClientRequestFactory.java create mode 100644 fineract-e2e-tests-core/src/test/java/org/apache/fineract/test/helper/CodeHelper.java create mode 100644 fineract-e2e-tests-core/src/test/java/org/apache/fineract/test/helper/ErrorHelper.java create mode 100644 fineract-e2e-tests-core/src/test/java/org/apache/fineract/test/helper/ErrorMessageHelper.java create mode 100644 fineract-e2e-tests-core/src/test/java/org/apache/fineract/test/helper/Utils.java create mode 100644 fineract-e2e-tests-core/src/test/java/org/apache/fineract/test/stepdef/AbstractStepDef.java create mode 100644 fineract-e2e-tests-core/src/test/java/org/apache/fineract/test/stepdef/common/ClientStepDef.java create mode 100644 fineract-e2e-tests-core/src/test/java/org/apache/fineract/test/support/TestContext.java create mode 100644 fineract-e2e-tests-core/src/test/java/org/apache/fineract/test/support/TestContextKey.java create mode 100644 fineract-e2e-tests-core/src/test/resources/fineract-test-application.properties create mode 100644 fineract-e2e-tests-runner/build.gradle create mode 100644 fineract-e2e-tests-runner/src/test/java/org/apache/fineract/test/TestRunner.java create mode 100644 fineract-e2e-tests-runner/src/test/java/org/apache/fineract/test/config/TestCucumberConfiguration.java create mode 100644 fineract-e2e-tests-runner/src/test/resources/META-INF/fineract-test.config create mode 100644 fineract-e2e-tests-runner/src/test/resources/allure.properties create mode 100644 fineract-e2e-tests-runner/src/test/resources/cucumber.properties create mode 100644 fineract-e2e-tests-runner/src/test/resources/features/Client.feature create mode 100644 fineract-e2e-tests-runner/src/test/resources/logback.xml diff --git a/.github/workflows/build-mariadb.yml b/.github/workflows/build-mariadb.yml index ae7982874..586367f0f 100644 --- a/.github/workflows/build-mariadb.yml +++ b/.github/workflows/build-mariadb.yml @@ -81,8 +81,8 @@ jobs: FINERACT_REPORT_EXPORT_S3_BUCKET_NAME: fineract-reports run: | ./gradlew --no-daemon --console=plain build -x cucumber -x test -x doc - ./gradlew --no-daemon --console=plain cucumber - ./gradlew --no-daemon --console=plain test -x :twofactor-tests:test -x :oauth2-test:test + ./gradlew --no-daemon --console=plain cucumber -x :fineract-e2e-tests-runner:cucumber + ./gradlew --no-daemon --console=plain test -x :twofactor-tests:test -x :oauth2-test:test -x :fineract-e2e-tests-runner:test ./gradlew --no-daemon --console=plain :twofactor-tests:test ./gradlew --no-daemon --console=plain :oauth2-tests:test diff --git a/.github/workflows/build-mysql.yml b/.github/workflows/build-mysql.yml index 59e4de1a8..50a388633 100644 --- a/.github/workflows/build-mysql.yml +++ b/.github/workflows/build-mysql.yml @@ -81,8 +81,8 @@ jobs: FINERACT_REPORT_EXPORT_S3_BUCKET_NAME: fineract-reports run: | ./gradlew --no-daemon --console=plain build -x cucumber -x test -x doc - ./gradlew --no-daemon --console=plain cucumber - ./gradlew --no-daemon --console=plain test -x :twofactor-tests:test -x :oauth2-test:test -PdbType=mysql + ./gradlew --no-daemon --console=plain cucumber -x :fineract-e2e-tests-runner:cucumber + ./gradlew --no-daemon --console=plain test -x :twofactor-tests:test -x :oauth2-test:test :fineract-e2e-tests-runner:test -PdbType=mysql ./gradlew --no-daemon --console=plain :twofactor-tests:test -PdbType=mysql ./gradlew --no-daemon --console=plain :oauth2-tests:test -PdbType=mysql diff --git a/.github/workflows/build-postgresql.yml b/.github/workflows/build-postgresql.yml index 6a43c2274..c5093bd6b 100644 --- a/.github/workflows/build-postgresql.yml +++ b/.github/workflows/build-postgresql.yml @@ -82,8 +82,8 @@ jobs: FINERACT_REPORT_EXPORT_S3_BUCKET_NAME: fineract-reports run: | ./gradlew --no-daemon --console=plain build -x cucumber -x test -x doc - ./gradlew --no-daemon --console=plain cucumber - ./gradlew --no-daemon --console=plain test -x :twofactor-tests:test -x :oauth2-test:test -PdbType=postgresql + ./gradlew --no-daemon --console=plain cucumber -x :fineract-e2e-tests-runner:cucumber + ./gradlew --no-daemon --console=plain test -x :twofactor-tests:test -x :oauth2-test:test :fineract-e2e-tests-runner:test -PdbType=postgresql ./gradlew --no-daemon --console=plain :twofactor-tests:test -PdbType=postgresql ./gradlew --no-daemon --console=plain :oauth2-tests:test -PdbType=postgresql diff --git a/.github/workflows/build-tests.yml b/.github/workflows/build-tests.yml new file mode 100644 index 000000000..289efc6e3 --- /dev/null +++ b/.github/workflows/build-tests.yml @@ -0,0 +1,42 @@ +name: Fineract Tests + +on: [push, pull_request] + +permissions: + contents: read + +jobs: + build: + runs-on: ubuntu-22.04 + env: + GRADLE_ENTERPRISE_ACCESS_KEY: ${{ secrets.GE_ACCESS_TOKEN }} + + steps: + - uses: actions/checkout@b4ffde65f46336ab88eb53be808477a3936bae11 # v4 + with: + fetch-depth: 0 + - name: Set up JDK 17 + uses: actions/setup-java@9704b39bf258b59bc04b50fa2dd55e9ed76b47a8 # v4 + with: + java-version: '17' + distribution: 'zulu' + cache: gradle + - name: Build the image + run: ./gradlew --no-daemon --console=plain :fineract-provider:clean :fineract-provider:build :fineract-provider:jibDockerBuild -x test -x cucumber + - name: Start the Fineract stack + run: docker compose -f docker-compose-postgresql.yml up -d + - name: Wait for stack to come up + run: sleep 400 + - name: Check the stack + run: docker ps + - name: Check health Manager + run: curl -f -k --retry 10 --retry-connrefused --connect-timeout 30 --retry-delay 30 https://localhost:8443/fineract-provider/actuator/health + - name: Execute tests + env: + BASE_URL: https://localhost:8443 + TEST_USERNAME: mifos + TEST_PASSWORD: password + TEST_TENANT_ID: default + INITIALIZATION_ENABLED: true + EVENT_VERIFICATION_ENABLED: false + run: ./gradlew --no-daemon --console=plain fineract-e2e-tests-runner:cucumber --tags 'not @Skip' allureReport diff --git a/build.gradle b/build.gradle index 104d5af10..b46af2b55 100644 --- a/build.gradle +++ b/build.gradle @@ -37,7 +37,9 @@ buildscript { 'twofactor-tests', 'oauth2-tests', 'fineract-client', - 'fineract-avro-schemas' + 'fineract-avro-schemas', + 'fineract-e2e-tests-core', + 'fineract-e2e-tests-runner' ].contains(it.name) } fineractPublishProjects = subprojects.findAll{ @@ -282,7 +284,8 @@ allprojects { ".mailmap", '**/images/diag-*.svg', '**/*.avsc', - "**/generated/**/*MapperImpl.java" + "**/generated/**/*MapperImpl.java", + '**/META-INF/fineract-test.config' ] } } diff --git a/fineract-e2e-tests-core/build.gradle b/fineract-e2e-tests-core/build.gradle new file mode 100644 index 000000000..79032d3e8 --- /dev/null +++ b/fineract-e2e-tests-core/build.gradle @@ -0,0 +1,64 @@ +/** + * 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. + */ + +plugins { + id 'java' +} + +repositories { + mavenCentral() +} + +dependencies { + testImplementation(project(':fineract-avro-schemas')) + testImplementation(project(':fineract-client')) + + testImplementation 'org.springframework:spring-context' + implementation 'org.springframework:spring-test' + testImplementation 'org.springframework:spring-jms' + + testImplementation 'com.squareup.retrofit2:retrofit:2.9.0' + testImplementation 'commons-httpclient:commons-httpclient:3.1' + testImplementation 'org.apache.commons:commons-lang3:3.14.0' + testImplementation 'com.googlecode.json-simple:json-simple:1.1.1' + testImplementation 'com.google.code.gson:gson:2.10.1' + + testImplementation 'io.cucumber:cucumber-java:7.15.0' + testImplementation 'io.cucumber:cucumber-junit:7.15.0' + testImplementation 'io.cucumber:cucumber-spring:7.15.0' + + testImplementation 'io.qameta.allure:allure-cucumber7-jvm:2.25.0' + + testImplementation 'org.assertj:assertj-core:3.25.3' + testImplementation 'org.junit.jupiter:junit-jupiter-api:5.10.2' + testImplementation 'org.junit.jupiter:junit-jupiter:5.10.2' + + testCompileOnly 'org.projectlombok:lombok:1.18.30' + testAnnotationProcessor 'org.projectlombok:lombok:1.18.30' + + testImplementation "ch.qos.logback:logback-core:1.5.3" + testImplementation "ch.qos.logback:logback-classic:1.5.3" + + testImplementation 'org.apache.activemq:activemq-client:6.0.1' + testImplementation "org.apache.avro:avro:1.11.3" + testImplementation "org.awaitility:awaitility:4.2.0" + testImplementation 'io.github.classgraph:classgraph:4.8.168' + + testImplementation 'org.apache.commons:commons-collections4:4.4' +} diff --git a/fineract-e2e-tests-core/src/test/java/org/apache/fineract/test/api/ApiConfiguration.java b/fineract-e2e-tests-core/src/test/java/org/apache/fineract/test/api/ApiConfiguration.java new file mode 100644 index 000000000..db8576355 --- /dev/null +++ b/fineract-e2e-tests-core/src/test/java/org/apache/fineract/test/api/ApiConfiguration.java @@ -0,0 +1,49 @@ +/** + * 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.test.api; + +import org.apache.fineract.client.services.ClientApi; +import org.apache.fineract.client.services.CodeValuesApi; +import org.apache.fineract.client.services.CodesApi; +import org.apache.fineract.client.util.FineractClient; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.context.annotation.Bean; +import org.springframework.context.annotation.Configuration; + +@Configuration +public class ApiConfiguration { + + @Autowired + private FineractClient fineractClient; + + @Bean + public ClientApi clientApi() { + return fineractClient.createService(ClientApi.class); + } + + @Bean + public CodesApi codesApi() { + return fineractClient.createService(CodesApi.class); + } + + @Bean + public CodeValuesApi codeValuesApi() { + return fineractClient.createService(CodeValuesApi.class); + } +} diff --git a/fineract-e2e-tests-core/src/test/java/org/apache/fineract/test/api/ApiProperties.java b/fineract-e2e-tests-core/src/test/java/org/apache/fineract/test/api/ApiProperties.java new file mode 100644 index 000000000..417685a13 --- /dev/null +++ b/fineract-e2e-tests-core/src/test/java/org/apache/fineract/test/api/ApiProperties.java @@ -0,0 +1,37 @@ +/** + * 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.test.api; + +import lombok.Getter; +import org.springframework.beans.factory.annotation.Value; +import org.springframework.stereotype.Component; + +@Component +@Getter +public class ApiProperties { + + @Value("${fineract-test.api.base-url}") + private String baseUrl; + @Value("${fineract-test.api.username}") + private String username; + @Value("${fineract-test.api.password}") + private String password; + @Value("${fineract-test.api.tenant-id}") + private String tenantId; +} diff --git a/fineract-e2e-tests-core/src/test/java/org/apache/fineract/test/api/FineractClientConfiguration.java b/fineract-e2e-tests-core/src/test/java/org/apache/fineract/test/api/FineractClientConfiguration.java new file mode 100644 index 000000000..dcdff97c9 --- /dev/null +++ b/fineract-e2e-tests-core/src/test/java/org/apache/fineract/test/api/FineractClientConfiguration.java @@ -0,0 +1,47 @@ +/** + * 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.test.api; + +import lombok.extern.slf4j.Slf4j; +import org.apache.fineract.client.util.FineractClient; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.context.annotation.Bean; +import org.springframework.context.annotation.Configuration; + +@Configuration +@Slf4j +public class FineractClientConfiguration { + + @Autowired + private ApiProperties apiProperties; + + @Bean + public FineractClient fineractClient() { + String baseUrl = apiProperties.getBaseUrl(); + String username = apiProperties.getUsername(); + String password = apiProperties.getPassword(); + String tenantId = apiProperties.getTenantId(); + + String apiBaseUrl = baseUrl + "/fineract-provider/api/"; + + log.info("Using base URL '{}'", apiBaseUrl); + + return FineractClient.builder().basicAuth(username, password).tenant(tenantId).baseURL(apiBaseUrl).insecure(true).build(); + } +} diff --git a/fineract-e2e-tests-core/src/test/java/org/apache/fineract/test/config/TestApplicationConfiguration.java b/fineract-e2e-tests-core/src/test/java/org/apache/fineract/test/config/TestApplicationConfiguration.java new file mode 100644 index 000000000..d75564c84 --- /dev/null +++ b/fineract-e2e-tests-core/src/test/java/org/apache/fineract/test/config/TestApplicationConfiguration.java @@ -0,0 +1,29 @@ +/** + * 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.test.config; + +import org.springframework.context.annotation.ComponentScan; +import org.springframework.context.annotation.Configuration; +import org.springframework.context.annotation.FilterType; +import org.springframework.context.annotation.PropertySource; + +@Configuration +@ComponentScan(value = "org.apache.fineract.test", excludeFilters = @ComponentScan.Filter(type = FilterType.REGEX, pattern = "org\\.apache\\.fineract\\.test\\.initializer.*")) +@PropertySource("classpath:fineract-test-application.properties") +public class TestApplicationConfiguration {} diff --git a/fineract-e2e-tests-core/src/test/java/org/apache/fineract/test/factory/ClientRequestFactory.java b/fineract-e2e-tests-core/src/test/java/org/apache/fineract/test/factory/ClientRequestFactory.java new file mode 100644 index 000000000..b58660c40 --- /dev/null +++ b/fineract-e2e-tests-core/src/test/java/org/apache/fineract/test/factory/ClientRequestFactory.java @@ -0,0 +1,49 @@ +/** + * 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.test.factory; + +import org.apache.fineract.client.models.PostClientsRequest; +import org.apache.fineract.test.helper.Utils; +import org.springframework.stereotype.Component; + +@Component +public class ClientRequestFactory { + + private static final Long HEAD_OFFICE_ID = 1L; + private static final Long LEGAL_FORM_ID_PERSON = 1L; + public static final String DATE_FORMAT = "dd MMMM yyyy"; + public static final String DEFAULT_LOCALE = "en"; + + public PostClientsRequest defaultClientCreationRequest() { + return new PostClientsRequest()// + .officeId(HEAD_OFFICE_ID)// + .legalFormId(LEGAL_FORM_ID_PERSON)// + .firstname(Utils.randomNameGenerator("Client_FirstName_", 5))// + .lastname(Utils.randomNameGenerator("Client_LastName_", 5))// + .externalId(randomClientId("ID_", 7))// + .dateFormat(DATE_FORMAT)// + .locale(DEFAULT_LOCALE)// + .active(true)// + .activationDate("04 March 2011");// + } + + private String randomClientId(final String prefix, final int lenOfRandomSuffix) { + return Utils.randomStringGenerator(prefix, lenOfRandomSuffix, "ABCDEFGHIJKLMNOPQRSTUVWXYZ"); + } +} diff --git a/fineract-e2e-tests-core/src/test/java/org/apache/fineract/test/helper/CodeHelper.java b/fineract-e2e-tests-core/src/test/java/org/apache/fineract/test/helper/CodeHelper.java new file mode 100644 index 000000000..ff01ac874 --- /dev/null +++ b/fineract-e2e-tests-core/src/test/java/org/apache/fineract/test/helper/CodeHelper.java @@ -0,0 +1,61 @@ +/** + * 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.test.helper; + +import java.io.IOException; +import lombok.RequiredArgsConstructor; +import org.apache.fineract.client.models.GetCodesResponse; +import org.apache.fineract.client.models.PostCodeValueDataResponse; +import org.apache.fineract.client.models.PostCodeValuesDataRequest; +import org.apache.fineract.client.services.CodeValuesApi; +import org.apache.fineract.client.services.CodesApi; +import org.springframework.stereotype.Component; +import retrofit2.Response; + +@Component +@RequiredArgsConstructor +public class CodeHelper { + + private static final String COUNTRY_CODE_NAME = "COUNTRY"; + private static final String STATE_CODE_NAME = "STATE"; + private static final String ADDRESS_TYPE_CODE_NAME = "ADDRESS_TYPE"; + + private final CodesApi codesApi; + private final CodeValuesApi codeValuesApi; + + public Response createAddressTypeCodeValue(String addressTypeName) throws IOException { + Long codeId = retrieveCodeByName(ADDRESS_TYPE_CODE_NAME).getId(); + return codeValuesApi.createCodeValue(codeId, new PostCodeValuesDataRequest().name(addressTypeName)).execute(); + } + + public Response createCountryCodeValue(String countryName) throws IOException { + Long codeId = retrieveCodeByName(COUNTRY_CODE_NAME).getId(); + return codeValuesApi.createCodeValue(codeId, new PostCodeValuesDataRequest().name(countryName)).execute(); + } + + public Response createStateCodeValue(String stateName) throws IOException { + Long codeId = retrieveCodeByName(STATE_CODE_NAME).getId(); + return codeValuesApi.createCodeValue(codeId, new PostCodeValuesDataRequest().name(stateName)).execute(); + } + + public GetCodesResponse retrieveCodeByName(String name) throws IOException { + return codesApi.retrieveCodes().execute().body().stream().filter(r -> name.equals(r.getName())).findAny() + .orElseThrow(() -> new IllegalArgumentException("Code with name " + name + " has not been found")); + } +} diff --git a/fineract-e2e-tests-core/src/test/java/org/apache/fineract/test/helper/ErrorHelper.java b/fineract-e2e-tests-core/src/test/java/org/apache/fineract/test/helper/ErrorHelper.java new file mode 100644 index 000000000..594902362 --- /dev/null +++ b/fineract-e2e-tests-core/src/test/java/org/apache/fineract/test/helper/ErrorHelper.java @@ -0,0 +1,37 @@ +/** + * 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.test.helper; + +import static org.assertj.core.api.Assertions.assertThat; + +import java.io.IOException; +import retrofit2.Response; + +public final class ErrorHelper { + + private ErrorHelper() {} + + public static void checkSuccessfulApiCall(Response response) throws IOException { + assertThat(response.isSuccessful()).as(ErrorMessageHelper.requestFailed(response)).isTrue(); + + if (response.code() != 200 && response.code() != 202 && response.code() != 204) { + throw new AssertionError(ErrorMessageHelper.requestFailedWithCode(response)); + } + } +} diff --git a/fineract-e2e-tests-core/src/test/java/org/apache/fineract/test/helper/ErrorMessageHelper.java b/fineract-e2e-tests-core/src/test/java/org/apache/fineract/test/helper/ErrorMessageHelper.java new file mode 100644 index 000000000..76cc7f51a --- /dev/null +++ b/fineract-e2e-tests-core/src/test/java/org/apache/fineract/test/helper/ErrorMessageHelper.java @@ -0,0 +1,35 @@ +/** + * 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.test.helper; + +import java.io.IOException; +import retrofit2.Response; + +public final class ErrorMessageHelper { + + private ErrorMessageHelper() {} + + public static String requestFailed(Response response) throws IOException { + return String.format("Request failed. Error:%n%s", response.errorBody() != null ? response.errorBody().string() : null); + } + + public static String requestFailedWithCode(Response response) { + return String.format("Response has error code: %2d", response.code()); + } +} diff --git a/fineract-e2e-tests-core/src/test/java/org/apache/fineract/test/helper/Utils.java b/fineract-e2e-tests-core/src/test/java/org/apache/fineract/test/helper/Utils.java new file mode 100644 index 000000000..f4e882ddc --- /dev/null +++ b/fineract-e2e-tests-core/src/test/java/org/apache/fineract/test/helper/Utils.java @@ -0,0 +1,45 @@ +/** + * 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.test.helper; + +import java.security.SecureRandom; + +public final class Utils { + + private static final SecureRandom random = new SecureRandom(); + + private Utils() {} + + public static String randomStringGenerator(final String prefix, final int len, final String sourceSetString) { + final int lengthOfSource = sourceSetString.length(); + final StringBuilder sb = new StringBuilder(len); + for (int i = 0; i < len; i++) { + sb.append(sourceSetString.charAt(random.nextInt(lengthOfSource))); + } + return prefix + sb; + } + + public static String randomStringGenerator(final String prefix, final int len) { + return randomStringGenerator(prefix, len, "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ"); + } + + public static String randomNameGenerator(final String prefix, final int lenOfRandomSuffix) { + return randomStringGenerator(prefix, lenOfRandomSuffix); + } +} diff --git a/fineract-e2e-tests-core/src/test/java/org/apache/fineract/test/stepdef/AbstractStepDef.java b/fineract-e2e-tests-core/src/test/java/org/apache/fineract/test/stepdef/AbstractStepDef.java new file mode 100644 index 000000000..61a52a9b4 --- /dev/null +++ b/fineract-e2e-tests-core/src/test/java/org/apache/fineract/test/stepdef/AbstractStepDef.java @@ -0,0 +1,28 @@ +/** + * 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.test.stepdef; + +import org.apache.fineract.test.support.TestContext; + +public class AbstractStepDef { + + public TestContext testContext() { + return TestContext.INSTANCE; + } +} diff --git a/fineract-e2e-tests-core/src/test/java/org/apache/fineract/test/stepdef/common/ClientStepDef.java b/fineract-e2e-tests-core/src/test/java/org/apache/fineract/test/stepdef/common/ClientStepDef.java new file mode 100644 index 000000000..7f0ae6e91 --- /dev/null +++ b/fineract-e2e-tests-core/src/test/java/org/apache/fineract/test/stepdef/common/ClientStepDef.java @@ -0,0 +1,118 @@ +/** + * 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.test.stepdef.common; + +import static org.assertj.core.api.Assertions.assertThat; + +import io.cucumber.java.en.Then; +import io.cucumber.java.en.When; +import java.io.IOException; +import java.util.Arrays; +import org.apache.fineract.client.models.PostClientsAddressRequest; +import org.apache.fineract.client.models.PostClientsRequest; +import org.apache.fineract.client.models.PostClientsResponse; +import org.apache.fineract.client.services.ClientApi; +import org.apache.fineract.test.factory.ClientRequestFactory; +import org.apache.fineract.test.helper.CodeHelper; +import org.apache.fineract.test.helper.ErrorHelper; +import org.apache.fineract.test.helper.ErrorMessageHelper; +import org.apache.fineract.test.helper.Utils; +import org.apache.fineract.test.stepdef.AbstractStepDef; +import org.apache.fineract.test.support.TestContextKey; +import org.springframework.beans.factory.annotation.Autowired; +import retrofit2.Response; + +public class ClientStepDef extends AbstractStepDef { + + @Autowired + private ClientApi clientApi; + + @Autowired + private CodeHelper codeHelper; + + @Autowired + private ClientRequestFactory clientRequestFactory; + + @When("Admin creates a client with random data") + public void createClientRandomFirstNameLastName() throws IOException { + PostClientsRequest clientsRequest = clientRequestFactory.defaultClientCreationRequest(); + + Response response = clientApi.create6(clientsRequest).execute(); + ErrorHelper.checkSuccessfulApiCall(response); + testContext().set(TestContextKey.CLIENT_CREATE_RESPONSE, response); + } + + @When("Admin creates a second client with random data") + public void createSecondClientRandomFirstNameLastName() throws IOException { + PostClientsRequest clientsRequest = clientRequestFactory.defaultClientCreationRequest(); + + Response response = clientApi.create6(clientsRequest).execute(); + ErrorHelper.checkSuccessfulApiCall(response); + testContext().set(TestContextKey.CLIENT_CREATE_SECOND_CLIENT_RESPONSE, response); + } + + @When("Admin creates a client with Firstname {string} and Lastname {string}") + public void createClient(String firstName, String lastName) throws IOException { + PostClientsRequest clientsRequest = clientRequestFactory.defaultClientCreationRequest().firstname(firstName).lastname(lastName); + + Response response = clientApi.create6(clientsRequest).execute(); + ErrorHelper.checkSuccessfulApiCall(response); + testContext().set(TestContextKey.CLIENT_CREATE_RESPONSE, response); + } + + @When("Admin creates a client with Firstname {string} and Lastname {string} with address") + public void createClientWithAddress(String firstName, String lastName) throws IOException { + Long addressTypeId = codeHelper.createAddressTypeCodeValue(Utils.randomNameGenerator("Residential address", 4)).body() + .getResourceId(); + Long countryId = codeHelper.createCountryCodeValue(Utils.randomNameGenerator("Hungary", 4)).body().getResourceId(); + Long stateId = codeHelper.createStateCodeValue(Utils.randomNameGenerator("Budapest", 4)).body().getResourceId(); + String city = "Budapest"; + boolean addressIsActive = true; + long postalCode = 1000L; + + PostClientsAddressRequest addressRequest = new PostClientsAddressRequest().postalCode(postalCode).city(city).countryId(countryId) + .stateProvinceId(stateId).addressTypeId(addressTypeId).isActive(addressIsActive); + + PostClientsRequest clientsRequest = clientRequestFactory.defaultClientCreationRequest().firstname(firstName).lastname(lastName) + .address(Arrays.asList(addressRequest)); + + Response response = clientApi.create6(clientsRequest).execute(); + ErrorHelper.checkSuccessfulApiCall(response); + testContext().set(TestContextKey.CLIENT_CREATE_RESPONSE, response); + + } + + @When("Admin creates a client with Firstname {string} and Lastname {string} with {string} activation date") + public void createClientWithSpecifiedDates(String firstName, String lastName, String activationDate) throws IOException { + + PostClientsRequest clientsRequest = clientRequestFactory.defaultClientCreationRequest().firstname(firstName).lastname(lastName) + .activationDate(activationDate); + + Response response = clientApi.create6(clientsRequest).execute(); + ErrorHelper.checkSuccessfulApiCall(response); + testContext().set(TestContextKey.CLIENT_CREATE_RESPONSE, response); + } + + @Then("Client is created successfully") + public void checkClientCreatedSuccessfully() throws IOException { + Response response = testContext().get(TestContextKey.CLIENT_CREATE_RESPONSE); + + assertThat(response.isSuccessful()).as(ErrorMessageHelper.requestFailed(response)).isTrue(); + } +} diff --git a/fineract-e2e-tests-core/src/test/java/org/apache/fineract/test/support/TestContext.java b/fineract-e2e-tests-core/src/test/java/org/apache/fineract/test/support/TestContext.java new file mode 100644 index 000000000..f9beda2a5 --- /dev/null +++ b/fineract-e2e-tests-core/src/test/java/org/apache/fineract/test/support/TestContext.java @@ -0,0 +1,49 @@ +/** + * 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.test.support; + +import static java.lang.ThreadLocal.withInitial; + +import java.util.HashMap; +import java.util.Map; + +public enum TestContext { + + INSTANCE; + + @SuppressWarnings("ImmutableEnumChecker") + private final ThreadLocal> testContexts = withInitial(HashMap::new); + + public T get(String name) { + Object storedValue = testContexts.get().get(name); + return (T) storedValue; + } + + public Map get() { + return testContexts.get(); + } + + public void set(String name, T object) { + testContexts.get().put(name, object); + } + + public void reset() { + testContexts.get().clear(); + } +} diff --git a/fineract-e2e-tests-core/src/test/java/org/apache/fineract/test/support/TestContextKey.java b/fineract-e2e-tests-core/src/test/java/org/apache/fineract/test/support/TestContextKey.java new file mode 100644 index 000000000..ac1c7472e --- /dev/null +++ b/fineract-e2e-tests-core/src/test/java/org/apache/fineract/test/support/TestContextKey.java @@ -0,0 +1,129 @@ +/** + * 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.test.support; + +import lombok.AccessLevel; +import lombok.NoArgsConstructor; + +@NoArgsConstructor(access = AccessLevel.PRIVATE) +public abstract class TestContextKey { + + public static final String CLIENT_CREATE_RESPONSE = "clientCreateResponse"; + public static final String CLIENT_CREATE_SECOND_CLIENT_RESPONSE = "clientCreateSecondClientResponse"; + public static final String LOAN_CREATE_RESPONSE = "loanCreateResponse"; + public static final String LOAN_CREATE_SECOND_LOAN_RESPONSE = "loanCreateSecondLoanResponse"; + public static final String LOAN_MODIFY_RESPONSE = "loanModifyResponse"; + public static final String ADD_DUE_DATE_CHARGE_RESPONSE = "addDueDateChargeResponse"; + public static final String ADD_PROCESSING_FEE_RESPONSE = "addProcessingFeeResponse"; + public static final String ADD_NSF_FEE_RESPONSE = "addNsfFeeResponse"; + public static final String WAIVE_CHARGE_RESPONSE = "waiveChargeResponse"; + public static final String UNDO_WAIVE_RESPONSE = "waiveNsfFeeResponse"; + public static final String LOAN_APPROVAL_RESPONSE = "loanApprovalResponse"; + public static final String LOAN_APPROVAL_SECOND_LOAN_RESPONSE = "loanApprovalSecondLoanResponse"; + public static final String LOAN_UNDO_APPROVAL_RESPONSE = "loanUndoApprovalResponse"; + public static final String LOAN_DISBURSE_RESPONSE = "loanDisburseResponse"; + public static final String LOAN_DISBURSE_SECOND_LOAN_RESPONSE = "loanDisburseSecondLoanResponse"; + public static final String LOAN_UNDO_DISBURSE_RESPONSE = "loanUndoDisburseResponse"; + public static final String LOAN_REPAYMENT_RESPONSE = "loanRepaymentResponse"; + public static final String LOAN_PAYMENT_TRANSACTION_RESPONSE = "loanPaymentTransactionResponse"; + public static final String LOAN_REFUND_RESPONSE = "loanRefundResponse"; + public static final String LOAN_REAGING_RESPONSE = "loanReAgingResponse"; + public static final String LOAN_REAGING_UNDO_RESPONSE = "loanReAgingUndoResponse"; + public static final String LOAN_REAMORTIZATION_RESPONSE = "loanReAmortizationResponse"; + public static final String LOAN_REAMORTIZATION_UNDO_RESPONSE = "loanReAmortizationUndoResponse"; + public static final String BUSINESS_DATE_RESPONSE = "businessDateResponse"; + public static final String DEFAULT_LOAN_PRODUCT_CREATE_RESPONSE_PIN30 = "loanProductCreateResponsePin30"; + public static final String DEFAULT_LOAN_PRODUCT_CREATE_RESPONSE_PIN30_DUE_DATE = "loanProductCreateResponsePin30DueDate"; + public static final String DEFAULT_LOAN_PRODUCT_CREATE_RESPONSE_PIN30_PAYMENT_STRATEGY_DUE_IN_ADVANCE = "loanProductCreateResponsePin30PaymentStrategyDueInAdvance"; + public static final String DEFAULT_LOAN_PRODUCT_CREATE_RESPONSE_PIN30_PAYMENT_STRATEGY_DUE_IN_ADVANCE_INTEREST_FLAT = "loanProductCreateResponsePin30PaymentStrategyDueInAdvanceInterestFlat"; + public static final String DEFAULT_LOAN_PRODUCT_CREATE_RESPONSE_PIN30_PAYMENT_STRATEGY_DUE_IN_ADVANCE_PENALTY_INTEREST_PRINCIPAL_FEE = "loanProductCreateResponsePin30PaymentStrategyDueInAdvancePenaltyInterestPrincipalFee"; + public static final String DEFAULT_LOAN_PRODUCT_CREATE_RESPONSE_PIN30_PAYMENT_STRATEGY_DUE_IN_ADVANCE_PENALTY_INTEREST_PRINCIPAL_FEE_INTEREST_FLAT = "loanProductCreateResponsePin30PaymentStrategyDueInAdvancePenaltyInterestPrincipalFeeInterestFlat"; + public static final String DEFAULT_LOAN_PRODUCT_CREATE_RESPONSE_PIN30_INTEREST_FLAT = "loanProductCreateResponsePin30InterestFlat"; + public static final String DEFAULT_LOAN_PRODUCT_CREATE_RESPONSE_PIN30_INTEREST_FLAT_OVERDUE_FROM_AMOUNT = "loanProductCreateResponsePin30InterestFlatOverdueFromAmount"; + public static final String DEFAULT_LOAN_PRODUCT_CREATE_RESPONSE_PIN30_INTEREST_FLAT_OVERDUE_FROM_AMOUNT_INTEREST = "loanProductCreateResponsePin30InterestFlatOverdueFromAmountInterest"; + public static final String DEFAULT_LOAN_PRODUCT_CREATE_RESPONSE_PIN30_INTEREST_DECLINING_BALANCE_MULTI_DISBURSE = "loanProductCreateResponsePin30InterestFlatMultiDisburse"; + public static final String DEFAULT_LOAN_PRODUCT_CREATE_RESPONSE_PIN30_INTEREST_DECLINING_PERIOD_SAME_AS_PAYMENT = "loanProductCreateResponsePin30InterestDecliningPeriodSameAsPayment"; + public static final String DEFAULT_LOAN_PRODUCT_CREATE_RESPONSE_PIN30_1MONTH_INTEREST_DECLINING_BALANCE_DAILY_RECALCULATION_COMPOUNDING_MONTHLY = "loanProductCreateResponsePin30InterestDecliningPeriodSameAsPaymentRecalculation"; + public static final String DEFAULT_LOAN_PRODUCT_CREATE_RESPONSE_PIN30_INTEREST_DECLINING_BALANCE_DAILY_RECALCULATION_COMPOUNDING_NONE = "loanProductCreateResponsePin30InterestDecliningBalanceDailyRecalculationCompoundingNone"; + public static final String DEFAULT_LOAN_PRODUCT_CREATE_RESPONSE_PIN30_INTEREST_DECLINING_BALANCE_DAILY_RECALCULATION_SAME_AS_REPAYMENT_COMPOUNDING_NONE = "loanProductCreateResponsePin30InterestDecliningBalanceDailyRecalculationSameAsRepaymentCompoundingNone"; + public static final String DEFAULT_LOAN_PRODUCT_CREATE_RESPONSE_PIN30_INTEREST_DECLINING_BALANCE_SAR_RECALCULATION_SAME_AS_REPAYMENT_COMPOUNDING_NONE_MULTI_DISBURSEMENT = "loanProductCreateResponsePin30InterestDecliningBalanceDailyRecalculationSameAsRepaymentCompoundingNoneMultiDisbursement"; + public static final String DEFAULT_LOAN_PRODUCT_CREATE_RESPONSE_PIN30_INTEREST_DECLINING_BALANCE_DAILY_RECALCULATION_COMPOUNDING_NONE_RESCHEDULE_REDUCE_NR_INSTALLMENTS = "loanProductCreateResponsePin30InterestDecliningBalanceDailyRecalculationCompoundingNoneRescheduleReduceNrInstallments"; + public static final String DEFAULT_LOAN_PRODUCT_CREATE_RESPONSE_PIN30_INTEREST_DECLINING_BALANCE_DAILY_RECALCULATION_COMPOUNDING_NONE_RESCHEDULE_NEXT_REPAYMENTS = "loanProductCreateResponsePin30InterestDecliningBalanceDailyRecalculationCompoundingNoneRescheduleNextRepayments"; + public static final String DEFAULT_LOAN_PRODUCT_CREATE_RESPONSE_PIN30_INTEREST_DECLINING_PERIOD_DAILY = "loanProductCreateResponsePin30InterestDecliningPeriodDaily"; + public static final String DEFAULT_LOAN_PRODUCT_CREATE_RESPONSE_PIN4_DOWNPAYMENT_AUTO_ADVANCED_PAYMENT_ALLOCATION = "loanProductCreateResponsePin4DownPaymentAutoAdvancedPaymentAllocation"; + public static final String DEFAULT_LOAN_PRODUCT_CREATE_RESPONSE_PIN4_DOWNPAYMENT = "loanProductCreateResponsePin4DownPayment"; + public static final String DEFAULT_LOAN_PRODUCT_CREATE_RESPONSE_PIN4_DOWNPAYMENT_INTEREST = "loanProductCreateResponsePin4DownPaymentInterest"; + public static final String DEFAULT_LOAN_PRODUCT_CREATE_RESPONSE_PIN4_DOWNPAYMENT_INTEREST_AUTO = "loanProductCreateResponsePin4DownPaymentInterestAuto"; + public static final String DEFAULT_LOAN_PRODUCT_CREATE_RESPONSE_PIN4_DOWNPAYMENT_AUTO = "loanProductCreateResponsePin4DownPaymentAuto"; + public static final String DEFAULT_LOAN_PRODUCT_CREATE_RESPONSE_PIN4_DOWNPAYMENT_ADVANCED_PAYMENT_ALLOCATION_PROGRESSIVE_LOAN_SCHEDULE = "loanProductCreateResponsePin4DownPaymentProgressiveLoanSchedule"; + public static final String DEFAULT_LOAN_PRODUCT_CREATE_RESPONSE_PIN4_DOWNPAYMENT_ADVANCED_PAYMENT_ALLOCATION_PROGRESSIVE_LOAN_SCHEDULE_VERTICAL = "loanProductCreateResponsePin4DownPaymentProgressiveLoanScheduleVertical"; + public static final String DEFAULT_LOAN_PRODUCT_CREATE_RESPONSE_PIN4_DOWNPAYMENT_ADVANCED_PAYMENT_ALLOCATION_PROGRESSIVE_LOAN_SCHEDULE_INSTALLMENT_LEVEL_DELINQUENCY = "loanProductCreateResponsePin4DownPaymentProgressiveLoanScheduleInstallmentLevelDelinquency"; + public static final String DEFAULT_LOAN_PRODUCT_CREATE_RESPONSE_PIN4_DOWNPAYMENT_ADV_PMT_ALLOC_PROG_SCHEDULE_HOR_INST_LVL_DELINQUENCY_CREDIT_ALLOCATION = "loanProductCreateResponsePin4DownPaymentProgressiveLoanScheduleHorizontalInstallmentLevelDelinquencyCreditAllocation"; + public static final String CHARGE_FOR_LOAN_PERCENT_LATE_CREATE_RESPONSE = "ChargeForLoanPercentLateCreateResponse"; + public static final String CHARGE_FOR_LOAN_PERCENT_LATE_AMOUNT_PLUS_INTEREST_CREATE_RESPONSE = "ChargeForLoanPercentLateAmountPlusInterestCreateResponse"; + public static final String CHARGE_FOR_LOAN_PERCENT_PROCESSING_CREATE_RESPONSE = "ChargeForLoanPercentProcessingCreateResponse"; + public static final String CHARGE_FOR_LOAN_FIXED_LATE_CREATE_RESPONSE = "ChargeForLoanFixedLateCreateResponse"; + public static final String CHARGE_FOR_LOAN_FIXED_RETURNED_PAYMENT_CREATE_RESPONSE = "ChargeForLoanFixedReturnedPaymentCreateResponse"; + public static final String CHARGE_FOR_LOAN_SNOOZE_FEE_CREATE_RESPONSE = "ChargeForLoanSnoozeFeeCreateResponse"; + public static final String CHARGE_FOR_LOAN_NSF_FEE_CREATE_RESPONSE = "ChargeForLoanNsfFeeCreateResponse"; + public static final String CHARGE_FOR_LOAN_DISBURSEMENET_FEE_CREATE_RESPONSE = "ChargeForLoanDisbursementCreateResponse"; + public static final String CHARGE_FOR_LOAN_INSTALLMENT_FEE_CREATE_RESPONSE = "ChargeForLoanInstallmentCreateResponse"; + public static final String CHARGE_FOR_CLIENT_FIXED_FEE_CREATE_RESPONSE = "ChargeForClientFixedFeeCreateResponse"; + public static final String LOAN_RESPONSE = "loanResponse"; + public static final String LOAN_REPAYMENT_UNDO_RESPONSE = "loanRepaymentUndoResponse"; + public static final String LOAN_TRANSACTION_UNDO_RESPONSE = "loanTransactionUndoResponse"; + public static final String LOAN_CHARGEBACK_RESPONSE = "loanChargebackResponse"; + public static final String LOAN_CHARGE_ADJUSTMENT_RESPONSE = "loanChargeAdjustmentResponse"; + public static final String PUT_CURRENCIES_RESPONSE = "putCurrenciesResponse"; + public static final String BATCH_API_CALL_RESPONSE = "batchApiCallResponse"; + public static final String BATCH_API_CALL_IDEMPOTENCY_KEY = "batchApiIdempotencyKey"; + public static final String BATCH_API_CALL_IDEMPOTENCY_KEY_2 = "batchApiIdempotencyKey2"; + public static final String BATCH_API_CALL_CLIENT_EXTERNAL_ID = "batchApiClientExternalId"; + public static final String BATCH_API_CALL_CLIENT_EXTERNAL_ID_2 = "batchApiClientExternalId2"; + public static final String BATCH_API_CALL_LOAN_EXTERNAL_ID = "batchApiLoanExternalId"; + public static final String BATCH_API_CALL_LOAN_EXTERNAL_ID_2 = "batchApiLoanExternalId2"; + public static final String EUR_SAVINGS_ACCOUNT_CREATE_RESPONSE = "eurSavingsAccountCreateResponse"; + public static final String USD_SAVINGS_ACCOUNT_CREATE_RESPONSE = "usdSavingsAccountCreateResponse"; + public static final String EUR_SAVINGS_ACCOUNT_APPROVE_RESPONSE = "eurSavingsAccountApproveResponse"; + public static final String USD_SAVINGS_ACCOUNT_APPROVE_RESPONSE = "usdSavingsAccountApproveResponse"; + public static final String EUR_SAVINGS_ACCOUNT_ACTIVATED_RESPONSE = "eurSavingsAccountActivateResponse"; + public static final String USD_SAVINGS_ACCOUNT_ACTIVATED_RESPONSE = "usdSavingsAccountActivateResponse"; + public static final String EUR_SAVINGS_ACCOUNT_DEPOSIT_RESPONSE = "eurSavingsAccountDepositResponse"; + public static final String USD_SAVINGS_ACCOUNT_DEPOSIT_RESPONSE = "usdSavingsAccountDepositResponse"; + public static final String EUR_SAVINGS_ACCOUNT_WITHDRAW_RESPONSE = "eurSavingsAccountWithdrawResponse"; + public static final String USD_SAVINGS_ACCOUNT_WITHDRAW_RESPONSE = "usdSavingsAccountWithdrawResponse"; + public static final String LOAN_FRAUD_MODIFY_RESPONSE = "loanFraudModifyResponse"; + public static final String DEFAULT_SAVINGS_PRODUCT_CREATE_RESPONSE_EUR = "defaultSavingsProductCreateResponseEur"; + public static final String DEFAULT_SAVINGS_PRODUCT_CREATE_RESPONSE_USD = "defaultSavingsProductCreateResponseUsd"; + public static final String TRANSACTION_IDEMPOTENCY_KEY = "transactionIdempotencyKey"; + public static final String LOAN_CHARGE_OFF_RESPONSE = "loanChargeOffResponse"; + public static final String LOAN_CHARGE_OFF_UNDO_RESPONSE = "loanChargeOffUndoResponse"; + public static final String CREATED_SIMPLE_USER_RESPONSE = "createdSimpleUserResponse"; + public static final String ASSET_EXTERNALIZATION_RESPONSE = "assetExternalizationResponse"; + public static final String ASSET_EXTERNALIZATION_TRANSFER_EXTERNAL_ID_USER_GENERATED = "assetExternalizationTransferExternalIdUserGenerated"; + public static final String ASSET_EXTERNALIZATION_TRANSFER_EXTERNAL_ID_FROM_RESPONSE = "assetExternalizationTransferExternalIdFromResponse"; + public static final String ASSET_EXTERNALIZATION_SALES_TRANSFER_EXTERNAL_ID_FROM_RESPONSE = "assetExternalizationSalesTransferExternalIdFromResponse"; + public static final String ASSET_EXTERNALIZATION_BUYBACK_TRANSFER_EXTERNAL_ID_FROM_RESPONSE = "assetExternalizationBuybackTransferExternalIdFromResponse"; + public static final String ASSET_EXTERNALIZATION_BUYBACK_TRANSFER_PREFIX = "assetExternalizationTransferPrefix"; + public static final String ASSET_EXTERNALIZATION_OWNER_EXTERNAL_ID = "assetExternalizationOwnerExternalId"; + public static final String TRANSACTION_EVENT = "transactionEvent"; + public static final String LOAN_WRITE_OFF_RESPONSE = "loanWriteOffResponse"; + public static final String LOAN_DELINQUENCY_ACTION_RESPONSE = "loanDelinquencyActionResponse"; + +} diff --git a/fineract-e2e-tests-core/src/test/resources/fineract-test-application.properties b/fineract-e2e-tests-core/src/test/resources/fineract-test-application.properties new file mode 100644 index 000000000..d9d724678 --- /dev/null +++ b/fineract-e2e-tests-core/src/test/resources/fineract-test-application.properties @@ -0,0 +1,39 @@ +# +# 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. +# + +fineract-test.api.base-url=${BASE_URL:https://localhost:8443} +fineract-test.api.username=${TEST_USERNAME:mifos} +fineract-test.api.password=${TEST_PASSWORD:password} +fineract-test.api.tenant-id=${TEST_TENANT_ID:default} + +fineract-test.initialization.enabled=${INITIALIZATION_ENABLED:false} + +fineract-test.testrail.enabled=${TESTRAIL_ENABLED:false} +fineract-test.testrail.base-url=${TESTRAIL_BASEURL:} +fineract-test.testrail.username=${TESTRAIL_USERNAME:} +fineract-test.testrail.password=${TESTRAIL_PASSWORD:} +fineract-test.testrail.run-id=${TESTRAIL_RUN_ID:0} + +fineract-test.messaging.jms.broker-url=${ACTIVEMQ_BROKER_URL:} +fineract-test.messaging.jms.broker-username=${ACTIVEMQ_BROKER_USERNAME:} +fineract-test.messaging.jms.broker-password=${ACTIVEMQ_BROKER_PASSWORD:} +fineract-test.messaging.jms.topic-name=${ACTIVEMQ_TOPIC_NAME:} + +fineract-test.event.wait-timeout-in-sec=${EVENT_WAIT_TIMEOUT_IN_SEC:5} +fineract-test.event.verification-enabled=${EVENT_VERIFICATION_ENABLED:false} diff --git a/fineract-e2e-tests-runner/build.gradle b/fineract-e2e-tests-runner/build.gradle new file mode 100644 index 000000000..170da9bd9 --- /dev/null +++ b/fineract-e2e-tests-runner/build.gradle @@ -0,0 +1,91 @@ +/** + * 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. + */ + +plugins { + id 'se.thinkcode.cucumber-runner' version '0.0.11' + id 'io.qameta.allure' version '2.11.2' +} + +apply plugin: 'java' +apply plugin: 'eclipse' + +repositories { + mavenCentral() +} + +dependencies { + testImplementation(project(':fineract-avro-schemas')) + testImplementation(project(':fineract-client')) + testImplementation(project(':fineract-e2e-tests-core').sourceSets.test.output) + + testImplementation 'org.springframework:spring-context' + implementation 'org.springframework:spring-test' + testImplementation 'org.springframework:spring-jms' + + testImplementation 'com.squareup.retrofit2:retrofit:2.9.0' + testImplementation 'commons-httpclient:commons-httpclient:3.1' + testImplementation 'org.apache.commons:commons-lang3:3.14.0' + testImplementation 'com.googlecode.json-simple:json-simple:1.1.1' + testImplementation 'com.google.code.gson:gson:2.10.1' + + testImplementation 'io.cucumber:cucumber-java:7.15.0' + testImplementation 'io.cucumber:cucumber-junit:7.15.0' + testImplementation 'io.cucumber:cucumber-spring:7.15.0' + + testImplementation 'io.qameta.allure:allure-cucumber7-jvm:2.25.0' + + testImplementation 'org.assertj:assertj-core:3.25.3' + testImplementation 'org.junit.jupiter:junit-jupiter-api:5.10.2' + testImplementation 'org.junit.jupiter:junit-jupiter:5.10.2' + + testCompileOnly 'org.projectlombok:lombok:1.18.30' + testAnnotationProcessor 'org.projectlombok:lombok:1.18.30' + + testImplementation "ch.qos.logback:logback-core:1.5.3" + testImplementation "ch.qos.logback:logback-classic:1.5.3" + + testImplementation 'org.apache.activemq:activemq-client:6.0.1' + testImplementation "org.apache.avro:avro:1.11.3" + testImplementation "org.awaitility:awaitility:4.2.0" + testImplementation 'io.github.classgraph:classgraph:4.8.168' + + testImplementation 'org.apache.commons:commons-collections4:4.4' +} + +tasks.named('test') { + useJUnitPlatform() +} + +tasks.named('cucumber').get().finalizedBy 'allureReport' + +tasks.named('cucumber').get().dependsOn 'spotlessCheck' + +cucumber { + tags = 'not @ignore' + main = 'io.cucumber.core.cli.Main' + shorten = 'argfile' + plugin = [ + 'pretty', + 'io.qameta.allure.cucumber7jvm.AllureCucumber7Jvm' + ] +} + +allure { + version = '2.17.3' +} diff --git a/fineract-e2e-tests-runner/src/test/java/org/apache/fineract/test/TestRunner.java b/fineract-e2e-tests-runner/src/test/java/org/apache/fineract/test/TestRunner.java new file mode 100644 index 000000000..c07c0349d --- /dev/null +++ b/fineract-e2e-tests-runner/src/test/java/org/apache/fineract/test/TestRunner.java @@ -0,0 +1,29 @@ +/** + * 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.test; + +import io.cucumber.junit.Cucumber; +import io.cucumber.junit.CucumberOptions; +import org.junit.runner.RunWith; + +@RunWith(Cucumber.class) +@CucumberOptions(features = "src/test/resources/features", glue = { "org.apache.fineract.test.stepdef", + "org.apache.fineract.test.stepdef.common", "org.apache.fineract.test.stepdef.hook", "org.apache.fineract.test.stepdef.loan", + "org.apache.fineract.test.stepdef.saving", "org.apache.fineract.test.config" }) +public class TestRunner {} diff --git a/fineract-e2e-tests-runner/src/test/java/org/apache/fineract/test/config/TestCucumberConfiguration.java b/fineract-e2e-tests-runner/src/test/java/org/apache/fineract/test/config/TestCucumberConfiguration.java new file mode 100644 index 000000000..9a85efb9d --- /dev/null +++ b/fineract-e2e-tests-runner/src/test/java/org/apache/fineract/test/config/TestCucumberConfiguration.java @@ -0,0 +1,26 @@ +/** + * 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.test.config; + +import io.cucumber.spring.CucumberContextConfiguration; +import org.springframework.test.context.ContextConfiguration; + +@CucumberContextConfiguration +@ContextConfiguration(classes = TestApplicationConfiguration.class) +public class TestCucumberConfiguration {} diff --git a/fineract-e2e-tests-runner/src/test/resources/META-INF/fineract-test.config b/fineract-e2e-tests-runner/src/test/resources/META-INF/fineract-test.config new file mode 100644 index 000000000..29e582985 --- /dev/null +++ b/fineract-e2e-tests-runner/src/test/resources/META-INF/fineract-test.config @@ -0,0 +1,2 @@ +org.apache.fineract.test.initializer.Configuration=org.apache.fineract.test.initializer.FineractInitializerConfiguration,\ + org.apache.fineract.test.initializer.base.BaseFineractInitializerConfiguration diff --git a/fineract-e2e-tests-runner/src/test/resources/allure.properties b/fineract-e2e-tests-runner/src/test/resources/allure.properties new file mode 100644 index 000000000..d66fd8925 --- /dev/null +++ b/fineract-e2e-tests-runner/src/test/resources/allure.properties @@ -0,0 +1,20 @@ +# +# 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. +# + +allure.results.directory=fineract-e2e-tests/fineract-e2e-tests-runner/build/allure-results diff --git a/fineract-e2e-tests-runner/src/test/resources/cucumber.properties b/fineract-e2e-tests-runner/src/test/resources/cucumber.properties new file mode 100644 index 000000000..d3b2786eb --- /dev/null +++ b/fineract-e2e-tests-runner/src/test/resources/cucumber.properties @@ -0,0 +1,20 @@ +# +# 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. +# + +cucumber.publish.quiet=true diff --git a/fineract-e2e-tests-runner/src/test/resources/features/Client.feature b/fineract-e2e-tests-runner/src/test/resources/features/Client.feature new file mode 100644 index 000000000..2728bd0bd --- /dev/null +++ b/fineract-e2e-tests-runner/src/test/resources/features/Client.feature @@ -0,0 +1,29 @@ +# +# 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. +# + +@ClientFeature +Feature: Client + + @TestRailId:C14 @Smoke + Scenario Outline: Client creation functionality for Fineract + When Admin creates a client with Firstname and Lastname + Then Client is created successfully + Examples: + | firstName | lastName | + | "FirstName1" | "Test1" | \ No newline at end of file diff --git a/fineract-e2e-tests-runner/src/test/resources/logback.xml b/fineract-e2e-tests-runner/src/test/resources/logback.xml new file mode 100644 index 000000000..28e220339 --- /dev/null +++ b/fineract-e2e-tests-runner/src/test/resources/logback.xml @@ -0,0 +1,35 @@ + + + + + + %d{HH:mm:ss.SSS} [%thread] %-5level %logger{36} - %msg%n + + + + + + + + + + diff --git a/integration-tests/src/test/java/org/apache/fineract/integrationtests/common/Utils.java b/integration-tests/src/test/java/org/apache/fineract/integrationtests/common/Utils.java index d842eb55b..222bc0d13 100644 --- a/integration-tests/src/test/java/org/apache/fineract/integrationtests/common/Utils.java +++ b/integration-tests/src/test/java/org/apache/fineract/integrationtests/common/Utils.java @@ -95,9 +95,7 @@ public final class Utils { public static final String SOURCE_SET_NUMBERS_AND_LETTERS = "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ"; public static final String SOURCE_SET_NUMBERS = "1234567890"; - private Utils() { - - } + private Utils() {} public static void initializeRESTAssured() { RestAssured.baseURI = "https://localhost"; diff --git a/settings.gradle b/settings.gradle index b9ee5672e..2a37c5397 100644 --- a/settings.gradle +++ b/settings.gradle @@ -61,6 +61,8 @@ include ':oauth2-tests' include ':fineract-client' include ':fineract-doc' include ':fineract-avro-schemas' +include ':fineract-e2e-tests-core' +include ':fineract-e2e-tests-runner' // NOTE: custom Docker image with all custom modules included include ':custom:docker' // NOTE: dynamically load custom modules with pattern "custom -> company -> category -> module"