incognia-python 3.0.0__tar.gz → 3.1.0__tar.gz

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (34) hide show
  1. {incognia_python-3.0.0 → incognia_python-3.1.0}/CODEOWNERS +1 -1
  2. {incognia_python-3.0.0 → incognia_python-3.1.0}/PKG-INFO +3 -2
  3. {incognia_python-3.0.0 → incognia_python-3.1.0}/incognia/api.py +86 -10
  4. incognia_python-3.1.0/incognia/datetime_util.py +13 -0
  5. {incognia_python-3.0.0 → incognia_python-3.1.0}/incognia/models.py +17 -1
  6. {incognia_python-3.0.0 → incognia_python-3.1.0}/incognia_python.egg-info/PKG-INFO +3 -2
  7. {incognia_python-3.0.0 → incognia_python-3.1.0}/tests/test_api.py +430 -2
  8. incognia_python-3.0.0/incognia/datetime_util.py +0 -5
  9. {incognia_python-3.0.0 → incognia_python-3.1.0}/.github/dependabot.yml +0 -0
  10. {incognia_python-3.0.0 → incognia_python-3.1.0}/.github/workflows/codeql.yaml +0 -0
  11. {incognia_python-3.0.0 → incognia_python-3.1.0}/.github/workflows/continuous.yaml +0 -0
  12. {incognia_python-3.0.0 → incognia_python-3.1.0}/.gitignore +0 -0
  13. {incognia_python-3.0.0 → incognia_python-3.1.0}/LICENSE.txt +0 -0
  14. {incognia_python-3.0.0 → incognia_python-3.1.0}/MANIFEST.in +0 -0
  15. {incognia_python-3.0.0 → incognia_python-3.1.0}/README.md +0 -0
  16. {incognia_python-3.0.0 → incognia_python-3.1.0}/incognia/__init__.py +0 -0
  17. {incognia_python-3.0.0 → incognia_python-3.1.0}/incognia/base_request.py +0 -0
  18. {incognia_python-3.0.0 → incognia_python-3.1.0}/incognia/endpoints.py +0 -0
  19. {incognia_python-3.0.0 → incognia_python-3.1.0}/incognia/exceptions.py +0 -0
  20. {incognia_python-3.0.0 → incognia_python-3.1.0}/incognia/feedback_events.py +0 -0
  21. {incognia_python-3.0.0 → incognia_python-3.1.0}/incognia/json_util.py +0 -0
  22. {incognia_python-3.0.0 → incognia_python-3.1.0}/incognia/singleton.py +0 -0
  23. {incognia_python-3.0.0 → incognia_python-3.1.0}/incognia/token_manager.py +0 -0
  24. {incognia_python-3.0.0 → incognia_python-3.1.0}/incognia_python.egg-info/SOURCES.txt +0 -0
  25. {incognia_python-3.0.0 → incognia_python-3.1.0}/incognia_python.egg-info/dependency_links.txt +0 -0
  26. {incognia_python-3.0.0 → incognia_python-3.1.0}/incognia_python.egg-info/not-zip-safe +0 -0
  27. {incognia_python-3.0.0 → incognia_python-3.1.0}/incognia_python.egg-info/requires.txt +0 -0
  28. {incognia_python-3.0.0 → incognia_python-3.1.0}/incognia_python.egg-info/top_level.txt +0 -0
  29. {incognia_python-3.0.0 → incognia_python-3.1.0}/pyproject.toml +0 -0
  30. {incognia_python-3.0.0 → incognia_python-3.1.0}/requirements.txt +0 -0
  31. {incognia_python-3.0.0 → incognia_python-3.1.0}/setup.cfg +0 -0
  32. {incognia_python-3.0.0 → incognia_python-3.1.0}/tests/__init__.py +0 -0
  33. {incognia_python-3.0.0 → incognia_python-3.1.0}/tests/test_base_request.py +0 -0
  34. {incognia_python-3.0.0 → incognia_python-3.1.0}/tests/test_token_manager.py +0 -0
@@ -2,4 +2,4 @@
2
2
  # the repo. Unless a later match takes precedence,
3
3
  # @inloco/incognia-owners will be requested for
4
4
  # review when someone opens a pull request.
5
- * @inloco/incognia-owners
5
+ * @inloco/api-codeowners
@@ -1,6 +1,6 @@
1
- Metadata-Version: 2.1
1
+ Metadata-Version: 2.4
2
2
  Name: incognia-python
3
- Version: 3.0.0
3
+ Version: 3.1.0
4
4
  Summary: Python lightweight client library for Incognia APIs
5
5
  Home-page: https://github.com/inloco/incognia-python
6
6
  Author: Incognia
@@ -13,6 +13,7 @@ Classifier: Programming Language :: Python :: 3.9
13
13
  Description-Content-Type: text/markdown
14
14
  License-File: LICENSE.txt
15
15
  Requires-Dist: requests
16
+ Dynamic: license-file
16
17
 
17
18
  # Incognia API Python Client 🐍
18
19
 
@@ -1,11 +1,19 @@
1
1
  import datetime as dt
2
2
  from typing import Optional, List
3
3
 
4
- from .datetime_util import has_timezone
4
+ from .datetime_util import has_timezone, datetime_valid
5
5
  from .endpoints import Endpoints
6
6
  from .exceptions import IncogniaHTTPError, IncogniaError
7
7
  from .json_util import encode
8
- from .models import Coordinates, StructuredAddress, TransactionAddress, PaymentValue, PaymentMethod
8
+ from .models import (
9
+ Coordinates,
10
+ StructuredAddress,
11
+ TransactionAddress,
12
+ PaymentValue,
13
+ PaymentMethod,
14
+ Location,
15
+ Coupon,
16
+ )
9
17
  from .singleton import Singleton
