def test_logging_convert_amount(self): """Test that a GET service with parameters can connect to a server and is logged appropriately""" test_path = "/v1/1234/services/convert/amount" # relative url through which the request should be sent logger = TestLogger() query_params = ConvertAmountParams() query_params.amount = 1000 query_params.source = "EUR" query_params.target = "USD" response_body = read_resource("convertAmount.json") handler = self.create_handler( body=response_body, additional_headers=(('Content-type', 'application/json'), )) with create_server_listening( handler) as address: # start server to listen to request with create_client(address) as client: # create client under test client.enable_logging(logger) response = client.merchant("1234").services().convert_amount( query_params) self.assertIsNotNone(response) self.assertIsNotNone(response.converted_amount) self.assertEqual( test_path, self.request_path.split("?")[0], 'Request has arrived at {} instead of {}'.format( self.request_path.split("?")[0], test_path)) self.assertLogsRequestAndResponse(logger, "convertAmount")
def test_create_payment_rejected(self): """Test that a POST service that is rejected results in an error, which is logged appropriately""" test_path = "/v1/1234/payments" # relative url through which the request should be sent logger = TestLogger() request = create_payment_request() response_body = read_resource("createPayment.failure.rejected.json") handler = self.create_handler( response_code=402, body=response_body, additional_headers=(('Content-type', 'application/json'), )) with create_server_listening( handler) as address: # start server to listen to request with create_client(address) as client: # create client under test client.enable_logging(logger) with self.assertRaises(DeclinedPaymentException) as exc: client.merchant("1234").payments().create(request) self.assertIsNotNone(exc.exception.create_payment_result) self.assertIsNotNone(exc.exception.create_payment_result.payment) self.assertIsNotNone(exc.exception.create_payment_result.payment.id) self.assertEqual(test_path, self.request_path, 'Request has arrived at the wrong path') self.assertLogsRequestAndResponse(logger, "createPayment_failure_rejected")
def test_logging_test_connection(self): """Test that a GET service without parameters can connect to a server and is logged appropriately""" test_path = "/v1/1234/services/testconnection" # relative url through which the request should be sent logger = TestLogger() response_body = read_resource("testConnection.json") handler = self.create_handler( body=response_body, additional_headers=(('Content-type', 'application/json'), )) with create_server_listening( handler) as address: # start server to listen to request with create_client(address) as client: # create client under test client.enable_logging(logger) response = client.merchant("1234").services().testconnection() self.assertIsNotNone(response) self.assertEqual(test_path, self.request_path, 'Request has arrived at the wrong path') self.assertEqual('OK', response.result) self.assertEqual(2, len(logger.entries)) # for request and response, check that the message exists in the logs and there are no errors request_entry = logger.entries[0] self.assertIsNotNone(request_entry[0]) self.assertIsNone(request_entry[1]) response_entry = logger.entries[1] self.assertIsNotNone(response_entry[0]) self.assertIsNone(response_entry[1]) # for request and response, check that their output is as predicted and that they match each other self.assertRequestAndResponse(request_entry[0], response_entry[0], "testConnection")
def test_create_payment(self): """Test that a POST service with 201 response can connect to a server and is logged appropriately""" test_path = "/v1/1234/payments" # relative url through which the request should be sent logger = TestLogger() request = create_payment_request() response_body = read_resource("createPayment.json") additional_headers = (("content-Type", "application/json"), ( "Location", "http://localhost/v1/1234/payments/000000123410000595980000100001") ) handler = self.create_handler(response_code=201, body=response_body, additional_headers=additional_headers) with create_server_listening( handler) as address: # start server to listen to request with create_client(address) as client: # create client under test client.enable_logging(logger) response = client.merchant("1234").payments().create(request) self.assertIsNotNone(response) self.assertIsNotNone(response.payment) self.assertIsNotNone(response.payment.id) self.assertEqual( test_path, self.request_path, 'Request has arrived at "{1}" while it should have been delivered to "{0}"' .format(test_path, self.request_path)) self.assertLogsRequestAndResponse(logger, "createPayment")
def test_create_payment_invalid_card_number(self): """Test that a POST service that is invalid results in an error, which is logged appropriately""" test_path = "/v1/1234/payments" # relative url through which the request should be sent logger = TestLogger() request = create_payment_request() response_body = read_resource( "createPayment.failure.invalidCardNumber.json") handler = self.create_handler( response_code=400, body=response_body, additional_headers=(('Content-type', 'application/json'), )) with create_server_listening( handler) as address: # start server to listen to request with create_client(address) as client: # create client under test client.enable_logging(logger) self.assertRaises(ValidationException, client.merchant("1234").payments().create, request) self.assertEqual(test_path, self.request_path, 'Request has arrived at the wrong path') self.assertLogsRequestAndResponse( logger, "createPayment_failure_invalidCardNumber")
def test_logging_error_only(self): """Test that an error can be logged separately by enabling log between request and response""" test_path = "/v2/1/services/testconnection" # relative url through which the request should be sent logger = TestLogger() response_body = read_resource("notFound.html") handler = self.create_handler(response_code=404, body=response_body, additional_headers=(("Content-Type", "text/html"),)) def enable_logging_late_response(*args, **kwargs): # handler that enables the log of the client self.client.enable_logging(logger) # and waits for a timeout before responding time.sleep(0.1) handler(*args, **kwargs) with create_server_listening(enable_logging_late_response) as address: # start server to listen to request with create_client(address, connect_timeout=0.500, socket_timeout=0.050) as client: self.client = client with self.assertRaises(CommunicationException): client.merchant("1").services().test_connection() self.assertEqual(test_path, self.request_path, 'Request has arrived at the wrong path') self.assertEqual(1, len(logger.entries)) # check that the response message exists in the logs and there are no errors error_entry = logger.entries[0] self.assertIsNotNone(error_entry[0]) self.assertIsNotNone(error_entry[1]) # check that the error is formatted correctly self.assertError(error_entry[0]) self.assertIsInstance(error_entry[1], Timeout, "logger should have logged a timeout error, logged {} instead".format(error_entry[1]))
def test_idempotence_second_request(self): """ Test that the client can successfully handle a response indicating a request has been sent prior """ response_body = read_resource("idempotence_success.json") idempotence_key = str(uuid.uuid4()) idempotence_timestamp = str(int(time.time() * 1000)) call_context = CallContext(idempotence_key) request = create_payment_request() test_path = "/v2/1/payments" # relative url through which the request should be sent additional_headers \ = (("Content-Type", "application/json"), ("Location", "http://localhost/v2/1/payments/1_1"), ("X-GCS-Idempotence-Request-Timestamp", idempotence_timestamp)) handler = self.create_handler(response_code=201, body=response_body, additional_headers=additional_headers) with create_server_listening(handler) as address: with create_client(address) as client: response = client.merchant("1").payments().create_payment(request, call_context) self.assertIsNotNone(response) self.assertIsNotNone(response.payment) self.assertIsNotNone(response.payment.id) self.assertEqual(test_path, self.request_path, 'Request has arrived at the wrong path') self.assertEqual(idempotence_key, self.idempotence_header, "Wrong idempotence key is sent in the request") self.assertEqual(idempotence_key, call_context.idempotence_key) self.assertEqual(int(idempotence_timestamp), int(call_context.idempotence_request_timestamp))
def test_logging_response_only(self): """Test that a response can be logged separately by enabling log between request and response""" test_path = "/v2/1/services/testconnection" # relative url through which the request should be sent logger = TestLogger() response_body = read_resource("testConnection.json") handler = self.create_handler(response_code=200, body=response_body, additional_headers=(("Content-Type", "application/json"),)) def enable_logging_response(*args, **kwargs): # handler that enables the log of the client self.client.enable_logging(logger) # before responding handler(*args, **kwargs) with create_server_listening(enable_logging_response) as address: # start server to listen to request with create_client(address) as client: # create client under test self.client = client response = client.merchant("1").services().test_connection() self.assertEqual("OK", response.result) self.assertEqual(test_path, self.request_path, 'Request has arrived at the wrong path') self.assertEqual(1, len(logger.entries)) # check that the response message exists in the logs and there are no errors response_entry = logger.entries[0] self.assertIsNotNone(response_entry[0]) self.assertIsNone(response_entry[1], "Error '{}' logged that should not have been thrown".format(response_entry[1])) # check that the response is formatted correctly self.assertResponse(response_entry[0], "testConnection")
def test_logging_read_timeout(self): """Test that if an exception is thrown before log due to a timeout, it is logged""" test_path = "/v2/1/services/testconnection" # relative url through which the request should be sent logger = TestLogger() response_body = read_resource("notFound.html") handler = self.create_handler(response_code=404, body=response_body, additional_headers=(("Content-Type", "text/html"),)) def delayed_response(*args, **kwargs): time.sleep(0.100) handler(*args, **kwargs) with create_server_listening(delayed_response) as address: # start server to listen to request with create_client(address, socket_timeout=0.05) as client: # create client under test client.enable_logging(logger) with self.assertRaises(CommunicationException): client.merchant("1").services().test_connection() self.assertEqual(test_path, self.request_path, 'Request has arrived at the wrong path') self.assertEqual(2, len(logger.entries)) # for request and response, check that the message exists in the logs and there is an error in the response request_entry = logger.entries[0] self.assertIsNotNone(request_entry[0]) self.assertIsNone(request_entry[1]) response_entry = logger.entries[1] self.assertIsNotNone(response_entry[0]) self.assertIsNotNone(response_entry[1]) # for request and error, check that their output is as predicted and that they match each other self.assertRequestAndError(request_entry[0], response_entry[0], "testConnection") self.assertIsInstance(response_entry[1], Timeout, "logger should have logged a timeout error")
def test_idempotence_duplicate_request(self): """Test a request where a request arrived twice""" response_body = read_resource("idempotence_duplicate_failure.json") idempotence_key = str(uuid.uuid4()) idempotence_timestamp = str(int(time.time() * 1000)) call_context = CallContext(idempotence_key) request = create_payment_request() test_path = "/v2/1/payments" # relative url through which the request should be sent additional_headers = (("Content-Type", "application/json"), ("X-GCS-Idempotence-Request-Timestamp", idempotence_timestamp)) handler = self.create_handler(response_code=409, body=response_body, additional_headers=additional_headers) with create_server_listening(handler) as address: with create_client(address) as client: with self.assertRaises(IdempotenceException) as exc: client.merchant("1").payments().create_payment(request, call_context) self.assertEqual(409, exc.exception.status_code) self.assertEqual(response_body, exc.exception.response_body) self.assertEqual(idempotence_key, exc.exception.idempotence_key) self.assertEqual(idempotence_key, self.idempotence_header, "Wrong idempotence key is sent in the request") self.assertEqual(idempotence_key, call_context.idempotence_key) self.assertEqual(test_path, self.request_path, 'Request has arrived at the wrong path') self.assertEqual(int(idempotence_timestamp), int(call_context.idempotence_request_timestamp))
def test_create_payment_unicode(self): """Tests if the body is encoded correctly""" test_path = "/v1/1234/payments" # relative url through which the request should be sent logger = TestLogger() request = create_payment_request() response_body = read_resource("createPayment.unicode.json") additional_headers = (("Content-Type", "application/json"), ( "Location", "http://localhost/v1/1234/payments/000000123410000595980000100001") ) handler = self.create_handler(response_code=201, body=response_body, additional_headers=additional_headers) with create_server_listening( handler) as address: # start server to listen to request with create_client(address) as client: # create client under test client.enable_logging(logger) response = client.merchant("1234").payments().create(request) self.assertIsNotNone(response) self.assertIsNotNone(response.payment) self.assertIsNotNone(response.payment.id) surname = response.payment.payment_output.redirect_payment_method_specific_output.\ payment_product840_specific_output.customer_account.surname self.assertEqual(surname, u"Schr\xf6der") self.assertEqual( test_path, self.request_path, 'Request has arrived at "{1}" while it should have been delivered to "{0}"' .format(test_path, self.request_path)) self.assertLogsRequestAndResponse(logger, "createPayment_unicode")
def test_logging_delete(self): """Test that a POST service without body and a void response can connect to a server and is logged appropriately """ test_path = "/v2/1/tokens/5678" # relative url through which the request should be sent logger = TestLogger() handler = self.create_handler(response_code=204) with create_server_listening(handler) as address: # start server to listen to request with create_client(address) as client: # create client under test client.enable_logging(logger) client.merchant("1").tokens().delete_token("5678", None) self.assertEqual(test_path, self.request_path, 'Request has arrived at the wrong path') self.assertLogsRequestAndResponse(logger, "deleteToken")
def test_logging_unknown_server_error(self): """Test that a GET service that results in an error is logged appropriately""" test_path = "/v2/1/services/testconnection" # relative url through which the request should be sent logger = TestLogger() response_body = read_resource("unknownServerError.json") handler = self.create_handler(response_code=500, body=response_body, additional_headers=(('Content-type', 'application/json'),)) with create_server_listening(handler) as address: # start server to listen to request with create_client(address) as client: # create client under test client.enable_logging(logger) with self.assertRaises(PaymentPlatformException): client.merchant("1").services().test_connection() self.assertEqual(test_path, self.request_path, 'Request has arrived at the wrong path') self.assertLogsRequestAndResponse(logger, "testConnection", "unknownServerError")
def test_logging_non_json(self): """Test that a GET service that results in a not found error is logged appropriately""" test_path = "/v2/1/services/testconnection" # relative url through which the request should be sent logger = TestLogger() response_body = read_resource("notFound.html") handler = self.create_handler(response_code=404, body=response_body, additional_headers=(("Content-Type", "text/html"),)) with create_server_listening(handler) as address: # start server to listen to request with create_client(address, connect_timeout=0.500, socket_timeout=0.050) as client: client.enable_logging(logger) with self.assertRaises(NotFoundException): client.merchant("1").services().test_connection() self.assertEqual(test_path, self.request_path, 'Request has arrived at the wrong path') self.assertLogsRequestAndResponse(logger, "testConnection", "notFound")
def test_idempotence_first_failure(self): """Test a request where a request is rejected without prior requests""" response_body = read_resource("idempotence_rejected.json") idempotence_key = str(uuid.uuid4()) call_context = CallContext(idempotence_key) request = create_payment_request() test_path = "/v2/1/payments" # relative url through which the request should be sent handler = self.create_handler(response_code=402, body=response_body, additional_headers=(("Content-Type", "application/json"),)) with create_server_listening(handler) as address: with create_client(address) as client: with self.assertRaises(DeclinedPaymentException) as exc: client.merchant("1").payments().create_payment(request, call_context) self.assertEqual(402, exc.exception.status_code) self.assertEqual(response_body, exc.exception.response_body) self.assertEqual(test_path, self.request_path, 'Request has arrived at the wrong path') self.assertEqual(idempotence_key, self.idempotence_header, "Wrong idempotence key is sent in the request") self.assertEqual(idempotence_key, call_context.idempotence_key) self.assertIsNone(call_context.idempotence_request_timestamp)
def test_logging_get(self): """Test that a GET service with parameters can connect to a server and is logged appropriately""" test_path = "/v2/1/products/1" # relative url through which the request should be sent logger = TestLogger() query_params = GetPaymentProductParams() query_params.amount = 1000 query_params.country_code = "BE" query_params.currency_code = "EUR" response_body = read_resource("getPaymentProduct.json") handler = self.create_handler(body=response_body, additional_headers=(('Content-type', 'application/json'),)) with create_server_listening(handler) as address: # start server to listen to request with create_client(address) as client: # create client under test client.enable_logging(logger) response = client.merchant("1").products().get_payment_product(1, query_params) self.assertIsNotNone(response) self.assertIsNotNone(response.id) self.assertEqual(test_path, self.request_path.split("?")[0], 'Request has arrived at {} instead of {}'.format(self.request_path.split("?")[0], test_path)) self.assertLogsRequestAndResponse(logger, "getPaymentProduct")
def test_idempotence_first_request(self): """Test a request with idempotence key where the first request is successful""" response_body = read_resource("idempotence_success.json") idempotence_key = str(uuid.uuid4()) call_context = CallContext(idempotence_key) request = create_payment_request() test_path = "/v1/20000/payments" # relative url through which the request should be sent additional_headers \ = (("Content-Type", "application/json"), ("Location", "http://localhost/v1/20000/payments/000002000020142549460000100001")) handler = self.create_handler(response_code=201, body=response_body, additional_headers=additional_headers) with create_server_listening(handler) as address: with create_client(address) as client: response = client.merchant("20000").payments().create(request, call_context) self.assertIsNotNone(response) self.assertIsNotNone(response.payment) self.assertIsNotNone(response.payment.id) self.assertEqual(test_path, self.request_path, 'Request has arrived at the wrong path') self.assertEqual(idempotence_key, self.idempotence_header, "Wrong idempotence key is sent in the request") self.assertEqual(idempotence_key, call_context.idempotence_key)