fix(mpesa-settings): add test cases to verify transactions
diff --git a/erpnext/erpnext_integrations/doctype/mpesa_settings/mpesa_settings.py b/erpnext/erpnext_integrations/doctype/mpesa_settings/mpesa_settings.py
index 1d318bb..dea4d81 100644
--- a/erpnext/erpnext_integrations/doctype/mpesa_settings/mpesa_settings.py
+++ b/erpnext/erpnext_integrations/doctype/mpesa_settings/mpesa_settings.py
@@ -26,11 +26,19 @@
 	def on_update(self):
 		create_custom_pos_fields()
 		create_payment_gateway('Mpesa-' + self.payment_gateway_name, settings='Mpesa Settings', controller=self.payment_gateway_name)
-		create_mode_of_payment('Mpesa-' + self.payment_gateway_name, payment_type="Phone")
 		call_hook_method('payment_gateway_enabled', gateway='Mpesa-' + self.payment_gateway_name, payment_channel="Phone")
 
+		# required to fetch the bank account details from the payment gateway account
+		frappe.db.commit()
+		create_mode_of_payment('Mpesa-' + self.payment_gateway_name, payment_type="Phone")
+
 	def request_for_payment(self, **kwargs):
-		response = frappe._dict(generate_stk_push(**kwargs))
+		if frappe.flags.in_test:
+			from erpnext.erpnext_integrations.doctype.mpesa_settings.test_mpesa_settings import get_payment_request_response_payload
+			response = frappe._dict(get_payment_request_response_payload())
+		else:
+			response = frappe._dict(generate_stk_push(**kwargs))
+
 		self.handle_api_response("CheckoutRequestID", kwargs, response)
 
 	def get_account_balance_info(self):
@@ -39,7 +47,13 @@
 			reference_docname=self.name,
 			doc_details=vars(self)
 		)
-		response = frappe._dict(get_account_balance(payload))
+
+		if frappe.flags.in_test:
+			from erpnext.erpnext_integrations.doctype.mpesa_settings.test_mpesa_settings import get_test_account_balance_response
+			response = frappe._dict(get_test_account_balance_response())
+		else:
+			response = frappe._dict(get_account_balance(payload))
+
 		self.handle_api_response("ConversationID", payload, response)
 
 	def handle_api_response(self, global_id, request_dict, response):
@@ -92,7 +106,6 @@
 def verify_transaction(**kwargs):
 	"""Verify the transaction result received via callback from stk."""
 	transaction_response = frappe._dict(kwargs["Body"]["stkCallback"])
-	frappe.logger().debug(transaction_response)
 
 	checkout_id = getattr(transaction_response, "CheckoutRequestID", "")
 	request = frappe.get_doc("Integration Request", checkout_id)
@@ -148,14 +161,13 @@
 		return
 
 	transaction_data = frappe._dict(loads(request.data))
-	frappe.logger().debug(account_balance_response)
 
 	if account_balance_response["ResultCode"] == 0:
 		try:
 			result_params = account_balance_response["ResultParameters"]["ResultParameter"]
 
 			balance_info = fetch_param_value(result_params, "AccountBalance", "Key")
-			balance_info = convert_to_json(balance_info)
+			balance_info = format_string_to_json(balance_info)
 
 			ref_doc = frappe.get_doc(transaction_data.reference_doctype, transaction_data.reference_docname)
 			ref_doc.db_set("account_balance", balance_info)
@@ -168,15 +180,15 @@
 	else:
 		request.handle_failure(account_balance_response)
 
-def convert_to_json(balance_info):
+def format_string_to_json(balance_info):
 	"""
-	Convert string to json.
+	Format string to json.
 
 	e.g: '''Working Account|KES|481000.00|481000.00|0.00|0.00'''
 	=> {'Working Account': {'current_balance': '481000.00',
 		'available_balance': '481000.00',
 		'reserved_balance': '0.00',
-		'uncleared_balance': '0.00'}
+		'uncleared_balance': '0.00'}}
 	"""
 	balance_dict = frappe._dict()
 	for account_info in balance_info.split("&"):
diff --git a/erpnext/erpnext_integrations/doctype/mpesa_settings/test_mpesa_settings.py b/erpnext/erpnext_integrations/doctype/mpesa_settings/test_mpesa_settings.py
index 4aa970e..55ccff3 100644
--- a/erpnext/erpnext_integrations/doctype/mpesa_settings/test_mpesa_settings.py
+++ b/erpnext/erpnext_integrations/doctype/mpesa_settings/test_mpesa_settings.py
@@ -2,9 +2,239 @@
 # Copyright (c) 2020, Frappe Technologies Pvt. Ltd. and Contributors
 # See license.txt
 from __future__ import unicode_literals
