From 616b1e6597fa5c13584f2371665f13afb03e1383 Mon Sep 17 00:00:00 2001 From: Kevin Hellemun Date: Tue, 1 Aug 2017 17:24:07 +0200 Subject: [PATCH] Add unittests --- .gitignore | 5 +- .idea/inspectionProfiles/Project_Default.xml | 42 ++++++ tests/api_context_handler.py | 50 +++++++ tests/assets/bunq_App_Icon_Square@4x.png | Bin 0 -> 9852 bytes tests/assets/config.example.json | 23 +++ tests/config.py | 134 ++++++++++++++++++ tests/model/__init__.py | 0 tests/model/generated/__init__.py | 0 .../model/generated/test_attachment_public.py | 58 ++++++++ tests/model/generated/test_avatar.py | 64 +++++++++ tests/model/generated/test_card_debit.py | 84 +++++++++++ .../generated/test_draft_share_invite_bank.py | 64 +++++++++ .../generated/test_monetary_account_bank.py | 52 +++++++ tests/model/generated/test_payment.py | 90 ++++++++++++ tests/model/generated/test_request_inquiry.py | 76 ++++++++++ tests/model/generated/test_session.py | 39 +++++ .../model/generated/test_tab_usage_single.py | 79 +++++++++++ 17 files changed, 859 insertions(+), 1 deletion(-) create mode 100644 .idea/inspectionProfiles/Project_Default.xml create mode 100644 tests/api_context_handler.py create mode 100644 tests/assets/bunq_App_Icon_Square@4x.png create mode 100644 tests/assets/config.example.json create mode 100644 tests/config.py create mode 100644 tests/model/__init__.py create mode 100644 tests/model/generated/__init__.py create mode 100644 tests/model/generated/test_attachment_public.py create mode 100644 tests/model/generated/test_avatar.py create mode 100644 tests/model/generated/test_card_debit.py create mode 100644 tests/model/generated/test_draft_share_invite_bank.py create mode 100644 tests/model/generated/test_monetary_account_bank.py create mode 100644 tests/model/generated/test_payment.py create mode 100644 tests/model/generated/test_request_inquiry.py create mode 100644 tests/model/generated/test_session.py create mode 100644 tests/model/generated/test_tab_usage_single.py diff --git a/.gitignore b/.gitignore index d5b09a8..4576e8e 100644 --- a/.gitignore +++ b/.gitignore @@ -86,4 +86,7 @@ htmlcov/ # bunq specific bunq.conf -**/tmp/ \ No newline at end of file +bunq-test.conf +**/tmp +config.json +tests/connectQr.png diff --git a/.idea/inspectionProfiles/Project_Default.xml b/.idea/inspectionProfiles/Project_Default.xml new file mode 100644 index 0000000..d1600d5 --- /dev/null +++ b/.idea/inspectionProfiles/Project_Default.xml @@ -0,0 +1,42 @@ + + + + \ No newline at end of file diff --git a/tests/api_context_handler.py b/tests/api_context_handler.py new file mode 100644 index 0000000..8c38058 --- /dev/null +++ b/tests/api_context_handler.py @@ -0,0 +1,50 @@ +from tests.config import Config +from bunq.sdk.context import ApiContext +from bunq.sdk.context import ApiEnvironmentType +from bunq.sdk.model.generated import endpoint +from bunq.sdk.exception import ApiException + + +class ApiContextHandler: + # Config values + _API_KEY = Config.get_api_key() + _BUNQ_CONFIG_FILE = "bunq-test.conf" + _DEVICE_DESCRIPTION = 'Python test device' + + @classmethod + def get_api_context(cls): + """ + Calls IsSessionActive to check if the session token is still active + and returns the ApiContext. + + :rtype: ApiContext + """ + + if cls._is_session_active(): + return ApiContext.restore(cls._BUNQ_CONFIG_FILE) + else: + api_context = ApiContext(ApiEnvironmentType.SANDBOX, cls._API_KEY, + cls._DEVICE_DESCRIPTION, []) + api_context.save(cls._BUNQ_CONFIG_FILE) + + return api_context + + @classmethod + def _is_session_active(cls): + """ + Catches ApiExceptoin if the session is inactive. + Catches BunqEception if the conf file does not exist. + + :rtype: bool + :return: True If exception is not called, otherwise False. + + """ + try: + api_context = ApiContext.restore(cls._BUNQ_CONFIG_FILE) + endpoint.User.list(api_context) + + return True + except ApiException: + return False + except FileNotFoundError: + return False diff --git a/tests/assets/bunq_App_Icon_Square@4x.png b/tests/assets/bunq_App_Icon_Square@4x.png new file mode 100644 index 0000000000000000000000000000000000000000..1eebc9a741227cc495c3f516ecaf6b62c8895ed2 GIT binary patch literal 9852 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 W_jirN)u|CoG@$NdlOd~gl` literal 0 HcmV?d00001 diff --git a/tests/assets/config.example.json b/tests/assets/config.example.json new file mode 100644 index 0000000..648dda0 --- /dev/null +++ b/tests/assets/config.example.json @@ -0,0 +1,23 @@ +{ + "API_KEY": "", + "USER_ID": "xxxx", + "MA_ID": "xxxx", + "MA_ID2": "xxxx", + "ipAddress": "", + "AttachmentPublicTest":{ + "CONTENT_TYPE": "image/png", + "DESCRIPTION": "TEST PNG PHP", + "PATH_IN": "/bunq_App_Icon_Square@4x.png" + }, + "TabUsageSingleTest": { + "CASH_REGISTER_ID": "xxx" + }, + "CounterPartySelf": { + "Alias": "", + "Type": "EMAIL" + }, + "CounterPartyOther": { + "Alias": "", + "Type": "EMAIL" + } +} diff --git a/tests/config.py b/tests/config.py new file mode 100644 index 0000000..86d684f --- /dev/null +++ b/tests/config.py @@ -0,0 +1,134 @@ +import json +import os + +from bunq.sdk.model.generated.object_ import Pointer + + +class Config: + _FIELD_IP_ADDRESS_ALLOWED = "ipAddress" + _FIELD_COUNTER_PARTY_OTHER = "CounterPartyOther" + _FIELD_COUNTER_PARTY_SELF = "CounterPartySelf" + _FIELD_TYPE = "Type" + _FIELD_ALIAS = "Alias" + _FIELD_TAB_USAGE = "TabUsageSingleTest" + _FIELD_CASH_REGISTER_ID = "CASH_REGISTER_ID" + _FIELD_MONETARY_ACCOUNT_ID_1 = "MA_ID" + _FIELD_MONETARY_ACCOUNT_ID_2 = "MA_ID2" + _FIELD_USER_ID = "USER_ID" + _FIELD_API_KEY = "API_KEY" + _FIELD_ATTACHMENT_PUBLIC = "AttachmentPublicTest" + _FIELD_ATTACHMENT_PATH_IN = "PATH_IN" + _FIELD_ATTACHMENT_DESCRIPTION = "DESCRIPTION" + _FIELD_ATTACHMENT_CONTENT_TYPE = "CONTENT_TYPE" + + @classmethod + def get_attachment_content_type(cls): + """ + :rtype: str + """ + + return cls._get_config_file()[cls._FIELD_ATTACHMENT_PUBLIC][ + cls._FIELD_ATTACHMENT_CONTENT_TYPE] + + @classmethod + def get_attachment_description(cls): + """ + :rtype: str + """ + + return cls._get_config_file()[cls._FIELD_ATTACHMENT_PUBLIC][ + cls._FIELD_ATTACHMENT_DESCRIPTION] + + @classmethod + def get_attachment_path_in(cls): + """ + :rtype: str + """ + + return cls._get_config_file()[cls._FIELD_ATTACHMENT_PUBLIC][ + cls._FIELD_ATTACHMENT_PATH_IN] + + @classmethod + def get_api_key(cls): + """ + :rtype: str + """ + + return cls._get_config_file()[cls._FIELD_API_KEY] + + @classmethod + def get_user_id(cls): + """ + :rtype: int + """ + + return int(cls._get_config_file()[cls._FIELD_USER_ID]) + + @classmethod + def get_monetary_account_id_2(cls): + """ + :rtype: int + """ + + return int(cls._get_config_file()[cls._FIELD_MONETARY_ACCOUNT_ID_2]) + + @classmethod + def get_monetary_account_id_1(cls): + """ + :rtype: int + """ + + return int(cls._get_config_file()[cls._FIELD_MONETARY_ACCOUNT_ID_1]) + + @classmethod + def get_cash_register_id(cls): + """ + :rtype str + """ + + return cls._get_config_file()[cls._FIELD_TAB_USAGE][ + cls._FIELD_CASH_REGISTER_ID] + + @classmethod + def get_pointer_counter_party_self(cls): + """ + :rtype: Pointer + """ + + type_ = cls._get_config_file()[cls._FIELD_COUNTER_PARTY_SELF][ + cls._FIELD_TYPE] + alias = cls._get_config_file()[cls._FIELD_COUNTER_PARTY_SELF][ + cls._FIELD_ALIAS] + + return Pointer(type_, alias) + + @classmethod + def get_pointer_counter_party_other(cls): + """ + :rtype: Pointer + """ + + type_ = cls._get_config_file()[cls._FIELD_COUNTER_PARTY_OTHER][ + cls._FIELD_TYPE] + alias = cls._get_config_file()[cls._FIELD_COUNTER_PARTY_OTHER][ + cls._FIELD_ALIAS] + + return Pointer(type_, alias) + + @classmethod + def get_ip_address(cls): + """ + :rtype: str + """ + + return cls._get_config_file()[cls._FIELD_IP_ADDRESS_ALLOWED] + + @classmethod + def _get_config_file(cls): + """ + :rtype: json.load + """ + + file_path = os.path.dirname(os.path.realpath(__file__)) + with open(file_path + "/assets/config.json", "r") as f: + return json.load(f) diff --git a/tests/model/__init__.py b/tests/model/__init__.py new file mode 100644 index 0000000..e69de29 diff --git a/tests/model/generated/__init__.py b/tests/model/generated/__init__.py new file mode 100644 index 0000000..e69de29 diff --git a/tests/model/generated/test_attachment_public.py b/tests/model/generated/test_attachment_public.py new file mode 100644 index 0000000..f5e414d --- /dev/null +++ b/tests/model/generated/test_attachment_public.py @@ -0,0 +1,58 @@ +import unittest + +from tests.api_context_handler import ApiContextHandler +from tests.config import Config +from bunq.sdk.model.generated.endpoint import AttachmentPublic +from bunq.sdk.model.generated.endpoint import AttachmentPublicContent +from bunq.sdk.client import ApiClient + + +class TestAttachmentPublic(unittest.TestCase): + """ + Tests: + AttachmentPublic + AttachmentPublicContent + """ + + @classmethod + def setUpClass(cls): + # config values + cls._PATH_TO_ATTACHMENT = '/Users/khellemun/bunq/sdk_python/tests/' \ + 'assets' + cls._READ_BYTES = "rb" + cls._CONTENT_TYPE = Config.get_attachment_content_type() + cls._ATTACHMENT_DESCRIPTION = Config.get_attachment_description() + cls._ATTACHMENT_PATH_IN = Config.get_attachment_path_in() + cls._API_CONTEXT = ApiContextHandler.get_api_context() + + def test_file_upload_and_retrieval(self): + """ + Tests uploading an attachment, retrieves it and compare them to see + if the uploaded attachment is indeed the attachment we are getting + back. + """ + + custom_headers = { + ApiClient.HEADER_CONTENT_TYPE: self._CONTENT_TYPE, + ApiClient.HEADER_ATTACHMENT_DESCRIPTION: + self._ATTACHMENT_DESCRIPTION, + } + + attachment_uuid = AttachmentPublic.create(self._API_CONTEXT, + self.attachment_contents, + custom_headers) + + contents_from_response = AttachmentPublicContent.list(self._API_CONTEXT, + attachment_uuid) + + self.assertEqual(self.attachment_contents, contents_from_response) + + @property + def attachment_contents(self): + """ + :rtype: bytes + """ + + with open(self._PATH_TO_ATTACHMENT + self._ATTACHMENT_PATH_IN, + self._READ_BYTES) as f: + return f.read() diff --git a/tests/model/generated/test_avatar.py b/tests/model/generated/test_avatar.py new file mode 100644 index 0000000..dd8508a --- /dev/null +++ b/tests/model/generated/test_avatar.py @@ -0,0 +1,64 @@ +import unittest + +from bunq.sdk.client import ApiClient +from bunq.sdk.model.generated.endpoint import Avatar +from bunq.sdk.model.generated.endpoint import AttachmentPublic +from bunq.sdk.model.generated.endpoint import AttachmentPublicContent +from tests.api_context_handler import ApiContextHandler +from tests.config import Config + + +class AvatarTest(unittest.TestCase): + """ + Tests: + Avatar + AttachmentPublic + AttachmentPublicContent + """ + + @classmethod + def setUpClass(cls): + cls._FIRST_INDEX = 0 + cls._PATH_TO_ATTACHMENT = '/Users/khellemun/bunq/sdk_python/tests' \ + '/assets' + cls._READ_FILE_BYTES = 'rb' + cls._CONTENT_TYPE = Config.get_attachment_content_type() + cls._ATTACHMENT_DESCRIPTION = Config.get_attachment_description() + cls._ATTACHMENT_PATH_IN = Config.get_attachment_path_in() + cls._API_CONTEXT = ApiContextHandler.get_api_context() + + def test_avatar_creation(self): + """ + Tests the creation of an avatar by uploading a picture via + AttachmentPublic and setting it as avatar via the uuid + """ + + custom_header = { + ApiClient.HEADER_ATTACHMENT_DESCRIPTION: + self._ATTACHMENT_DESCRIPTION, + ApiClient.HEADER_CONTENT_TYPE: self._CONTENT_TYPE + } + attachment_public_uuid = AttachmentPublic \ + .create(self._API_CONTEXT, self.attachment_contents, custom_header) + + avatar_map = { + Avatar.FIELD_ATTACHMENT_PUBLIC_UUID: attachment_public_uuid + } + avatar_uuid = Avatar.create(self._API_CONTEXT, avatar_map) + attachment_uuid_after = Avatar.get(self._API_CONTEXT, avatar_uuid) \ + .image[self._FIRST_INDEX].attachment_public_uuid + + file_contents_received = AttachmentPublicContent.list( + self._API_CONTEXT, attachment_uuid_after + ) + self.assertEqual(self.attachment_contents, file_contents_received) + + @property + def attachment_contents(self): + """ + :rtype: bytes + """ + + with open(self._PATH_TO_ATTACHMENT + self._ATTACHMENT_PATH_IN, + self._READ_FILE_BYTES) as f: + return f.read() diff --git a/tests/model/generated/test_card_debit.py b/tests/model/generated/test_card_debit.py new file mode 100644 index 0000000..8e329a3 --- /dev/null +++ b/tests/model/generated/test_card_debit.py @@ -0,0 +1,84 @@ +import random +import string +import unittest + +from bunq.sdk.model.generated.endpoint import User +from bunq.sdk.model.generated.endpoint import CardName +from bunq.sdk.model.generated.endpoint import Card +from bunq.sdk.model.generated.endpoint import CardDebit +from bunq.sdk.model.generated.object_ import Pointer +from tests.api_context_handler import ApiContextHandler +from tests.config import Config + + +class TestCardDebit(unittest.TestCase): + """ + Tests: + Card + CardDebit + CardName + """ + + @classmethod + def setUpClass(cls): + cls._CARD_PIN_CODE = '4045' + cls._FIRST_INDEX = 0 + cls._SECOND_LINE_LENGTH_MAXIMUM = 20 + cls._EMPTY_STRING = '' + cls._USER_ID = Config.get_user_id() + cls._API_CONTEXT = ApiContextHandler.get_api_context() + + def test_order_debit_card(self): + """ + Tests ordering a new card and checks if the fields we have entered + are indeed correct by retrieving the card from the card endpoint and + checks this date against the data we have submitted + """ + + second_line = self.second_line_random + + card_debit_map = { + CardDebit.FIELD_NAME_ON_CARD: self.card_name_allowed, + CardDebit.FIELD_ALIAS: self.alias_first, + CardDebit.FIELD_PIN_CODE: self._CARD_PIN_CODE, + CardDebit.FIELD_SECOND_LINE: second_line + } + card_debit = CardDebit.create(self._API_CONTEXT, card_debit_map, + self._USER_ID) + card = Card.get(self._API_CONTEXT, self._USER_ID, card_debit.id_) + + self.assertEqual(self.card_name_allowed, card.name_on_card) + self.assertEqual(second_line, card.second_line) + self.assertEqual(card_debit.created, card.created) + + @property + def alias_first(self): + """ + :rtype: Pointer + """ + + return User.list(self._API_CONTEXT)[self._FIRST_INDEX].UserCompany \ + .alias[self._FIRST_INDEX] + + @property + def card_name_allowed(self): + """ + :rtype: str + """ + + return CardName.list(self._API_CONTEXT, self._USER_ID)[ + self._FIRST_INDEX].possible_card_name_array[self._FIRST_INDEX] + + @property + def second_line_random(self): + """ + :rtype: str + """ + + second_line_characters = [] + + for _ in range(self._SECOND_LINE_LENGTH_MAXIMUM): + next_char = random.choice(string.ascii_uppercase) + second_line_characters.append(next_char) + + return self._EMPTY_STRING.join(second_line_characters) diff --git a/tests/model/generated/test_draft_share_invite_bank.py b/tests/model/generated/test_draft_share_invite_bank.py new file mode 100644 index 0000000..8574fb0 --- /dev/null +++ b/tests/model/generated/test_draft_share_invite_bank.py @@ -0,0 +1,64 @@ +import unittest +from datetime import datetime +from datetime import timedelta + +from bunq.sdk.model.generated.object_ import ShareDetailReadOnly +from bunq.sdk.model.generated.object_ import ShareDetail +from bunq.sdk.model.generated.object_ import DraftShareInviteBankEntry +from bunq.sdk.model.generated.endpoint import DraftShareInviteBank +from bunq.sdk.model.generated.endpoint import DraftShareInviteBankQrCodeContent +from tests.api_context_handler import ApiContextHandler +from tests.config import Config + + +class TestDraftShareInvite(unittest.TestCase): + """ + Tests: + DraftShareInviteBankEntry + DraftShareInviteBankQrCodeContent + """ + + @classmethod + def setUpClass(cls): + cls._OUT_PUT_FILE_PATH = 'connectQr.png' + cls._WRITE_BYTES = 'wb' + cls._EXPIRATION_ADDED_TIME = 1 + cls._USER_ID = Config.get_user_id() + cls._API_CONTEXT = ApiContextHandler.get_api_context() + + def test_draft_share_invite_bank(self): + """ + Tests the creation of a connect and retrieves the QR code bound to + this connect. + + This test has no assertion as of its testing to see if the code runs + without errors + """ + + read_only = ShareDetailReadOnly(True, True, True) + share_detail = ShareDetail() + share_detail.read_only = read_only + share_settings = DraftShareInviteBankEntry(share_detail) + draft_map = { + DraftShareInviteBank.FIELD_DRAFT_SHARE_SETTINGS: share_settings, + DraftShareInviteBank.FIELD_EXPIRATION: self.expiration_date + } + draft_id = DraftShareInviteBank.create(self._API_CONTEXT, draft_map, + self._USER_ID) + + connect_qr = DraftShareInviteBankQrCodeContent.list(self._API_CONTEXT, + self._USER_ID, + draft_id,) + + with open(self._OUT_PUT_FILE_PATH, self._WRITE_BYTES) as f: + f.write(connect_qr) + + @property + def expiration_date(self): + """ + :rtype: str + """ + + date = datetime.utcnow() + timedelta(hours=self._EXPIRATION_ADDED_TIME) + + return date.isoformat() diff --git a/tests/model/generated/test_monetary_account_bank.py b/tests/model/generated/test_monetary_account_bank.py new file mode 100644 index 0000000..6711397 --- /dev/null +++ b/tests/model/generated/test_monetary_account_bank.py @@ -0,0 +1,52 @@ +import unittest +from secrets import token_hex + +from bunq.sdk.model.generated.endpoint import MonetaryAccountBank +from tests.api_context_handler import ApiContextHandler +from tests.config import Config + + +class TestMonetaryAccount(unittest.TestCase): + """ + Tests: + MonetaryAccountBank + """ + + @classmethod + def setUpClass(cls): + cls._FIELD_STATUS = 'CANCELLED' + cls._FIELD_SUB_STATUS = 'REDEMPTION_VOLUNTARY' + cls._FIELD_REASON = 'OTHER' + cls._FIELD_REASON_DESCRIPTION = 'Because this is a test' + cls._FIELD_CURRENCY = 'EUR' + cls._MONETARY_ACCOUNT_PREFIX = 'Python_test' + cls._USER_ID = Config.get_user_id() + cls._API_CONTEXT = ApiContextHandler.get_api_context() + + def test_create_new_monetary_account(self): + """ + Tests the creation of a new monetary account. This account will be + deleted after test exited with code 0. + + This test has no assertion as of its testing to see if the code runs + without errors + """ + + create_map = { + MonetaryAccountBank.FIELD_CURRENCY: self._FIELD_CURRENCY, + MonetaryAccountBank.FIELD_DESCRIPTION: + self._MONETARY_ACCOUNT_PREFIX + token_hex() + } + monetary_account_id = MonetaryAccountBank.create(self._API_CONTEXT, + create_map, + self._USER_ID) + + update_map = { + MonetaryAccountBank.FIELD_STATUS: self._FIELD_STATUS, + MonetaryAccountBank.FIELD_SUB_STATUS: self._FIELD_SUB_STATUS, + MonetaryAccountBank.FIELD_REASON: self._FIELD_REASON, + MonetaryAccountBank.FIELD_REASON_DESCRIPTION: + self._FIELD_REASON_DESCRIPTION, + } + MonetaryAccountBank.update(self._API_CONTEXT, update_map, self._USER_ID, + monetary_account_id) diff --git a/tests/model/generated/test_payment.py b/tests/model/generated/test_payment.py new file mode 100644 index 0000000..8702bf7 --- /dev/null +++ b/tests/model/generated/test_payment.py @@ -0,0 +1,90 @@ +import unittest + +from bunq.sdk.model.generated.endpoint import Payment +from bunq.sdk.model.generated.endpoint import PaymentChat +from bunq.sdk.model.generated.endpoint import ChatMessageText +from bunq.sdk.model.generated.object_ import Amount +from tests.api_context_handler import ApiContextHandler +from tests.config import Config + + +class TestPayment(unittest.TestCase): + """ + Tests: + Payment + PaymentChat + ChatMessageText + """ + + @classmethod + def setUpClass(cls): + cls._PAYMENT_AMOUNT_IN_EUR = '0.01' + cls._PAYMENT_CURRENCY = 'EUR' + cls._FIELD_DESCRIPTION = 'Python unit test' + cls._PAYMENT_CHAT_TEXT_MESSAGE = 'send from python test' + cls._USER_ID = Config.get_user_id() + cls._COUNTER_PARTY_OTHER_USER = Config.get_pointer_counter_party_other() + cls._COUNTER_PARTY_SAME_USER = Config.get_pointer_counter_party_self() + cls._MONETARY_ACCOUNT_ID = Config.get_monetary_account_id_1() + cls._API_CONTEXT = ApiContextHandler.get_api_context() + + def test_payment_to_other_user(self): + """ + Tests making a payment to another sandbox user + + This test has no assertion as of its testing to see if the code runs + without errors + """ + + request_map = { + Payment.FIELD_COUNTERPARTY_ALIAS: self._COUNTER_PARTY_OTHER_USER, + Payment.FIELD_AMOUNT: Amount(self._PAYMENT_AMOUNT_IN_EUR, + self._PAYMENT_CURRENCY), + Payment.FIELD_DESCRIPTION: self._FIELD_DESCRIPTION, + } + Payment.create(self._API_CONTEXT, request_map, self._USER_ID, + self._MONETARY_ACCOUNT_ID) + + def test_payment_to_other_account(self): + """ + Tests making a payment to another monetary account of the same user + + This test has no assertion as of its testing to see if the code runs + without errors + """ + + request_map = { + Payment.FIELD_COUNTERPARTY_ALIAS: self._COUNTER_PARTY_SAME_USER, + Payment.FIELD_DESCRIPTION: self._FIELD_DESCRIPTION, + Payment.FIELD_AMOUNT: Amount(self._PAYMENT_AMOUNT_IN_EUR, + self._PAYMENT_CURRENCY), + } + Payment.create(self._API_CONTEXT, request_map, self._USER_ID, + self._MONETARY_ACCOUNT_ID) + + def test_payment_chat(self): + """ + Tests sending a chat message in a newly created payment + + This test has no assertion as of its testing to see if the code runs + without errors + """ + + request_map = { + Payment.FIELD_COUNTERPARTY_ALIAS: self._COUNTER_PARTY_OTHER_USER, + Payment.FIELD_AMOUNT: Amount(self._PAYMENT_AMOUNT_IN_EUR, + self._PAYMENT_CURRENCY), + Payment.FIELD_DESCRIPTION: self._FIELD_DESCRIPTION, + } + payment_id = Payment.create(self._API_CONTEXT, request_map, + self._USER_ID, self._MONETARY_ACCOUNT_ID) + + chat_map = {} + chat_id = PaymentChat.create(self._API_CONTEXT, chat_map, self._USER_ID, + self._MONETARY_ACCOUNT_ID, payment_id) + + message_map = { + ChatMessageText.FIELD_TEXT: self._PAYMENT_CHAT_TEXT_MESSAGE, + } + ChatMessageText.create(self._API_CONTEXT, message_map, self._USER_ID, + chat_id) diff --git a/tests/model/generated/test_request_inquiry.py b/tests/model/generated/test_request_inquiry.py new file mode 100644 index 0000000..8f4639f --- /dev/null +++ b/tests/model/generated/test_request_inquiry.py @@ -0,0 +1,76 @@ +import unittest + +from bunq.sdk.model.generated.object_ import Amount +from tests.api_context_handler import ApiContextHandler +from tests.config import Config +from bunq.sdk.model.generated.endpoint import RequestInquiry +from bunq.sdk.model.generated.endpoint import RequestResponse + + +class TestRequestEnquiry(unittest.TestCase): + """ + Tests: + RequestInquiry + RequestResponse + """ + + @classmethod + def setUpClass(cls): + cls._REQUEST_AMOUNT_IN_EUR = '0.01' + cls._REQUEST_CURRENCY = 'EUR' + cls._FIELD_DESCRIPTION = 'Python unit test request' + cls._FIELD_STATUS = 'ACCEPTED' + cls._FIRST_INDEX = 0 + cls._USER_ID = Config.get_user_id() + cls._COUNTER_PARTY_SAME_USER = Config.get_pointer_counter_party_self() + cls._MONETARY_ACCOUNT_ID = Config.get_monetary_account_id_1() + cls._MONETARY_ACCOUNT_ID2 = Config.get_monetary_account_id_2() + cls._API_CONTEXT = ApiContextHandler.get_api_context() + + def test_sending_and_accepting_request(self): + """ + Tests sending a request from monetary account 1 to monetary account 2 and accepting this + request + + This test has no assertion as of its testing to see if the code runs + without errors + """ + + self.send_request() + + request_response_id = RequestResponse.list(self._API_CONTEXT, + self._USER_ID, + self._MONETARY_ACCOUNT_ID2)[ + self._FIRST_INDEX].id_ + + self.accept_request(request_response_id) + + def send_request(self): + """ + :rtype: None + """ + + request_map = { + RequestInquiry.FIELD_AMOUNT_INQUIRED: Amount( + self._REQUEST_AMOUNT_IN_EUR, self._REQUEST_CURRENCY + ), + RequestInquiry.FIELD_DESCRIPTION: self._FIELD_DESCRIPTION, + RequestInquiry.FIELD_COUNTERPARTY_ALIAS: + self._COUNTER_PARTY_SAME_USER, + RequestInquiry.FIELD_ALLOW_BUNQME: False, + } + + RequestInquiry.create(self._API_CONTEXT, request_map, self._USER_ID, + self._MONETARY_ACCOUNT_ID) + + def accept_request(self, response_id): + """ + :param response_id: + :rtype response_id: int + """ + + request_map = { + RequestResponse.FIELD_STATUS: self._FIELD_STATUS + } + RequestResponse.update(self._API_CONTEXT, request_map, self._USER_ID, + self._MONETARY_ACCOUNT_ID2, response_id) diff --git a/tests/model/generated/test_session.py b/tests/model/generated/test_session.py new file mode 100644 index 0000000..0bccba7 --- /dev/null +++ b/tests/model/generated/test_session.py @@ -0,0 +1,39 @@ +import unittest +import time + +from bunq.sdk.model.generated import Session +from tests.api_context_handler import ApiContextHandler +from tests.config import Config + + +class TestSession(unittest.TestCase): + """ + Tests: + Session + """ + + @classmethod + def setUpClass(cls): + cls._SESSION_ID = 0 + cls._API_KEY = Config.get_api_key() + cls._BUNQ_CONFIG_FILE = "bunq-test.conf" + cls._DEVICE_DESCRIPTION = 'Python test device' + cls._API_CONTEXT = ApiContextHandler.get_api_context() + + def test_session_delete(self): + """ + Tests the deletion and resetting of the current active session + + This test has no assertion as of its testing to see if the code runs + without errors. + + Notes + ----- + time.sleep() is needed as of you can only make 1 POST call to + Session endpoint per second. + """ + + Session.delete(self._API_CONTEXT, self._SESSION_ID) + time.sleep(2) + self._API_CONTEXT.reset_session() + self._API_CONTEXT.save(self._BUNQ_CONFIG_FILE) diff --git a/tests/model/generated/test_tab_usage_single.py b/tests/model/generated/test_tab_usage_single.py new file mode 100644 index 0000000..bba2c9b --- /dev/null +++ b/tests/model/generated/test_tab_usage_single.py @@ -0,0 +1,79 @@ +import unittest + +from bunq.sdk.model.generated.endpoint import TabUsageSingle +from bunq.sdk.model.generated.endpoint import TabItemShop +from bunq.sdk.model.generated.object_ import Amount +from tests.api_context_handler import ApiContextHandler +from tests.config import Config + + +class TestTabUsageSingle(unittest.TestCase): + """ + Tests: + TabUsageSingle + TabItemShop + """ + + @classmethod + def setUpClass(cls): + cls._USER_ID = Config.get_user_id() + cls._MONETARY_ACCOUNT_ID = Config.get_monetary_account_id_1() + cls._CASH_REGISTER_ID = Config.get_cash_register_id() + cls._AMOUNT_IN_EUR = '0.02' + cls._CURRENCY = 'EUR' + cls._STATUS_OPEN = 'OPEN' + cls._TAB_ITEM_FIELD_DESCRIPTION = 'Super expensive python tea' + cls._STATUS_WAITING = 'WAITING_FOR_PAYMENT' + cls._TAB_FIELD_DESCRIPTION = 'Pay the tab for Python test please.' + cls._API_CONTEXT = ApiContextHandler.get_api_context() + + def test_create_and_update_tab(self): + """ + Tests the creation of a Tab, adds a tab item to it and updates this tab + + This test has no assertion as of its testing to see if the code runs + without errors + """ + + create_map = { + TabUsageSingle.FIELD_STATUS: self._STATUS_OPEN, + TabUsageSingle.FIELD_DESCRIPTION: self._TAB_FIELD_DESCRIPTION, + TabUsageSingle.FIELD_AMOUNT_TOTAL: Amount(self._AMOUNT_IN_EUR, + self._CURRENCY) + } + tab_uuid = TabUsageSingle.create(self._API_CONTEXT, create_map, + self._USER_ID, + self._MONETARY_ACCOUNT_ID, + self._CASH_REGISTER_ID) + + self._add_item_to_tab(tab_uuid) + self._update_tab(tab_uuid) + + def _add_item_to_tab(self, tab_uuid): + """ + :param tab_uuid: + :type tab_uuid: str + """ + + tab_item_map = { + TabItemShop.FIELD_AMOUNT: Amount(self._AMOUNT_IN_EUR, + self._CURRENCY), + TabItemShop.FIELD_DESCRIPTION: self._TAB_ITEM_FIELD_DESCRIPTION, + } + TabItemShop.create(self._API_CONTEXT, tab_item_map, self._USER_ID, + self._MONETARY_ACCOUNT_ID, + self._CASH_REGISTER_ID, + tab_uuid) + + def _update_tab(self, tab_uuid): + """ + :param tab_uuid: + :type tab_uuid: str + """ + + update_map = { + TabUsageSingle.FIELD_STATUS: self._STATUS_WAITING, + } + TabUsageSingle.update(self._API_CONTEXT, update_map, self._USER_ID, + self._MONETARY_ACCOUNT_ID, self._CASH_REGISTER_ID, + tab_uuid)