10
18
  from .token_manager import TokenManager
11
19
  from .base_request import BaseRequest, JSON_CONTENT_HEADER
@@ -27,7 +35,9 @@ class IncogniaAPI(metaclass=Singleton):
27
35
  address_coordinates: Optional[Coordinates] = None,
28
36
  external_id: Optional[str] = None,
29
37
  policy_id: Optional[str] = None,
30
- account_id: Optional[str] = None) -> dict:
38
+ account_id: Optional[str] = None,
39
+ device_os: Optional[str] = None,
40
+ app_version: Optional[str] = None) -> dict:
31
41
  if not request_token:
32
42
  raise IncogniaError('request_token is required.')
33
43
 
@@ -41,7 +51,33 @@ class IncogniaAPI(metaclass=Singleton):
41
51
  'address_coordinates': address_coordinates,
42
52
  'external_id': external_id,
43
53
  'policy_id': policy_id,
44
- 'account_id': account_id
54
+ 'account_id': account_id,
55
+ 'device_os': device_os.lower() if device_os is not None else None,
56
+ 'app_version': app_version
57
+ }
58
+ data = encode(body)
59
+ return self.__request.post(Endpoints.SIGNUPS, headers=headers, data=data)
60
+
61
+ except IncogniaHTTPError as e:
62
+ raise IncogniaHTTPError(e) from None
63
+
64
+ def register_new_web_signup(self,
65
+ request_token: Optional[str],
66
+ policy_id: Optional[str] = None,
67
+ account_id: Optional[str] = None,
68
+ custom_properties: Optional[dict] = None,
69
+ ) -> dict:
70
+ if not request_token:
71
+ raise IncogniaError('request_token is required.')
72
+
73
+ try:
74
+ headers = self.__get_authorization_header()
75
+ headers.update(JSON_CONTENT_HEADER)
76
+ body = {
77
+ 'request_token': request_token,
78
+ 'policy_id': policy_id,
79
+ 'account_id': account_id,
80
+ 'custom_properties': custom_properties
45
81
  }
46
82
  data = encode(body)
47
83
  return self.__request.post(Endpoints.SIGNUPS, headers=headers, data=data)
@@ -94,15 +130,31 @@ class IncogniaAPI(metaclass=Singleton):
94
130
  request_token: str,
95
131
  account_id: str,
96
132
  external_id: Optional[str] = None,
133
+ location: Optional[Location] = None,
97
134
  addresses: Optional[List[TransactionAddress]] = None,
98
135
  payment_value: Optional[PaymentValue] = None,
99
136
  payment_methods: Optional[List[PaymentMethod]] = None,
100
137
  evaluate: Optional[bool] = None,
101
- policy_id: Optional[str] = None) -> dict:
138
+ policy_id: Optional[str] = None,
139
+ custom_properties: Optional[dict] = None,
140
+ coupon: Optional[Coupon] = None,
141
+ device_os: Optional[str] = None,
142
+ app_version: Optional[str] = None,
143
+ store_id: Optional[str] = None) -> dict:
102
144
  if not request_token:
103
145
  raise IncogniaError('request_token is required.')
104
146
  if not account_id:
105
147
  raise IncogniaError('account_id is required.')
148
+ if location is not None:
149
+ if location['latitude'] is None:
150
+ raise IncogniaError('location argument requires "latitude" field')
151
+ if location['longitude'] is None:
152
+ raise IncogniaError('location argument requires "longitude" field')
153
+ if (
154
+ location['collected_at'] is not None
155
+ and not datetime_valid(location['collected_at'])
156
+ ):
157
+ raise IncogniaError('location["collected_at"] must conform to ISO-8601 format')
106
158
 
107
159
  try:
108
160
  headers = self.__get_authorization_header()
@@ -113,10 +165,16 @@ class IncogniaAPI(metaclass=Singleton):
113
165
  'request_token': request_token,
114
166
  'account_id': account_id,
115
167
  'external_id': external_id,
168
+ 'location': location,
116
169
  'addresses': addresses,
117
170
  'payment_value': payment_value,
118
171
  'payment_methods': payment_methods,
119
- 'policy_id': policy_id
172
+ 'policy_id': policy_id,
173
+ 'custom_properties': custom_properties,
174
+ 'coupon': coupon,
175
+ 'device_os': device_os.lower() if device_os is not None else None,
176
+ 'app_version': app_version,
177
+ 'store_id': store_id,
120
178
  }
121
179
  data = encode(body)
122
180
  return self.__request.post(Endpoints.TRANSACTIONS, headers=headers, params=params,
@@ -128,13 +186,26 @@ class IncogniaAPI(metaclass=Singleton):
128
186
  def register_login(self,
129
187
  request_token: str,
130
188
  account_id: str,
189
+ location: Optional[Location] = None,
131
190
  external_id: Optional[str] = None,
132
191
  evaluate: Optional[bool] = None,
133
- policy_id: Optional[str] = None) -> dict:
192
+ policy_id: Optional[str] = None,
193
+ device_os: Optional[str] = None,
194
+ app_version: Optional[str] = None) -> dict:
134
195
  if not request_token:
135
196
  raise IncogniaError('request_token is required.')
136
197
  if not account_id:
137
198
  raise IncogniaError('account_id is required.')
199
+ if location is not None:
200
+ if location['latitude'] is None:
201
+ raise IncogniaError('location argument requires "latitude" field')
202
+ if location['longitude'] is None:
203
+ raise IncogniaError('location argument requires "longitude" field')
204
+ if (
205
+ location['collected_at'] is not None
206
+ and not datetime_valid(location['collected_at'])
207
+ ):
208
+ raise IncogniaError('location["collected_at"] must conform to ISO-8601 format')
138
209
 