-
-# import frappe
+from json import dumps
+import frappe
 import unittest
+from erpnext.erpnext_integrations.doctype.mpesa_settings.mpesa_settings import process_balance_info, verify_transaction
+from erpnext.accounts.doctype.pos_invoice.test_pos_invoice import create_pos_invoice
 
 class TestMpesaSettings(unittest.TestCase):
-	pass
+	def test_creation_of_payment_gateway(self):
+		mpesa_doc = create_mpesa_settings(payment_gateway_name="_Test")
+
+		mode_of_payment = frappe.get_doc("Mode of Payment", "Mpesa-_Test")
+		self.assertTrue(frappe.db.exists("Payment Gateway Account", {'payment_gateway': "Mpesa-_Test"}))
+		self.assertTrue(mode_of_payment.name)
+		self.assertEquals(mode_of_payment.type, "Phone")
+
+	def test_processing_of_account_balance(self):
+		mpesa_doc = create_mpesa_settings(payment_gateway_name="_Account Balance")
+		mpesa_doc.get_account_balance_info()
+
+		callback_response = get_account_balance_callback_payload()
+		process_balance_info(**callback_response)
+		integration_request = frappe.get_doc("Integration Request", "AG_20200927_00007cdb1f9fb6494315")
+
+		# test integration request creation and successful update of the status on receiving callback response
+		self.assertTrue(integration_request)
+		self.assertEquals(integration_request.status, "Completed")
+
+		# test formatting of account balance received as string to json with appropriate currency symbol
+		mpesa_doc.reload()
+		self.assertEquals(mpesa_doc.account_balance, dumps({
+			"Working Account": {
+				"current_balance": "Sh 481,000.00",
+				"available_balance": "Sh 481,000.00",
+				"reserved_balance": "Sh 0.00",
+				"uncleared_balance": "Sh 0.00"
+			}
+		}))
+
+	def test_processing_of_callback_payload(self):
+		mpesa_doc = create_mpesa_settings(payment_gateway_name="Payment")
+		mpesa_account = frappe.db.get_value("Payment Gateway Account", {"payment_gateway": 'Mpesa-Payment'}, "payment_account")
+		frappe.db.set_value("Account", mpesa_account, "account_currency", "KES")
+
+		pos_invoice = create_pos_invoice(do_not_submit=1)
+		pos_invoice.append("payments", {'mode_of_payment': 'Mpesa-Payment', 'account': mpesa_account, 'amount': 500})
+		pos_invoice.contact_mobile = "093456543894"
+		pos_invoice.currency = "KES"
+		pos_invoice.save()
+
+		pr = pos_invoice.create_payment_request()
+		# test payment request creation
+		self.assertEquals(pr.payment_gateway, "Mpesa-Payment")
+
+		callback_response = get_payment_callback_payload()
+		verify_transaction(**callback_response)
+		# test creation of integration request
+		integration_request = frappe.get_doc("Integration Request", "ws_CO_061020201133231972")
+
+		# test integration request creation and successful update of the status on receiving callback response
+		self.assertTrue(integration_request)
+		self.assertEquals(integration_request.status, "Completed")
+
+		pos_invoice.reload()
+		integration_request.reload()
+		self.assertEquals(pos_invoice.mpesa_receipt_number, "LGR7OWQX0R")
+		self.assertEquals(integration_request.status, "Completed")
+
+def create_mpesa_settings(payment_gateway_name="Express"):
+	if frappe.db.exists("Mpesa Settings", payment_gateway_name):
+		return frappe.get_doc("Mpesa Settings", payment_gateway_name)
+
+	doc = frappe.get_doc(dict(
+		doctype="Mpesa Settings",
+		payment_gateway_name=payment_gateway_name,
+		consumer_key="5sMu9LVI1oS3oBGPJfh3JyvLHwZOdTKn",
+		consumer_secret="VI1oS3oBGPJfh3JyvLHw",
+		online_passkey="LVI1oS3oBGPJfh3JyvLHwZOd",
+		till_number="174379"
+	))
+
+	doc.insert(ignore_permissions=True)
+	return doc
+
+def get_test_account_balance_response():
+	"""Response received after calling the account balance API."""
+	return {
+		"ResultType":0,
+		"ResultCode":0,
+		"ResultDesc":"The service request has been accepted successfully.",
+		"OriginatorConversationID":"10816-694520-2",
+		"ConversationID":"AG_20200927_00007cdb1f9fb6494315",
+		"TransactionID":"LGR0000000",
+		"ResultParameters":{
+		"ResultParameter":[
+			{
+			"Key":"ReceiptNo",
+			"Value":"LGR919G2AV"
+			},
+			{
+			"Key":"Conversation ID",
+			"Value":"AG_20170727_00004492b1b6d0078fbe"
+			},
+			{
+			"Key":"FinalisedTime",
+			"Value":20170727101415
+			},
+			{
+			"Key":"Amount",
+			"Value":10
+			},
+			{
+			"Key":"TransactionStatus",
+			"Value":"Completed"
+			},
+			{
+			"Key":"ReasonType",
+			"Value":"Salary Payment via API"
+			},
+			{
+			"Key":"TransactionReason"
+			},
+			{
+			"Key":"DebitPartyCharges",
+			"Value":"Fee For B2C Payment|KES|33.00"
+			},
+			{
+			"Key":"DebitAccountType",
+			"Value":"Utility Account"
+			},
+			{
+			"Key":"InitiatedTime",
+			"Value":20170727101415
+			},
+			{
+			"Key":"Originator Conversation ID",
+			"Value":"19455-773836-1"
+			},
+			{
+			"Key":"CreditPartyName",
+			"Value":"254708374149 - John Doe"
+			},
+			{
+			"Key":"DebitPartyName",
+			"Value":"600134 - Safaricom157"
+			}
+		]
+	},
+	"ReferenceData":{
+	"ReferenceItem":{
+		"Key":"Occasion",
+		"Value":"aaaa"
+	}
+	}
+		}
+
+def get_payment_request_response_payload():
+	"""Response received after successfully calling the stk push process request API."""
+	return {
+		"MerchantRequestID": "8071-27184008-1",
+		"CheckoutRequestID": "ws_CO_061020201133231972",
+		"ResultCode": 0,
+		"ResultDesc": "The service request is processed successfully.",
+		"CallbackMetadata": {
+			"Item": [
+				{ "Name": "Amount", "Value": 500.0 },
+				{ "Name": "MpesaReceiptNumber", "Value": "LGR7OWQX0R" },
+				{ "Name": "TransactionDate", "Value": 20201006113336 },
+				{ "Name": "PhoneNumber", "Value": 254723575670 }
+			]
+		}
+	}
+
+
+def get_payment_callback_payload():
+	"""Response received from the server as callback after calling the stkpush process request API."""
+	return {
+		"Body":{
+		"stkCallback":{
+			"MerchantRequestID":"19465-780693-1",
+			"CheckoutRequestID":"ws_CO_061020201133231972",
+			"ResultCode":0,
+			"ResultDesc":"The service request is processed successfully.",
+			"CallbackMetadata":{
+			"Item":[
+				{
+				"Name":"Amount",
+				"Value":500
+				},
+				{
+				"Name":"MpesaReceiptNumber",
+				"Value":"LGR7OWQX0R"
+				},
+				{
+				"Name":"Balance"
+				},
+				{
+				"Name":"TransactionDate",
+				"Value":20170727154800
+				},
+				{
+				"Name":"PhoneNumber",
+				"Value":254721566839
+				}
+			]
+			}
+		}
+		}
+	}
+
+def get_account_balance_callback_payload():
+	"""Response received from the server as callback after calling the account balance API."""
+	return {
+		"Result":{
+			"ResultType": 0,
+			"ResultCode": 0,
+			"ResultDesc": "The service request is processed successfully.",
+			"OriginatorConversationID": "16470-170099139-1",
+			"ConversationID": "AG_20200927_00007cdb1f9fb6494315",
+			"TransactionID": "OIR0000000",
+			"ResultParameters": {
+				"ResultParameter": [
+					{
+						"Key": "AccountBalance",
+						"Value": "Working Account|KES|481000.00|481000.00|0.00|0.00"
+					},
+					{ "Key": "BOCompletedTime", "Value": 20200927234123 }
+				]
+			},
+			"ReferenceData": {
+				"ReferenceItem": {
+					"Key": "QueueTimeoutURL",
+					"Value": "https://internalsandbox.safaricom.co.ke/mpesa/abresults/v1/submit"
+				}
+			}
+		}
+	}
\ No newline at end of file