Skip to content

Commit be51f2a

Browse files
authored
Merge branch 'develop' into fix_import_error_json_decode_bunq/sdk_python#72
2 parents fae9577 + 15237f6 commit be51f2a

13 files changed

+281
-156
lines changed

bunq/sdk/context.py

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,6 @@
77
from bunq.sdk.exception import BunqException
88
from bunq.sdk.json import converter
99
from bunq.sdk.model import core
10-
from bunq.sdk.model.device_server_internal import DeviceServerInternal
1110
from bunq.sdk.model.generated import endpoint
1211

1312

@@ -121,6 +120,8 @@ def _register_device(self, device_description,
121120
:rtype: None
122121
"""
123122

123+
from bunq.sdk.model.device_server_internal import DeviceServerInternal
124+
124125
DeviceServerInternal.create(
125126
device_description,
126127
self.api_key,
@@ -222,7 +223,7 @@ def _delete_session(self):
222223
:rtype: None
223224
"""
224225

225-
endpoint.Session.delete(self, self._SESSION_ID_DUMMY)
226+
endpoint.Session.delete(self._SESSION_ID_DUMMY)
226227

227228
@property
228229
def environment_type(self):

bunq/sdk/util.py

Lines changed: 58 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,58 @@
1+
import json
2+
import socket
3+
4+
import requests
5+
6+
from bunq.sdk.client import ApiClient
7+
from bunq.sdk.context import ApiContext, ApiEnvironmentType
8+
from bunq.sdk.exception import BunqException
9+
from bunq.sdk.model.generated import endpoint
10+
11+
__UNIQUE_REQUEST_ID = "uniqueness-is-required"
12+
__FIELD_API_KEY = "ApiKey"
13+
__INDEX_FIRST = 0
14+
__FIELD_RESPONSE = "Response"
15+
__ENDPOINT_SANDBOX_USER = "sandbox-user"
16+
17+
_ERROR_COULD_NOT_CREATE_NEW_SANDBOX_USER = "Could not create new sandbox" \
18+
" user."
19+
20+
21+
def automatic_sandbox_install():
22+
"""
23+
:rtype: ApiContext
24+
"""
25+
26+
sandbox_user = __generate_new_sandbox_user()
27+
28+
return ApiContext(
29+
ApiEnvironmentType.SANDBOX,
30+
sandbox_user.api_key,
31+
socket.gethostname()
32+
)
33+
34+
35+
def __generate_new_sandbox_user():
36+
"""
37+
:rtype: endpoint.SandboxUser
38+
"""
39+
40+
url = ApiEnvironmentType.SANDBOX.uri_base + __ENDPOINT_SANDBOX_USER
41+
42+
headers = {
43+
ApiClient.HEADER_REQUEST_ID: __UNIQUE_REQUEST_ID,
44+
ApiClient.HEADER_CACHE_CONTROL: ApiClient._CACHE_CONTROL_NONE,
45+
ApiClient.HEADER_GEOLOCATION: ApiClient._GEOLOCATION_ZERO,
46+
ApiClient.HEADER_LANGUAGE: ApiClient._LANGUAGE_EN_US,
47+
ApiClient.HEADER_REGION: ApiClient._REGION_NL_NL,
48+
}
49+
50+
response = requests.request(ApiClient._METHOD_POST, url, headers=headers)
51+
52+
if response.status_code is ApiClient._STATUS_CODE_OK:
53+
response_json = json.loads(response.text)
54+
return endpoint.SandboxUser.from_json(
55+
json.dumps(response_json[__FIELD_RESPONSE][__INDEX_FIRST][
56+
__FIELD_API_KEY]))
57+
58+
raise BunqException(_ERROR_COULD_NOT_CREATE_NEW_SANDBOX_USER)

tests/bunq_test.py

Lines changed: 146 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,24 @@
11
import os
2+
import time
23
import unittest
34

4-
from tests import config
55
from bunq.sdk import context
6+
from bunq.sdk import util
7+
from bunq.sdk.client import ApiClient
8+
from bunq.sdk.exception import BunqException
9+
from bunq.sdk.model.generated import endpoint
10+
from bunq.sdk.model.generated import object_
11+
from tests import config
612

713

814
class BunqSdkTestCase(unittest.TestCase):
15+
"""
16+
:type _second_monetary_account: endpoint.MonetaryAccountBank
17+
:type _cash_register: endpoint.CashRegister
18+
"""
19+
20+
__ERROR_COULD_NOT_DETERMINE_USER = 'Could not determine user alias.'
21+
922
# Config values
1023
_API_KEY = config.Config.get_api_key()
1124

@@ -15,33 +28,148 @@ class BunqSdkTestCase(unittest.TestCase):
1528
# Device description used for python tests
1629
_DEVICE_DESCRIPTION = 'Python test device'
1730

31+
_PATH_ATTACHMENT = 'tests/assets/'
32+
_READ_BYTES = "rb"
33+
_ATTACHMENT_PATH_IN = '[email protected]'
34+
_CONTENT_TYPE = 'image/png'
35+
_ATTACHMENT_DESCRIPTION = 'SDK python test'
36+
_FIRST_INDEX = 0
37+
38+
__SPENDING_MONEY_AMOUNT = '500'
39+
__CURRENCY_EUR = 'EUR'
40+
__POINTER_EMAIL = 'EMAIL'
41+
__SPENDING_MONEY_RECIPIENT = '[email protected]'
42+
__REQUEST_SPENDING_DESCRIPTION = 'sdk python test, thanks daddy <3'
43+
44+
__CASH_REGISTER_STATUS = 'PENDING_APPROVAL'
45+
__CASH_REGISTER_DESCRIPTION = 'python test cash register'
46+
47+
__SECOND_MONETARY_ACCOUNT_DESCRIPTION = 'test account python'
48+
49+
__EMAIL_BRAVO = '[email protected]'
50+
51+
__TIME_OUT_AUTO_ACCEPT_SPENDING_MONEY = 0.5
52+
53+
_second_monetary_account = None
54+
_cash_register = None
55+
1856
@classmethod
19-
def _get_api_context(cls):
20-
"""
21-
Calls IsSessionActive to check if the session token is still active
22-
and returns the context.ApiContext.
57+
def setUpClass(cls):
58+
context.BunqContext.load_api_context(cls._get_api_context())
59+
60+
def setUp(self):
61+
self.__set_second_monetary_account()
62+
self.__request_spending_money()
63+
time.sleep(self.__TIME_OUT_AUTO_ACCEPT_SPENDING_MONEY)
64+
context.BunqContext.user_context().refresh_user_context()
65+
66+
def __set_second_monetary_account(self):
67+
response = endpoint.MonetaryAccountBank.create(
68+
self.__CURRENCY_EUR,
69+
self.__SECOND_MONETARY_ACCOUNT_DESCRIPTION
70+
)
2371

24-
Catches ApiException if the session is inactive.
25-
Catches BunqException if the conf file does not exist.
72+
self._second_monetary_account = endpoint.MonetaryAccountBank.get(
73+
response.value
74+
).value
2675

76+
def __request_spending_money(self):
77+
endpoint.RequestInquiry.create(
78+
object_.Amount(self.__SPENDING_MONEY_AMOUNT, self.__CURRENCY_EUR),
79+
object_.Pointer(
80+
self.__POINTER_EMAIL,
81+
self.__SPENDING_MONEY_RECIPIENT
82+
),
83+
self.__REQUEST_SPENDING_DESCRIPTION,
84+
False
85+
)
86+
endpoint.RequestInquiry.create(
87+
object_.Amount(self.__SPENDING_MONEY_AMOUNT, self.__CURRENCY_EUR),
88+
object_.Pointer(
89+
self.__POINTER_EMAIL,
90+
self.__SPENDING_MONEY_RECIPIENT
91+
),
92+
self.__REQUEST_SPENDING_DESCRIPTION,
93+
False,
94+
self._second_monetary_account.id_
95+
)
96+
97+
def _get_cash_register_id(self):
98+
if self._cash_register is None:
99+
self._set_cash_register()
100+
101+
return self._cash_register.id_
102+
103+
@classmethod
104+
def _get_api_context(cls):
105+
"""
27106
:rtype: context.ApiContext
28107
"""
29108

30-
filename_bunq_config_full = (cls._get_directory_test_root() +
31-
cls._FILENAME_BUNQ_CONFIG)
109+
return util.automatic_sandbox_install()
110+
111+
def _get_pointer_bravo(self):
112+
"""
113+
:rtype: object_.Pointer
114+
"""
32115

33-
try:
34-
api_context = context.ApiContext.restore(filename_bunq_config_full)
35-
except FileNotFoundError:
36-
api_context = context.ApiContext(context.ApiEnvironmentType.SANDBOX, cls._API_KEY,
37-
cls._DEVICE_DESCRIPTION, [])
38-
else:
39-
api_context.ensure_session_active()
116+
return object_.Pointer(self.__POINTER_EMAIL, self.__EMAIL_BRAVO)
40117

41-
api_context.save(filename_bunq_config_full)
118+
def _get_alias_second_account(self):
119+
"""
120+
:rtype: object_.Pointer
121+
"""
42122

43-
return api_context
123+
return self._second_monetary_account.alias[self._FIRST_INDEX]
44124

45125
@staticmethod
46126
def _get_directory_test_root():
47127
return os.path.dirname(os.path.abspath(__file__))
128+
129+
def _set_cash_register(self):
130+
attachment_uuid = endpoint.AttachmentPublic.create(
131+
self._attachment_contents,
132+
{
133+
ApiClient.HEADER_CONTENT_TYPE: self._CONTENT_TYPE,
134+
ApiClient.HEADER_ATTACHMENT_DESCRIPTION:
135+
self._ATTACHMENT_DESCRIPTION,
136+
}
137+
)
138+
avatar_uuid = endpoint.Avatar.create(attachment_uuid.value)
139+
cash_register_id = endpoint.CashRegister.create(
140+
self.__CASH_REGISTER_DESCRIPTION,
141+
self.__CASH_REGISTER_STATUS,
142+
avatar_uuid.value
143+
)
144+
145+
self._cash_register = endpoint.CashRegister.get(cash_register_id.value)
146+
147+
@property
148+
def _attachment_contents(self):
149+
"""
150+
:rtype: bytes
151+
"""
152+
153+
with open(
154+
self._get_directory_test_root() +
155+
self._PATH_ATTACHMENT +
156+
self._ATTACHMENT_PATH_IN,
157+
self._READ_BYTES
158+
) as file:
159+
return file.read()
160+
161+
@property
162+
def alias_first(self):
163+
"""
164+
:rtype: Pointer
165+
"""
166+
167+
if context.BunqContext.user_context().is_only_user_company_set():
168+
return context.BunqContext.user_context().user_company.alias[
169+
self._FIRST_INDEX]
170+
171+
if context.BunqContext.user_context().is_only_user_person_set():
172+
return context.BunqContext.user_context().user_person.alias[
173+
self._FIRST_INDEX]
174+
175+
raise BunqException(self.__ERROR_COULD_NOT_DETERMINE_USER)

tests/http/test_api_context.py

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,7 @@ class TestApiContext(BunqSdkTestCase):
1515

1616
@classmethod
1717
def setUpClass(cls):
18+
super().setUpClass()
1819
cls._FILE_MODE_READ = ApiContext._FILE_MODE_READ
1920
cls._API_CONTEXT = cls._get_api_context()
2021
cls._TMP_FILE_PATH_FULL = (cls._get_directory_test_root() +

tests/model/generated/endpoint/test_attachment_public.py

Lines changed: 5 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,8 @@
1+
import os
2+
13
from bunq.sdk.client import ApiClient
2-
from bunq.sdk.context import BunqContext
3-
from bunq.sdk.model.generated.endpoint import AttachmentPublic
4-
from bunq.sdk.model.generated.endpoint import AttachmentPublicContent
4+
from bunq.sdk.model.generated import endpoint
55
from tests.bunq_test import BunqSdkTestCase
6-
from tests.config import Config
76

87

98
class TestAttachmentPublic(BunqSdkTestCase):
@@ -13,17 +12,6 @@ class TestAttachmentPublic(BunqSdkTestCase):
1312
AttachmentPublicContent
1413
"""
1514

16-
@classmethod
17-
def setUpClass(cls):
18-
# config values
19-
cls._PATH_ATTACHMENT = cls._get_directory_test_root() + '/assets/'
20-
cls._READ_BYTES = "rb"
21-
cls._CONTENT_TYPE = Config.get_attachment_content_type()
22-
cls._ATTACHMENT_DESCRIPTION = Config.get_attachment_description()
23-
cls._ATTACHMENT_PATH_IN = Config.get_attachment_path_in()
24-
25-
BunqContext.load_api_context(cls._get_api_context())
26-
2715
def test_file_upload_and_retrieval(self):
2816
"""
2917
Tests uploading an attachment, retrieves it and compare them to see
@@ -37,10 +25,10 @@ def test_file_upload_and_retrieval(self):
3725
self._ATTACHMENT_DESCRIPTION,
3826
}
3927

40-
attachment_uuid = AttachmentPublic.create(self.attachment_contents,
28+
attachment_uuid = endpoint.AttachmentPublic.create(self.attachment_contents,
4129
custom_headers).value
4230

43-
contents_from_response = AttachmentPublicContent.list(
31+
contents_from_response = endpoint.AttachmentPublicContent.list(
4432
attachment_uuid).value
4533

4634
self.assertEqual(self.attachment_contents, contents_from_response)

tests/model/generated/endpoint/test_avatar.py

Lines changed: 5 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,6 @@
33
from bunq.sdk.model.generated.endpoint import AttachmentPublicContent
44
from bunq.sdk.model.generated.endpoint import Avatar
55
from tests.bunq_test import BunqSdkTestCase
6-
from tests.config import Config
76

87

98
class TestAvatar(BunqSdkTestCase):
@@ -14,16 +13,6 @@ class TestAvatar(BunqSdkTestCase):
1413
AttachmentPublicContent
1514
"""
1615

17-
@classmethod
18-
def setUpClass(cls):
19-
cls._FIRST_INDEX = 0
20-
cls._PATH_ATTACHMENT = cls._get_directory_test_root() + '/assets/'
21-
cls._READ_FILE_BYTES = 'rb'
22-
cls._CONTENT_TYPE = Config.get_attachment_content_type()
23-
cls._ATTACHMENT_DESCRIPTION = Config.get_attachment_description()
24-
cls._ATTACHMENT_PATH_IN = Config.get_attachment_path_in()
25-
cls._API_CONTEXT = cls._get_api_context()
26-
2716
def test_avatar_creation(self):
2817
"""
2918
Tests the creation of an avatar by uploading a picture via
@@ -53,6 +42,8 @@ def attachment_contents(self):
5342
:rtype: bytes
5443
"""
5544

56-
with open(self._PATH_ATTACHMENT + self._ATTACHMENT_PATH_IN,
57-
self._READ_FILE_BYTES) as f:
58-
return f.read()
45+
with open(
46+
self._PATH_ATTACHMENT + self._ATTACHMENT_PATH_IN,
47+
self._READ_BYTES
48+
) as file:
49+
return file.read()

0 commit comments

Comments
 (0)