139
210
  try:
140
211
  headers = self.__get_authorization_header()
@@ -144,8 +215,11 @@ class IncogniaAPI(metaclass=Singleton):
144
215
  'type': 'login',
145
216
  'request_token': request_token,
146
217
  'account_id': account_id,
218
+ 'location': location,
147
219
  'external_id': external_id,
148
- 'policy_id': policy_id
220
+ 'policy_id': policy_id,
221
+ 'device_os': device_os.lower() if device_os is not None else None,
222
+ 'app_version': app_version,
149
223
  }
150
224
  data = encode(body)
151
225
  return self.__request.post(Endpoints.TRANSACTIONS, headers=headers, params=params,
@@ -159,7 +233,8 @@ class IncogniaAPI(metaclass=Singleton):
159
233
  account_id: str,
160
234
  external_id: Optional[str] = None,
161
235
  evaluate: Optional[bool] = None,
162
- policy_id: Optional[str] = None) -> dict:
236
+ policy_id: Optional[str] = None,
237
+ custom_properties: Optional[dict] = None) -> dict:
163
238
  if not request_token:
164
239
  raise IncogniaError('request_token is required.')
165
240
  if not account_id:
@@ -174,7 +249,8 @@ class IncogniaAPI(metaclass=Singleton):
174
249
  'request_token': request_token,
175
250
  'account_id': account_id,
176
251
  'external_id': external_id,
177
- 'policy_id': policy_id
252
+ 'policy_id': policy_id,
253
+ 'custom_properties': custom_properties,
178
254
  }
179
255
  data = encode(body)
180
256
  return self.__request.post(Endpoints.TRANSACTIONS, headers=headers, params=params,
@@ -0,0 +1,13 @@
1
+ from datetime import datetime
2
+
3
+
4
+ def has_timezone(d: datetime) -> bool:
5
+ return d.tzinfo is not None and d.tzinfo.utcoffset(d) is not None
6
+
7
+
8
+ def datetime_valid(dt_str):
9
+ try:
10
+ datetime.fromisoformat(dt_str.replace('Z', '+00:00'))
11
+ except ValueError:
12
+ return False
13
+ return True
@@ -20,6 +20,14 @@ class StructuredAddress(TypedDict, total=False):
20
20
  postal_code: str
21
21
 
22
22
 
23
+ class Coupon (TypedDict, total=False):
24
+ type: Literal['percent_off', 'fixed_value']
25
+ value: float
26
+ max_discount: float
27
+ id: str
28
+ name: str
29
+
30
+
23
31
  class TransactionAddress(TypedDict, total=False):
24
32
  type: Literal['shipping', 'billing', 'home']
25
33
  structured_address: StructuredAddress
@@ -39,6 +47,14 @@ class CardInfo(TypedDict, total=False):
39
47
 
40
48
 
41
49
  class PaymentMethod(TypedDict, total=False):
42
- type: Literal['credit', 'debit']
50
+ type: Literal['account_balance', 'apple_pay', 'bancolombia',
51
+ 'boleto_bancario', 'cash', 'credit_card', 'debit_card',
52
+ 'google_pay', 'meal_voucher', 'nu_pay', 'paypal', 'pix']
43
53
  credit_card_info: CardInfo
44
54
  debit_card_info: CardInfo
55
+
56
+
57
+ class Location(TypedDict, total=False):
58
+ latitude: float
59
+ longitude: float
60
+ collected_at: str
@@ -1,6 +1,6 @@
1
- Metadata-Version: 2.1
1
+ Metadata-Version: 2.4
2
2
  Name: incognia-python
3
- Version: 3.0.0
3
+ Version: 3.1.0
4
4
  Summary: Python lightweight client library for Incognia APIs
5
5
  Home-page: https://github.com/inloco/incognia-python
6
6
  Author: Incognia
@@ -13,6 +13,7 @@ Classifier: Programming Language :: Python :: 3.9
13
13
  Description-Content-Type: text/markdown
14
14
  License-File: LICENSE.txt
15
15
  Requires-Dist: requests
16
+ Dynamic: license-file
16
17
 
17
18
  # Incognia API Python Client 🐍
18
19
 
@@ -20,6 +20,8 @@ class TestIncogniaAPI(TestCase):
20
20
  ACCOUNT_ID: Final[str] = 'ANY_ACCOUNT_ID'
21
21
  INVALID_ACCOUNT_ID: Final[str] = 'INVALID_ACCOUNT_ID'
22
22
  ADDRESS_LINE: Final[str] = 'ANY_ADDRESS_LINE'
23
+ DEVICE_OS: Final[str] = 'ANY_DEVICE_OS'
24
+ APP_VERSION: Final[str] = 'ANY_APP_VERSION'
23
25
  STRUCTURED_ADDRESS: Final[dict] = {
24
26
  'locale': 'ANY_LOCALE',
25
27
  'country_name': 'ANY_COUNTRY_NAME',
@@ -67,7 +69,25 @@ class TestIncogniaAPI(TestCase):
67
69
  'address_coordinates': ADDRESS_COORDINATES,
68
70
  'external_id': f'{EXTERNAL_ID}',
69
71
  'policy_id': f'{POLICY_ID}',
70
- 'account_id': f'{ACCOUNT_ID}'
72
+ 'account_id': f'{ACCOUNT_ID}',
73
+ 'device_os': f'{DEVICE_OS.lower()}',
74
+ 'app_version': f'{APP_VERSION}'
75
+ })
76
+ CUSTOM_PROPERTIES: Final[dict] = {
77
+ 'float_field': 6.092,
78
+ 'string_field': "the next generation of identity",
79
+ }
80
+ REGISTER_WEB_SIGNUP_DATA: Final[bytes] = encode({
81
+ 'request_token': f'{REQUEST_TOKEN}'
82
+ })
83
+ REGISTER_INVALID_WEB_SIGNUP_DATA: Final[bytes] = encode({
84
+ 'request_token': f'{INVALID_REQUEST_TOKEN}'
85
+ })
86
+ FULL_REGISTER_WEB_SIGNUP_DATA: Final[bytes] = encode({
87
+ 'request_token': f'{REQUEST_TOKEN}',
88
+ 'policy_id': f'{POLICY_ID}',
89
+ 'account_id': f'{ACCOUNT_ID}',
90
+ 'custom_properties': CUSTOM_PROPERTIES
71
91
  })
