Skip to content

Commit

Permalink
Create test case for airtel-connector.
Browse files Browse the repository at this point in the history
  • Loading branch information
sanchit-0 committed Aug 21, 2024
1 parent 773dfdb commit 7899d66
Show file tree
Hide file tree
Showing 14 changed files with 264 additions and 16 deletions.
2 changes: 1 addition & 1 deletion build.gradle
Original file line number Diff line number Diff line change
Expand Up @@ -148,7 +148,7 @@ dependencies {
implementation 'org.springframework.boot:spring-boot-starter'
testImplementation "com.github.tomakehurst:wiremock-jre8:2.35.0"
testImplementation 'org.springframework.boot:spring-boot-starter-test'
implementation 'org.mifos:ph-ee-connector-common:1.8.1-SNAPSHOT'
implementation 'org.mifos:ph-ee-connector-common:1.10.0-SNAPSHOT'
testImplementation "com.google.truth:truth:1.1.3"
testImplementation 'com.google.code.gson:gson:2.9.0'
testImplementation('io.rest-assured:rest-assured:5.1.1') {
Expand Down
23 changes: 23 additions & 0 deletions src/main/java/org/mifos/integrationtest/config/AirtelConfig.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
package org.mifos.integrationtest.config;

import org.springframework.beans.factory.annotation.Value;
import org.springframework.boot.context.properties.ConfigurationProperties;
import org.springframework.boot.context.properties.EnableConfigurationProperties;
import org.springframework.context.annotation.Configuration;
import org.springframework.stereotype.Component;

@Configuration
@EnableConfigurationProperties
@ConfigurationProperties(prefix = "airtel-connector.mock-airtel")
@Component
public class AirtelConfig {

@Value("${airtel-connector.contactpoint}")
public String airtelConnectorContactPoint;

@Value("${callback_url}")
public String callbackURL;

@Value("${airtel-connector.airtel-ussd-push}")
public String airtelUssdPushEndpoint;
}
3 changes: 3 additions & 0 deletions src/main/resources/application.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -154,6 +154,9 @@ mock-payment-schema:
mock-batch-authorization: "/batches/"
actuator: "/actuator/health"

airtel-connector:
contactpoint: "http://localhost:2901"
airtel-ussd-push: "/merchant/v2/payments/"

netflix-conductor:
server:
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -54,7 +54,7 @@ public void setup() {
@Disabled
public void testSendCollectionRequest() throws JSONException {
requestSpec.header(Utils.X_CORRELATIONID, clientCorrelationId);
JSONObject collectionRequestBody = CollectionHelper.getCollectionRequestBody("1", "254708374149", "24450523");
JSONObject collectionRequestBody = CollectionHelper.getCollectionRequestBody("1", "USD", "254708374149", "24450523");
logger.info(String.valueOf(collectionRequestBody));
String json = RestAssured.given(requestSpec).baseUri(channelConnectorConfig.channelConnectorContactPoint)
.body(collectionRequestBody.toString()).expect().spec(statusOkResponseSpec).when().post("/channel/collection").andReturn()
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -44,7 +44,7 @@ public void setup() {
@Test
@Disabled
public void testSendCollectionRequest() throws JSONException {
JSONObject collectionRequestBody = CollectionHelper.getCollectionRequestBody("1", "254708374149", "24450523");
JSONObject collectionRequestBody = CollectionHelper.getCollectionRequestBody("1", "USD", "254708374149", "24450523");
log.debug("{}", collectionRequestBody);
String json = RestAssured.given(requestSpec).baseUri("http://localhost:5002").body(collectionRequestBody.toString()).expect()
.spec(statusOkResponseSpec).when().post("/channel/collection").andReturn().asString();
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -15,15 +15,18 @@ public final class CollectionHelper {

private CollectionHelper() {}

public static JSONObject getCollectionRequestBody(String amount, String msisdn, String accountId) throws JSONException {
public static JSONObject getCollectionRequestBody(String amount, String currency, String msisdn, String accountId)
throws JSONException {
List<Pair<String, String>> payers = new ArrayList<>();
payers.add(new Pair<>("MSISDN", msisdn));
payers.add(new Pair<>("ACCOUNTID", accountId));

JSONObject body = new JSONObject();
body.put("payer", getPayerArray(payers));
body.put("amount", getAmountObject(amount));
body.put("amount", getAmountObject(amount, currency));
body.put("transactionType", getTransactionTypeObject());
body.put("customData", new JSONArray());
body.put("note", "Testing");
return body;
}

Expand All @@ -34,7 +37,7 @@ public static JSONObject getCollectionRequestBody(String key1, String key2) thro

JSONObject body = new JSONObject();
body.put("payer", getPayerArray(payers));
body.put("amount", getAmountObject("1"));
body.put("amount", getAmountObject("1", "USD"));
body.put("transactionType", getTransactionTypeObject());
return body;
}
Expand All @@ -58,16 +61,16 @@ private static JSONObject getPayerObject(String key, String value) throws JSONEx
return payerObject;
}

private static JSONObject getAmountObject(String amount) throws JSONException {
private static JSONObject getAmountObject(String amount, String currency) throws JSONException {
JSONObject amountObject = new JSONObject();
amountObject.put("currency", "USD");
amountObject.put("currency", currency);
amountObject.put("amount", amount);
return amountObject;
}

private static JSONObject getTransactionTypeObject() throws JSONException {
JSONObject txnType = new JSONObject();
txnType.put("scenario", "MPESA");
txnType.put("scenario", "AIRTEL");
txnType.put("subScenario", "BUYGOODS");
txnType.put("initiator", "PAYEE");
txnType.put("initiatorType", "BUSINESS");
Expand Down
2 changes: 2 additions & 0 deletions src/test/java/org/mifos/integrationtest/common/Utils.java
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,8 @@ private Utils() {}
public static final String QUERY_PARAM_TYPE = "type";
public static final String HEADER_REGISTERING_INSTITUTE_ID = "X-Registering-Institution-ID";
public static final String HEADER_PROGRAM_ID = "X-Program-ID";
public static final String X_PAYEMENTSCHEMA = "X-Payment-Scheme";
public static final String X_COUNTRY = "X-Country";

public static void initializeRESTAssured() {
RestAssured.baseURI = "https://localhost";
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,147 @@
package org.mifos.integrationtest.cucumber.stepdef;

import static com.github.tomakehurst.wiremock.client.WireMock.equalTo;
import static com.github.tomakehurst.wiremock.client.WireMock.matchingJsonPath;
import static com.github.tomakehurst.wiremock.client.WireMock.postRequestedFor;
import static com.github.tomakehurst.wiremock.client.WireMock.urlEqualTo;
import static com.github.tomakehurst.wiremock.client.WireMock.verify;
import static com.google.common.truth.Truth.assertThat;
import static java.util.concurrent.TimeUnit.SECONDS;
import static org.awaitility.Awaitility.await;
import static org.mifos.integrationtest.common.Utils.CONTENT_TYPE;

import io.cucumber.java.en.And;
import io.cucumber.java.en.Given;
import io.cucumber.java.en.Then;
import io.cucumber.java.en.When;
import io.restassured.RestAssured;
import io.restassured.builder.ResponseSpecBuilder;
import io.restassured.specification.RequestSpecification;
import org.json.JSONException;
import org.json.JSONObject;
import org.mifos.connector.common.mobilemoney.airtel.dto.AirtelPaymentRequestDTO;
import org.mifos.connector.common.mobilemoney.airtel.dto.AirtelPaymentRequestSubscriberDTO;
import org.mifos.connector.common.mobilemoney.airtel.dto.AirtelPaymentRequestTransactionDTO;
import org.mifos.connector.common.mobilemoney.airtel.dto.AirtelPaymentResponseDTO;
import org.mifos.integrationtest.common.CollectionHelper;
import org.mifos.integrationtest.common.Utils;
import org.mifos.integrationtest.config.AirtelConfig;
import org.springframework.beans.factory.annotation.Autowired;

public class AirtelStepDef extends BaseStepDef {

@Autowired
AirtelConfig airtelConfig;

@Given("I have MSISDN as {string}")
public void iHaveMSISDNAs(String msisdn) {
scenarioScopeState.msisdn = msisdn;
assertThat(scenarioScopeState.msisdn).isNotEmpty();
}

@Given("I have clientCorrelationId as {string}")
public void iHaveClientCorrelationIdAs(String clientCorrelationId) {
scenarioScopeState.clientCorrelationId = clientCorrelationId;
assertThat(scenarioScopeState.clientCorrelationId).isNotEmpty();
}

@Given("I have accountId as {string}")
public void iHaveAccountId(String accountId) {
scenarioScopeState.accountId = accountId;
assertThat(scenarioScopeState.accountId).isNotEmpty();
}

@And("I have transaction id as {string}")
public void iHaveTransactionIdAs(String transactionId) {
scenarioScopeState.transactionId = transactionId;
assertThat(scenarioScopeState.transactionId).isNotEmpty();
}

@And("I have amount as {string}")
public void iHaveAmountAs(String amount) {
scenarioScopeState.amount = amount;
assertThat(scenarioScopeState.amount).isNotEmpty();
}

@And("I have currency as {string}")
public void iHaveCurrencyAs(String currency) {
scenarioScopeState.currency = currency;
assertThat(scenarioScopeState.currency).isNotEmpty();
}

@And("I have the request body with payer ams identifiers using keys MSISDN and accountId, currency {string}, and amount {string}")
public void iHaveRequestBody(String currency, String amount) throws JSONException {
JSONObject collectionRequestBody = CollectionHelper.getCollectionRequestBody(amount, currency, scenarioScopeState.msisdn,
scenarioScopeState.accountId);
scenarioScopeState.requestBody = collectionRequestBody;
logger.info(String.valueOf(scenarioScopeState.requestBody));
}

@Then("I should be able to verify that {string} endpoint received {int} request with status code {string}")
public void iShouldBeAbleToVerifyThatEndpointReceivedRequestWithStatusCode(String endpoint, int numberOfRequest, String statusCode) {
await().atMost(awaitMost, SECONDS).pollInterval(pollInterval, SECONDS).untilAsserted(() -> {
verify(numberOfRequest, postRequestedFor(urlEqualTo(endpoint))
.withRequestBody(matchingJsonPath("$.transaction.statusCode", equalTo(statusCode))));
});
}

@And("I can mock USSD push payment request body")
public void iCanMockUSSDPushPaymentRequestBody() {
// The mock Airtel API does not process or validate the request body.
// Adding random values for the request body.
AirtelPaymentRequestDTO airtelPaymentRequestDTO = new AirtelPaymentRequestDTO();
airtelPaymentRequestDTO.setReference("Testing transaction");

AirtelPaymentRequestSubscriberDTO airtelPaymentRequestSubscriberDTO = new AirtelPaymentRequestSubscriberDTO();
airtelPaymentRequestSubscriberDTO.setCountry("KE");
airtelPaymentRequestSubscriberDTO.setCurrency("KES");
airtelPaymentRequestSubscriberDTO.setMsisdn(scenarioScopeState.msisdn);
airtelPaymentRequestDTO.setSubscriber(airtelPaymentRequestSubscriberDTO);

AirtelPaymentRequestTransactionDTO airtelPaymentRequestTransactionDTO = new AirtelPaymentRequestTransactionDTO();
airtelPaymentRequestTransactionDTO.setAmount(1000);
airtelPaymentRequestTransactionDTO.setCountry("KE");
airtelPaymentRequestTransactionDTO.setCurrency("KES");
airtelPaymentRequestTransactionDTO.setId(scenarioScopeState.transactionId);
airtelPaymentRequestDTO.setTransaction(airtelPaymentRequestTransactionDTO);

scenarioScopeState.mockAirtelUSSDPaymentRequest = airtelPaymentRequestDTO;
logger.info("mockAirtelUSSDPaymentRequest: {}", scenarioScopeState.mockAirtelUSSDPaymentRequest);
assertThat(scenarioScopeState.mockAirtelUSSDPaymentRequest).isNotNull();
}

@When("I call USSD push payment API with MSISDN with expected status of {int}")
public void iCallUSSDPushPaymentAPIWithMSISDNWithExpectedStatusOf(int expectedStatus) {
// The mock Airtel API does not process or validate headers.
// Adding random values for headers.
RequestSpecification requestSpec = Utils.getDefaultSpec();
requestSpec.header(CONTENT_TYPE, "application/json");
requestSpec.header("X-Country", "KE");
requestSpec.header("X-Currency", "KES");
requestSpec.header("Authorization", "Bearer UC23y1292w");
requestSpec.header("x-signature", "MGsp1Hs683Ag==");
requestSpec.header("x-key", "DVZCgY91bS==");
scenarioScopeState.response = RestAssured.given(requestSpec).baseUri(airtelConfig.airtelConnectorContactPoint)
.body(scenarioScopeState.mockAirtelUSSDPaymentRequest).expect()
.spec(new ResponseSpecBuilder().expectStatusCode(expectedStatus).build()).when().post(airtelConfig.airtelUssdPushEndpoint)
.andReturn().asString();

logger.info("USSD Push Payment Req response: {}", scenarioScopeState.response);
}

@And("I should get airtel USSD push payment response body in response")
public void iShouldGetAirtelUSSDPushPaymentResponseBodyInResponse() throws JSONException {
try {
scenarioScopeState.airtelPaymentResponseDTO = objectMapper.readValue(scenarioScopeState.response,
AirtelPaymentResponseDTO.class);
} catch (Exception e) {
scenarioScopeState.airtelPaymentResponseDTO = null;
}
}

@And("I should get response with data field null")
public void iShouldGetResponseWithDataFieldNull() {
assertThat(scenarioScopeState.airtelPaymentResponseDTO.getData()).isNull();
}

}
Original file line number Diff line number Diff line change
Expand Up @@ -9,20 +9,23 @@
import io.restassured.RestAssured;
import io.restassured.builder.ResponseSpecBuilder;
import io.restassured.specification.RequestSpecification;
import java.util.UUID;
import org.json.JSONException;
import org.json.JSONObject;
import org.mifos.integrationtest.common.CollectionHelper;
import org.mifos.integrationtest.common.Utils;
import org.mifos.integrationtest.common.dto.CollectionResponse;
import org.mifos.integrationtest.common.dto.operationsapp.GetTransactionRequestResponse;
import org.mifos.integrationtest.config.AirtelConfig;
import org.springframework.beans.factory.annotation.Autowired;

public class ChannelCollectionStepDef extends BaseStepDef {

@Autowired
ScenarioScopeState scenarioScopeState;

@Autowired
AirtelConfig mockAirtelConfig;

@And("I have the request body with payer ams identifier keys as {string} and {string}")
public void iHaveRequestBody(String key1, String key2) throws JSONException {
JSONObject collectionRequestBody = CollectionHelper.getCollectionRequestBody(key1, key2);
Expand All @@ -33,18 +36,31 @@ public void iHaveRequestBody(String key1, String key2) throws JSONException {
@When("I call the channel collection API with client correlation id and expected status of {int}")
public void iCallChannelCollectionAPI(int expectedStatus) {
RequestSpecification requestSpec = Utils.getDefaultSpec(scenarioScopeState.tenant);
requestSpec.header(Utils.X_CORRELATIONID, UUID.randomUUID());
requestSpec.header(Utils.X_CORRELATIONID, "123456");
scenarioScopeState.response = RestAssured.given(requestSpec).baseUri(channelConnectorConfig.channelConnectorContactPoint)
// BaseStepDef.response = RestAssured.given(requestSpec).baseUri("https://localhost:8443")
.body(scenarioScopeState.requestBody.toString()).expect()
.spec(new ResponseSpecBuilder().expectStatusCode(expectedStatus).build()).when()
.post(channelConnectorConfig.collectionEndpoint).andReturn().asString();
}

@When("I call the channel collection API with client correlation id, country {string}, callback {string}, payment schema {string} and expected status of {int}")
public void iCallChannelCollectionsAPII(String country, String callback, String paymentSchema, int expectedStatus) {
RequestSpecification requestSpec = Utils.getDefaultSpec(scenarioScopeState.tenant, scenarioScopeState.clientCorrelationId);
requestSpec.header(Utils.X_PAYEMENTSCHEMA, paymentSchema);
requestSpec.header(Utils.X_COUNTRY, country);
requestSpec.header(Utils.X_CallbackURL, "http://127.0.0.1:53013" + callback);
scenarioScopeState.response = RestAssured.given(requestSpec).baseUri(channelConnectorConfig.channelConnectorContactPoint)
.body(scenarioScopeState.requestBody.toString()).expect()
.spec(new ResponseSpecBuilder().expectStatusCode(expectedStatus).build()).when()
.post(channelConnectorConfig.collectionEndpoint).andReturn().asString();
}

@Then("I should get transaction id in response")
public void iGetTransactionIdInResponse() {
CollectionResponse response = (new Gson()).fromJson(scenarioScopeState.response, CollectionResponse.class);
scenarioScopeState.transactionId = response.getTransactionId();
logger.info("THE TXN ID IS BEING PASSED {}", scenarioScopeState.transactionId);
assertThat(response.getTransactionId()).isNotNull();
}

Expand All @@ -61,7 +77,7 @@ public void iCallTheTxnAPIWithTransactionId() throws InterruptedException {
requestSpec.header("Authorization", "Bearer " + scenarioScopeState.accessToken);
}
requestSpec.queryParam("transactionId", scenarioScopeState.transactionId);

logger.info("the transactionID is {}", scenarioScopeState.transactionId);
scenarioScopeState.response = RestAssured.given(requestSpec).baseUri(operationsAppConfig.operationAppContactPoint).expect()
.spec(new ResponseSpecBuilder().expectStatusCode(200).build()).when().get(operationsAppConfig.transactionRequestsEndpoint)
.andReturn().asString();
Expand All @@ -73,6 +89,7 @@ public void iCallTheTxnAPIWithTransactionId() throws InterruptedException {
public void assertValues() {
GetTransactionRequestResponse transactionRequestResponse = (new Gson()).fromJson(scenarioScopeState.response,
GetTransactionRequestResponse.class);

assertThat(transactionRequestResponse.getContent().size()).isEqualTo(1);
assertThat(transactionRequestResponse.getContent().get(0).getState()).isAnyOf("ACCEPTED", "FAILED");
assertThat(transactionRequestResponse.getContent().get(0).getExternalId()).isNotNull();
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -81,7 +81,7 @@ public void checkDate() {
public void iCallCollectionApiWithExpectedStatus(int expectedStatus) throws JSONException {
RequestSpecification requestSpec = Utils.getDefaultSpec(scenarioScopeState.tenant);
requestSpec.header(Utils.X_CORRELATIONID, clientCorrelationId);
JSONObject collectionRequestBody = CollectionHelper.getCollectionRequestBody("1", "254708374149", "24450523");
JSONObject collectionRequestBody = CollectionHelper.getCollectionRequestBody("1", "USD", "254708374149", "24450523");
logger.info(String.valueOf(collectionRequestBody));
String json = RestAssured.given(requestSpec).baseUri(channelConnectorConfig.channelConnectorContactPoint)
.body(collectionRequestBody.toString()).expect().spec(new ResponseSpecBuilder().expectStatusCode(expectedStatus).build())
Expand Down
Loading

0 comments on commit 7899d66

Please sign in to comment.