72
92
  OK_STATUS_CODE: Final[int] = 200
73
93
  CLIENT_ERROR_CODE: Final[int] = 400
@@ -76,6 +96,53 @@ class TestIncogniaAPI(TestCase):
76
96
  TIMESTAMP_WITHOUT_TIMEZONE: Final[dt.datetime] = dt.datetime.now()
77
97
  LOGIN_ID: Final[str] = 'ANY_LOGIN_ID'
78
98
  PAYMENT_ID: Final[str] = 'ANY_PAYMENT_ID'
99
+ STORE_ID: Final[str] = 'ANY_STORE_ID'
100
+ COUPON: Final[dict] = {
101
+ "type": "percent_off",
102
+ "value": 2.5,
103
+ "max_discount": 50.0,
104
+ "id": "COUPON_ID",
105
+ "name": "COUPON_NAME"
106
+ }
107
+ TRANSACTION_ADDRESS: Final[dict] = {
108
+ "type": "billing",
109
+ "structured_address": STRUCTURED_ADDRESS,
110
+ "address_coordinates": ADDRESS_COORDINATES
111
+ }
112
+ PAYMENT_VALUE: Final[dict] = {
113
+ 'value': 12.34,
114
+ 'currency': 'BRL'
115
+ }
116
+ CARD_INFO: Final[dict] = {
117
+ 'bin': '0000000000',
118
+ 'last_four_digits': '0000',
119
+ 'expiry_year': '2029',
120
+ 'expiry_month': '04'
121
+ }
122
+ PAYMENT_METHOD: Final[dict] = {
123
+ 'type': 'credit_card',
124
+ 'credit_card_info': CARD_INFO
125
+ }
126
+ LOCATION: Final[dict] = {
127
+ 'latitude': 0.000,
128
+ 'longitude': 89.000,
129
+ 'collected_at': TIMESTAMP.isoformat()
130
+ }
131
+ INVALID_LOCATION_EMPTY_LATITUDE: Final[dict] = {
132
+ 'latitude': None,
133
+ 'longitude': 13.123,
134
+ 'collected_at': TIMESTAMP.isoformat()
135
+ }
136
+ INVALID_LOCATION_EMPTY_LONGITUDE: Final[dict] = {
137
+ 'latitude': 0.000,
138
+ 'longitude': None,
139
+ 'collected_at': TIMESTAMP.isoformat()
140
+ }
141
+ INVALID_LOCATION_WRONG_TIMESTAMP: Final[dict] = {
142
+ 'latitude': 0.000,
143
+ 'longitude': 13.123,
144
+ 'collected_at': "12:04 14/10/2024"
145
+ }
79
146
  REGISTER_VALID_FEEDBACK_DATA: Final[bytes] = encode({
80
147
  'event': f'{VALID_EVENT_FEEDBACK_TYPE}'
81
148
  })
@@ -97,6 +164,29 @@ class TestIncogniaAPI(TestCase):
97
164
  'account_id': f'{ACCOUNT_ID}',
98
165
  'policy_id': f'{POLICY_ID}',
99
166
  })
167
+ REGISTER_VALID_PAYMENT_DATA_ALL_FIELDS: Final[bytes] = encode({
168
+ 'type': 'payment',
169
+ 'request_token': f'{REQUEST_TOKEN}',
170
+ 'account_id': f'{ACCOUNT_ID}',
171
+ 'external_id': f'{EXTERNAL_ID}',
172
+ 'location': LOCATION,
173
+ 'addresses': [TRANSACTION_ADDRESS],
174
+ 'payment_value': PAYMENT_VALUE,
175
+ 'payment_methods': PAYMENT_METHOD,
176
+ 'policy_id': f'{POLICY_ID}',
177
+ 'custom_properties': CUSTOM_PROPERTIES,
178
+ 'coupon': COUPON,
179
+ 'device_os': f'{DEVICE_OS.lower()}',
180
+ 'app_version': f'{APP_VERSION}',
181
+ 'store_id': f'{STORE_ID}'
182
+ })
183
+ REGISTER_VALID_PAYMENT_DATA_WITH_LOCATION: Final[bytes] = encode({
184
+ 'type': 'payment',
185
+ 'request_token': f'{REQUEST_TOKEN}',
186
+ 'account_id': f'{ACCOUNT_ID}',
187
+ 'location': LOCATION,
188
+ 'policy_id': f'{POLICY_ID}',
189
+ })
100
190
  REGISTER_INVALID_PAYMENT_DATA: Final[bytes] = encode({
101
191
  'type': 'payment',
102
192
  'request_token': f'{INVALID_REQUEST_TOKEN}',
@@ -108,12 +198,37 @@ class TestIncogniaAPI(TestCase):
108
198
  'account_id': f'{ACCOUNT_ID}',
109
199
  'policy_id': f'{POLICY_ID}'
110
200
  })
201
+ REGISTER_VALID_LOGIN_DATA_WITH_LOCATION: Final[bytes] = encode({
202
+ 'type': 'login',
203
+ 'request_token': f'{REQUEST_TOKEN}',
204
+ 'account_id': f'{ACCOUNT_ID}',
205
+ 'location': LOCATION,
206
+ 'policy_id': f'{POLICY_ID}'
207
+ })
208
+ REGISTER_VALID_LOGIN_DATA_ALL_FIELDS: Final[bytes] = encode({
209
+ 'type': 'login',
210
+ 'request_token': f'{REQUEST_TOKEN}',
211
+ 'account_id': f'{ACCOUNT_ID}',
212
+ 'location': LOCATION,
213
+ 'external_id': f'{EXTERNAL_ID}',
214
+ 'policy_id': f'{POLICY_ID}',
215
+ 'device_os': f'{DEVICE_OS.lower()}',
216
+ 'app_version': f'{APP_VERSION}'
217
+ })
111
218
  REGISTER_VALID_WEB_LOGIN_DATA: Final[bytes] = encode({
112
219
  'type': 'login',
113
220
  'request_token': f'{REQUEST_TOKEN}',
114
221
  'account_id': f'{ACCOUNT_ID}',
115
222
  'policy_id': f'{POLICY_ID}'
116
223
  })
224
+ REGISTER_VALID_WEB_LOGIN_ALL_FIELDS: Final[bytes] = encode({
225
+ 'type': 'login',
226
+ 'request_token': f'{REQUEST_TOKEN}',
227
+ 'account_id': f'{ACCOUNT_ID}',
228
+ 'external_id': f'{EXTERNAL_ID}',
229
+ 'policy_id': f'{POLICY_ID}',
230
+ 'custom_properties': CUSTOM_PROPERTIES
231
+ })
117
232
  REGISTER_INVALID_LOGIN_DATA: Final[bytes] = encode({
118
233
  'type': 'login',
119
234
  'request_token': f'{INVALID_REQUEST_TOKEN}',
@@ -148,6 +263,22 @@ class TestIncogniaAPI(TestCase):
148
263
 
149
264
  self.assertEqual(response, self.JSON_RESPONSE)
150
265
 
266
+ @patch.object(BaseRequest, 'post')
267
+ @patch.object(TokenManager, 'get', return_value=TOKEN_VALUES)
268
+ def test_register_new_web_signup_when_request_token_is_valid_should_return_a_valid_dict(
269
+ self, mock_token_manager_get: Mock, mock_base_request_post: Mock):
270
+ mock_base_request_post.configure_mock(return_value=self.JSON_RESPONSE)
271
+
272
+ api = IncogniaAPI(self.CLIENT_ID, self.CLIENT_SECRET)
273
+ response = api.register_new_web_signup(request_token=self.REQUEST_TOKEN)
274
+
275
+ mock_token_manager_get.assert_called()
276
+ mock_base_request_post.assert_called_with(Endpoints.SIGNUPS,
277
+ headers=self.AUTH_AND_JSON_CONTENT_HEADERS,
278
+ data=self.REGISTER_WEB_SIGNUP_DATA)
279
+
280
+ self.assertEqual(response, self.JSON_RESPONSE)
281
+
151
282
  @patch.object(BaseRequest, 'post')
152
283
  @patch.object(TokenManager, 'get', return_value=TOKEN_VALUES)
153
284
  def test_register_new_signup_when_request_token_is_valid_should_return_full_valid_dict_(
@@ -161,7 +292,9 @@ class TestIncogniaAPI(TestCase):
161
292
  external_id=self.EXTERNAL_ID,
162
293
  policy_id=self.POLICY_ID,
163
294
  account_id=self.ACCOUNT_ID,
164
- request_token=self.REQUEST_TOKEN)
295
+ request_token=self.REQUEST_TOKEN,
296
+ device_os=self.DEVICE_OS,
297
+ app_version=self.APP_VERSION)
165
298
 
166
299
  mock_token_manager_get.assert_called()
167
300
  mock_base_request_post.assert_called_with(Endpoints.SIGNUPS,
@@ -170,6 +303,25 @@ class TestIncogniaAPI(TestCase):
170
303
 
171
304
  self.assertEqual(response, self.JSON_RESPONSE)
172
305
 
306
+ @patch.object(BaseRequest, 'post')
307
+ @patch.object(TokenManager, 'get', return_value=TOKEN_VALUES)
308
+ def test_register_new_web_signup_when_request_token_is_valid_should_return_full_valid_dict_(
309
+ self, mock_token_manager_get: Mock, mock_base_request_post: Mock):
310
+ mock_base_request_post.configure_mock(return_value=self.JSON_RESPONSE)
311
+
312
+ api = IncogniaAPI(self.CLIENT_ID, self.CLIENT_SECRET)
313
+ response = api.register_new_web_signup(request_token=self.REQUEST_TOKEN,
314
+ policy_id=self.POLICY_ID,
315
+ account_id=self.ACCOUNT_ID,
316
+ custom_properties=self.CUSTOM_PROPERTIES)
317
+
318
+ mock_token_manager_get.assert_called()
319
+ mock_base_request_post.assert_called_with(Endpoints.SIGNUPS,
320
+ headers=self.AUTH_AND_JSON_CONTENT_HEADERS,
321
+ data=self.FULL_REGISTER_WEB_SIGNUP_DATA)
322
+
323
+ self.assertEqual(response, self.JSON_RESPONSE)
324
+
173
325
  @patch.object(BaseRequest, 'post')
174
326
  @patch.object(TokenManager, 'get', return_value=TOKEN_VALUES)
175
327
  def test_register_new_signup_when_request_token_is_empty_should_raise_an_IncogniaError(
@@ -181,6 +333,17 @@ class TestIncogniaAPI(TestCase):
181
333
  mock_token_manager_get.assert_not_called()
182
334
  mock_base_request_post.assert_not_called()
183
335
 
336
+ @patch.object(BaseRequest, 'post')
337
+ @patch.object(TokenManager, 'get', return_value=TOKEN_VALUES)
338
+ def test_register_new_web_signup_when_request_token_is_empty_should_raise_an_IncogniaError(
339
+ self, mock_token_manager_get: Mock, mock_base_request_post: Mock):
340
+ api = IncogniaAPI(self.CLIENT_ID, self.CLIENT_SECRET)
341
+
342
+ self.assertRaises(IncogniaError, api.register_new_web_signup, request_token='')
343
+
344
+ mock_token_manager_get.assert_not_called()
345
+ mock_base_request_post.assert_not_called()
346
+
184
347
  @patch.object(BaseRequest, 'post')
185
348
  @patch.object(TokenManager, 'get', return_value=TOKEN_VALUES)
186
349
  def test_register_new_signup_when_request_token_is_invalid_should_raise_an_IncogniaHTTPError(
@@ -196,6 +359,22 @@ class TestIncogniaAPI(TestCase):
196
359
  headers=self.AUTH_AND_JSON_CONTENT_HEADERS,
197
360
  data=self.REGISTER_INVALID_SIGNUP_DATA)
198
361
 
362
+ @patch.object(BaseRequest, 'post')
363
+ @patch.object(TokenManager, 'get', return_value=TOKEN_VALUES)
364
+ def test_register_new_web_signup_if_request_token_is_invalid_should_raise_an_IncogniaHTTPError(
365
+ self, mock_token_manager_get: Mock, mock_base_request_post: Mock):
366
+ mock_base_request_post.configure_mock(side_effect=IncogniaHTTPError)
367
+
368
+ api = IncogniaAPI(self.CLIENT_ID, self.CLIENT_SECRET)
369
+
370
+ self.assertRaises(IncogniaHTTPError, api.register_new_web_signup,
371
+ self.INVALID_REQUEST_TOKEN)
372
+
373
+ mock_token_manager_get.assert_called()
374
+ mock_base_request_post.assert_called_with(Endpoints.SIGNUPS,
375
+ headers=self.AUTH_AND_JSON_CONTENT_HEADERS,
376
+ data=self.REGISTER_INVALID_WEB_SIGNUP_DATA)
377
+
199
378
  @patch.object(BaseRequest, 'post')
200
379
  @patch.object(TokenManager, 'get', return_value=TOKEN_VALUES)
201
380
  def test_register_feedback_when_required_fields_are_valid_should_work(
@@ -290,6 +469,38 @@ class TestIncogniaAPI(TestCase):
290
469
 
291
470
  self.assertEqual(request_response, self.JSON_RESPONSE)
292
471
 
472
+ @patch.object(BaseRequest, 'post')
473
+ @patch.object(TokenManager, 'get', return_value=TOKEN_VALUES)
474
+ def test_register_payment_with_all_fields_should_work(
475
+ self, mock_token_manager_get: Mock, mock_base_request_post: Mock):
476
+ mock_base_request_post.configure_mock(return_value=self.JSON_RESPONSE)
477
+
478
+ api = IncogniaAPI(self.CLIENT_ID, self.CLIENT_SECRET)
479
+
480
+ request_response = api.register_payment(
481
+ request_token=self.REQUEST_TOKEN,
482
+ account_id=self.ACCOUNT_ID,
483
+ external_id=self.EXTERNAL_ID,
484
+ location=self.LOCATION,
485
+ addresses=[self.TRANSACTION_ADDRESS],
486
+ payment_value=self.PAYMENT_VALUE,
487
+ payment_methods=self.PAYMENT_METHOD,
488
+ policy_id=self.POLICY_ID,
489
+ custom_properties=self.CUSTOM_PROPERTIES,
490
+ coupon=self.COUPON,
491
+ device_os=self.DEVICE_OS,
492
+ app_version=self.APP_VERSION,
493
+ store_id=self.STORE_ID
494
+ )
495
+
496
+ mock_token_manager_get.assert_called()
497
+ mock_base_request_post.assert_called_with(Endpoints.TRANSACTIONS,
498
+ headers=self.AUTH_AND_JSON_CONTENT_HEADERS,
499
+ params=self.DEFAULT_PARAMS,
500
+ data=self.REGISTER_VALID_PAYMENT_DATA_ALL_FIELDS)
501
+
502
+ self.assertEqual(request_response, self.JSON_RESPONSE)
503
+
293
504
  @patch.object(BaseRequest, 'post')
294
505
  @patch.object(TokenManager, 'get', return_value=TOKEN_VALUES)
295
506
  def test_register_payment_when_request_token_is_empty_should_raise_an_IncogniaError(
@@ -418,6 +629,27 @@ class TestIncogniaAPI(TestCase):
418
629
 
419
630
  self.assertEqual(request_response, self.JSON_RESPONSE)
420
631
 
632
+ @patch.object(BaseRequest, 'post')
633
+ @patch.object(TokenManager, 'get', return_value=TOKEN_VALUES)
634
+ def test_register_web_login_when_all_fields_are_valid_should_work(
635
+ self, mock_token_manager_get: Mock, mock_base_request_post: Mock):
636
+ mock_base_request_post.configure_mock(return_value=self.JSON_RESPONSE)
637
+
638
+ api = IncogniaAPI(self.CLIENT_ID, self.CLIENT_SECRET)
639
+
640
+ request_response = api.register_web_login(self.REQUEST_TOKEN,
641
+ self.ACCOUNT_ID,
642
+ external_id=self.EXTERNAL_ID,
643
+ policy_id=self.POLICY_ID,
644
+ custom_properties=self.CUSTOM_PROPERTIES)
645
+ mock_token_manager_get.assert_called()
646
+ mock_base_request_post.assert_called_with(Endpoints.TRANSACTIONS,
647
+ headers=self.AUTH_AND_JSON_CONTENT_HEADERS,
648
+ params=self.DEFAULT_PARAMS,
649
+ data=self.REGISTER_VALID_WEB_LOGIN_ALL_FIELDS)
650
+
651
+ self.assertEqual(request_response, self.JSON_RESPONSE)
652
+
421
653
  @patch.object(BaseRequest, 'post')
422
654
  @patch.object(TokenManager, 'get', return_value=TOKEN_VALUES)
423
655
  def test_register_web_login_when_request_token_is_empty_should_raise_an_IncogniaError(
@@ -461,3 +693,199 @@ class TestIncogniaAPI(TestCase):
461
693
  headers=self.AUTH_AND_JSON_CONTENT_HEADERS,
462
694
  params=self.DEFAULT_PARAMS,
463
695
  data=self.REGISTER_INVALID_WEB_LOGIN_DATA)
696
+
697
+ @patch.object(BaseRequest, 'post')
698
+ @patch.object(TokenManager, 'get', return_value=TOKEN_VALUES)
699
+ def test_register_login_with_valid_location_should_work(
700
+ self, mock_token_manager_get: Mock, mock_base_request_post: Mock):
701
+
702
+ mock_base_request_post.configure_mock(return_value=self.JSON_RESPONSE)
703
+
704
+ api = IncogniaAPI(self.CLIENT_ID, self.CLIENT_SECRET)
705
+
706
+ request_response = api.register_login(self.REQUEST_TOKEN,
707
+ self.ACCOUNT_ID,
708
+ location=self.LOCATION,
709
+ policy_id=self.POLICY_ID)
710
+
711
+ mock_token_manager_get.assert_called()
712
+ mock_base_request_post.assert_called_with(Endpoints.TRANSACTIONS,
713
+ headers=self.AUTH_AND_JSON_CONTENT_HEADERS,
714
+ params=self.DEFAULT_PARAMS,
715
+ data=self.REGISTER_VALID_LOGIN_DATA_WITH_LOCATION)
716
+
717
+ self.assertEqual(request_response, self.JSON_RESPONSE)
718
+
719
+ @patch.object(BaseRequest, 'post')
720
+ @patch.object(TokenManager, 'get', return_value=TOKEN_VALUES)
721
+ def test_register_login_with_all_fields_should_work(
722
+ self, mock_token_manager_get: Mock, mock_base_request_post: Mock):
723
+
724
+ mock_base_request_post.configure_mock(return_value=self.JSON_RESPONSE)
725
+
726
+ api = IncogniaAPI(self.CLIENT_ID, self.CLIENT_SECRET)
727
+
728
+ request_response = api.register_login(self.REQUEST_TOKEN,
729
+ self.ACCOUNT_ID,
730
+ location=self.LOCATION,
731
+ external_id=self.EXTERNAL_ID,
732
+ policy_id=self.POLICY_ID,
733
+ device_os=self.DEVICE_OS,
734
+ app_version=self.APP_VERSION)
735
+
736
+ mock_token_manager_get.assert_called()
737
+ mock_base_request_post.assert_called_with(Endpoints.TRANSACTIONS,
738
+ headers=self.AUTH_AND_JSON_CONTENT_HEADERS,
739
+ params=self.DEFAULT_PARAMS,
740
+ data=self.REGISTER_VALID_LOGIN_DATA_ALL_FIELDS)
741
+
742
+ self.assertEqual(request_response, self.JSON_RESPONSE)
743
+
744
+ @patch.object(BaseRequest, 'post')
745
+ @patch.object(TokenManager, 'get', return_value=TOKEN_VALUES)
746
+ def test_register_login_with_location_and_empty_latitude_should_raise_an_IncogniaError(
747
+ self, mock_token_manager_get: Mock, mock_base_request_post: Mock):
748
+
749
+ mock_base_request_post.configure_mock(return_value=self.JSON_RESPONSE)
750
+
751
+ api = IncogniaAPI(self.CLIENT_ID, self.CLIENT_SECRET)
752
+
753
+ self.assertRaises(
754
+ IncogniaError, api.register_login,
755
+ self.REQUEST_TOKEN,
756
+ self.ACCOUNT_ID,
757
+ location=self.INVALID_LOCATION_EMPTY_LATITUDE,
758
+ policy_id=self.POLICY_ID,
759
+ )
760
+
761
+ mock_token_manager_get.assert_not_called()
762
+ mock_base_request_post.assert_not_called()
763
+
764
+ @patch.object(BaseRequest, 'post')
765
+ @patch.object(TokenManager, 'get', return_value=TOKEN_VALUES)
766
+ def test_register_login_with_location_and_empty_longitude_should_raise_an_IncogniaError(
767
+ self, mock_token_manager_get: Mock, mock_base_request_post: Mock):
768
+
769
+ mock_base_request_post.configure_mock(return_value=self.JSON_RESPONSE)
770
+
771
+ api = IncogniaAPI(self.CLIENT_ID, self.CLIENT_SECRET)
772
+
773
+ self.assertRaises(
774
+ IncogniaError,
775
+ api.register_login,
776
+ self.REQUEST_TOKEN,
777
+ self.ACCOUNT_ID,
778
+ location=self.INVALID_LOCATION_EMPTY_LONGITUDE,
779
+ policy_id=self.POLICY_ID,
780
+ )
781
+
782
+ mock_token_manager_get.assert_not_called()
783
+ mock_base_request_post.assert_not_called()
784
+
785
+ @patch.object(BaseRequest, 'post')
786
+ @patch.object(TokenManager, 'get', return_value=TOKEN_VALUES)
787
+ def test_register_login_with_location_and_wrong_timestamp_should_raise_an_IncogniaError(
788
+ self, mock_token_manager_get: Mock, mock_base_request_post: Mock):
789
+
790
+ mock_base_request_post.configure_mock(return_value=self.JSON_RESPONSE)
791
+
792
+ api = IncogniaAPI(self.CLIENT_ID, self.CLIENT_SECRET)
793
+
794
+ self.assertRaises(
795
+ IncogniaError,
796
+ api.register_login,
797
+ self.REQUEST_TOKEN,
798
+ self.ACCOUNT_ID,
799
+ location=self.INVALID_LOCATION_WRONG_TIMESTAMP,
800
+ policy_id=self.POLICY_ID,
801
+ )
802
+
803
+ mock_token_manager_get.assert_not_called()
804
+ mock_base_request_post.assert_not_called()
805
+
806
+ @patch.object(BaseRequest, 'post')
807
+ @patch.object(TokenManager, 'get', return_value=TOKEN_VALUES)
808
+ def test_register_payment_with_valid_location_should_work(
809
+ self, mock_token_manager_get: Mock, mock_base_request_post: Mock):
810
+
811
+ mock_base_request_post.configure_mock(return_value=self.JSON_RESPONSE)
812
+
813
+ api = IncogniaAPI(self.CLIENT_ID, self.CLIENT_SECRET)
814
+
815
+ request_response = api.register_payment(
816
+ self.REQUEST_TOKEN,
817
+ self.ACCOUNT_ID,
818
+ location=self.LOCATION,
819
+ policy_id=self.POLICY_ID,
820
+ )
821
+
822
+ mock_token_manager_get.assert_called()
823
+ mock_base_request_post.assert_called_with(
824
+ Endpoints.TRANSACTIONS,
825
+ headers=self.AUTH_AND_JSON_CONTENT_HEADERS,
826
+ params=self.DEFAULT_PARAMS,
827
+ data=self.REGISTER_VALID_PAYMENT_DATA_WITH_LOCATION,
828
+ )
829
+
830
+ self.assertEqual(request_response, self.JSON_RESPONSE)
831
+
832
+ @patch.object(BaseRequest, 'post')
833
+ @patch.object(TokenManager, 'get', return_value=TOKEN_VALUES)
834
+ def test_register_payment_with_location_and_empty_latitude_should_raise_an_IncogniaError(
835
+ self, mock_token_manager_get: Mock, mock_base_request_post: Mock):
836
+
837
+ mock_base_request_post.configure_mock(return_value=self.JSON_RESPONSE)
838
+
839
+ api = IncogniaAPI(self.CLIENT_ID, self.CLIENT_SECRET)
840
+
841
+ self.assertRaises(
842
+ IncogniaError, api.register_payment,
843
+ self.REQUEST_TOKEN,
844
+ self.ACCOUNT_ID,
845
+ location=self.INVALID_LOCATION_EMPTY_LATITUDE,
846
+ policy_id=self.POLICY_ID,
847
+ )
848
+
849
+ mock_token_manager_get.assert_not_called()
850
+ mock_base_request_post.assert_not_called()
851
+
852
+ @patch.object(BaseRequest, 'post')
853
+ @patch.object(TokenManager, 'get', return_value=TOKEN_VALUES)
854
+ def test_register_payment_with_location_and_empty_longitude_should_raise_an_IncogniaError(
855
+ self, mock_token_manager_get: Mock, mock_base_request_post: Mock):
856
+
857
+ mock_base_request_post.configure_mock(return_value=self.JSON_RESPONSE)
858
+
859
+ api = IncogniaAPI(self.CLIENT_ID, self.CLIENT_SECRET)
860
+
861
+ self.assertRaises(
862
+ IncogniaError, api.register_payment,
863
+ self.REQUEST_TOKEN,
864
+ self.ACCOUNT_ID,
865
+ location=self.INVALID_LOCATION_EMPTY_LONGITUDE,
866
+ policy_id=self.POLICY_ID,
867
+ )
868
+
869
+ mock_token_manager_get.assert_not_called()
870
+ mock_base_request_post.assert_not_called()
871
+
872
+ @patch.object(BaseRequest, 'post')
873
+ @patch.object(TokenManager, 'get', return_value=TOKEN_VALUES)
874
+ def test_register_payment_with_location_and_wrong_timestamp_should_raise_an_IncogniaError(
875
+ self, mock_token_manager_get: Mock, mock_base_request_post: Mock):
876
+
877
+ mock_base_request_post.configure_mock(return_value=self.JSON_RESPONSE)
878
+
879
+ api = IncogniaAPI(self.CLIENT_ID, self.CLIENT_SECRET)
880
+
881
+ self.assertRaises(
882
+ IncogniaError,
883
+ api.register_payment,
884
+ self.REQUEST_TOKEN,
885
+ self.ACCOUNT_ID,
886
+ location=self.INVALID_LOCATION_WRONG_TIMESTAMP,
887
+ policy_id=self.POLICY_ID,
888
+ )
889
+
890
+ mock_token_manager_get.assert_not_called()
891
+ mock_base_request_post.assert_not_called()
@@ -1,5 +0,0 @@
1
- import datetime as dt
2
-
3
-
4
- def has_timezone(d: dt.datetime) -> bool:
5
- return d.tzinfo is not None and d.tzinfo.utcoffset(d) is not None