Skip to content
This repository was archived by the owner on Sep 6, 2025. It is now read-only.

Commit 218314c

Browse files
Evaluate json function in track_user_task (#17)
* Use codes from requests instead of constants * Add try except block to track_user_task function * Update Version and Readme
1 parent ddf2b69 commit 218314c

File tree

4 files changed

+87
-52
lines changed

4 files changed

+87
-52
lines changed

README.md

Lines changed: 14 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -13,21 +13,26 @@ Python client for [Crossengage's API](https://docs.crossengage.io)
1313
Library supports next methods:
1414

1515
**User profile management**
16-
- `update_user(self, user)`
17-
- `delete_user(self, user)`
18-
- `delete_user_by_xng_id(self, user)`
16+
- `get_user(self, user)` | v2
17+
- `update_user(self, user)` | v1
18+
- `update_user_async(self, user)` | v2
19+
- `delete_user(self, user)` | v1
20+
- `delete_user_async(self, user)` | v2
21+
- `delete_user_by_xng_id(self, user)` | v1
22+
- `track_user_task(self, tracking_id)` | v2
1923

2024
**User attributes management**
21-
- `add_user_attribute(self, attribute_name, attribute_type, nested_type)`
22-
- `add_nested_user_attribute(self, parent_name, attribute_name, attribute_type)`
23-
- `list_user_attributes(self, offset, limit)`
24-
- `delete_user_attribute(self, attribute_id)`
25+
- `add_user_attribute(self, attribute_name, attribute_type, nested_type)` | v1
26+
- `add_nested_user_attribute(self, parent_name, attribute_name, attribute_type)` | v1
27+
- `list_user_attributes(self, offset, limit)` | v1
28+
- `delete_user_attribute(self, attribute_id)` | v1
2529

2630
**Bulk user management**
27-
- `batch_process(self, delete_list=[], update_list=[])`
31+
- `batch_process(self, delete_list=[], update_list=[])` | v1
32+
- `batch_process_async(self, delete_list=[], update_list=[])` | v2
2833

2934
**Events management**
30-
- `send_events(self, events, email=None, user_id=None, business_unit=None)`
35+
- `send_events(self, events, email=None, user_id=None, business_unit=None)` | v1
3136

3237
### Owner
3338
[Alexander Zhilyaev](mailto:azh@hellofresh.com)

crossengage/client.py

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -339,7 +339,12 @@ def track_user_task(self, tracking_id):
339339

340340
r = self.requests.get(self.request_url, headers=headers)
341341

342-
return r.status_code, r.json()
342+
try:
343+
body = r.json()
344+
except ValueError:
345+
body = None
346+
347+
return r.status_code, body
343348

344349
def __create_request(self, payload, request_type, version):
345350
headers = update_dict(self.default_headers, {self.API_VERSION_HEADER: self.API_VERSIONS[version]})

setup.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
from setuptools import setup, find_packages
22

33
NAME = "crossengage-client"
4-
VERSION = "0.7.0"
4+
VERSION = "1.1.1"
55

66
REQUIRES = []
77

tests/test_client.py

Lines changed: 66 additions & 41 deletions
Original file line numberDiff line numberDiff line change
@@ -2,14 +2,14 @@
22
import unittest
33

44
from mock import Mock
5-
from requests import RequestException
5+
from requests import RequestException, codes
66

77
from crossengage.client import CrossengageClient
88

99

1010
class DummyRequest(object):
1111
def __init__(self):
12-
self.status_code = 200
12+
self.status_code = codes.ok
1313
self.text = 'Some text'
1414
self.request = Mock()
1515

@@ -32,7 +32,7 @@ def json():
3232

3333
class DummyRequestException(object):
3434
def __init__(self):
35-
self.status_code = 200
35+
self.status_code = codes.ok
3636

3737
def put(self, request_url, data, headers):
3838
raise RequestException('Something went wrong')
@@ -81,8 +81,8 @@ def test_init(self):
8181

8282
def test_get_user(self):
8383
expected_response = self.user.copy()
84-
expected_response.update({"status_code": 200})
85-
response = Mock(status_code=200)
84+
expected_response.update({"status_code": codes.ok})
85+
response = Mock(status_code=codes.ok)
8686
response.json.return_value = expected_response
8787
requests = Mock()
8888
requests.get.return_value = response
@@ -104,7 +104,7 @@ def test_update_user(self):
104104
self.assertEqual(self.client.default_headers['X-XNG-AuthToken'], 'SOME_TOKEN')
105105
self.assertEqual(self.client.default_headers['Content-Type'], 'application/json')
106106

107-
self.assertEqual(response['status_code'], 200)
107+
self.assertEqual(response['status_code'], codes.ok)
108108
self.assertEqual(response['errors'], '')
109109
self.assertEqual(response['success'], True)
110110

@@ -121,7 +121,7 @@ def test_update_user_request_exception(self):
121121

122122
def test_update_users_bulk(self):
123123
response = Mock(
124-
status_code=200,
124+
status_code=codes.ok,
125125
text='{"updated": [{"id": "updated_id","xngId": "updated_xngId","success": true}],'
126126
'"deleted": [{"id": "deleted_id","xngId": "deleted_xngId","success": true}]}')
127127

@@ -146,13 +146,13 @@ def test_update_users_bulk(self):
146146
}
147147
)
148148

149-
self.assertEqual(response['status_code'], 200)
149+
self.assertEqual(response['status_code'], codes.ok)
150150
self.assertEqual(response['updated'][0]['id'], 'updated_id')
151151
self.assertEqual(response['updated'][0]['success'], True)
152152

153153
def test_update_users_bulk_bad_request(self):
154154
response = Mock(
155-
status_code=400,
155+
status_code=codes.bad_request,
156156
text='{"updated": [{"id": "updated_id","xngId": "updated_xngId","success": false,'
157157
'"errors": [{"field": "id","type": "NOT_NULL"},{"field": "email","type": "WRONG_FORMAT"}]}],'
158158
'"deleted": [{"id": "deleted_id","xngId": "deleted_xngId","success": false,'
@@ -179,7 +179,7 @@ def test_update_users_bulk_bad_request(self):
179179
}
180180
)
181181

182-
self.assertEqual(response['status_code'], 400)
182+
self.assertEqual(response['status_code'], codes.bad_request)
183183
self.assertEqual(response['updated'][0]['id'], 'updated_id')
184184
self.assertEqual(response['updated'][0]['success'], False)
185185
self.assertEqual(response['success'], False)
@@ -189,7 +189,7 @@ def test_delete_user(self):
189189
'id': '1',
190190
}
191191
dummy_request = DummyRequest()
192-
dummy_request.status_code = 204
192+
dummy_request.status_code = codes.no_content
193193
self.client.requests = dummy_request
194194
response = self.client.delete_user(user)
195195

@@ -198,14 +198,14 @@ def test_delete_user(self):
198198
self.assertEqual(self.client.default_headers['X-XNG-ApiVersion'], '1')
199199
self.assertEqual(self.client.default_headers['Content-Type'], 'application/json')
200200

201-
self.assertEqual(response['status_code'], 204)
201+
self.assertEqual(response['status_code'], codes.no_content)
202202

203203
def test_delete_user_by_xng_id(self):
204204
user = {
205205
'xngId': '1',
206206
}
207207
dummy_request = DummyRequest()
208-
dummy_request.status_code = 204
208+
dummy_request.status_code = codes.no_content
209209
self.client.requests = dummy_request
210210
response = self.client.delete_user_by_xng_id(user)
211211

@@ -214,11 +214,11 @@ def test_delete_user_by_xng_id(self):
214214
self.assertEqual(self.client.default_headers['X-XNG-ApiVersion'], '1')
215215
self.assertEqual(self.client.default_headers['Content-Type'], 'application/json')
216216

217-
self.assertEqual(response['status_code'], 204)
217+
self.assertEqual(response['status_code'], codes.no_content)
218218

219219
def test_add_user_attribute(self):
220220
dummy_request = DummyRequest()
221-
dummy_request.status_code = 200
221+
dummy_request.status_code = codes.ok
222222
self.client.requests = dummy_request
223223
response = self.client.add_user_attribute(
224224
attribute_name='attr_name',
@@ -231,13 +231,13 @@ def test_add_user_attribute(self):
231231
self.assertEqual(self.client.default_headers['X-XNG-ApiVersion'], '1')
232232
self.assertEqual(self.client.default_headers['Content-Type'], 'application/json')
233233

234-
self.assertEqual(response['status_code'], 200)
234+
self.assertEqual(response['status_code'], codes.ok)
235235
self.assertEqual(response['errors'], '')
236236
self.assertEqual(response['success'], True)
237237

238238
def test_add_nested_user_attribute(self):
239239
dummy_request = DummyRequest()
240-
dummy_request.status_code = 200
240+
dummy_request.status_code = codes.ok
241241
self.client.requests = dummy_request
242242
response = self.client.add_nested_user_attribute(
243243
parent_name='parent_attribute',
@@ -250,13 +250,13 @@ def test_add_nested_user_attribute(self):
250250
self.assertEqual(self.client.default_headers['X-XNG-ApiVersion'], '1')
251251
self.assertEqual(self.client.default_headers['Content-Type'], 'application/json')
252252

253-
self.assertEqual(response['status_code'], 200)
253+
self.assertEqual(response['status_code'], codes.ok)
254254
self.assertEqual(response['errors'], '')
255255
self.assertEqual(response['success'], True)
256256

257257
def test_list_user_attributes(self):
258258
dummy_request = DummyRequest()
259-
dummy_request.status_code = 200
259+
dummy_request.status_code = codes.ok
260260
self.client.requests = dummy_request
261261
response = self.client.list_user_attributes(offset=0, limit=10)
262262

@@ -265,13 +265,13 @@ def test_list_user_attributes(self):
265265
self.assertEqual(self.client.default_headers['X-XNG-ApiVersion'], '1')
266266
self.assertEqual(self.client.default_headers['Content-Type'], 'application/json')
267267

268-
self.assertEqual(response['status_code'], 200)
268+
self.assertEqual(response['status_code'], codes.ok)
269269
self.assertEqual(response['errors'], '')
270270
self.assertEqual(response['success'], True)
271271

272272
def test_delete_user_attributes(self):
273273
dummy_request = DummyRequest()
274-
dummy_request.status_code = 204
274+
dummy_request.status_code = codes.no_content
275275
self.client.requests = dummy_request
276276
response = self.client.delete_user_attribute(attribute_id=123)
277277

@@ -280,10 +280,10 @@ def test_delete_user_attributes(self):
280280
self.assertEqual(self.client.default_headers['X-XNG-ApiVersion'], '1')
281281
self.assertEqual(self.client.default_headers['Content-Type'], 'application/json')
282282

283-
self.assertEqual(response['status_code'], 204)
283+
self.assertEqual(response['status_code'], codes.no_content)
284284

285285
def test_send_events_with_user_id(self):
286-
response = Mock(status_code=202, text='{"success": true, "errors": ""}')
286+
response = Mock(status_code=codes.accepted, text='{"success": true, "errors": ""}')
287287
response.json.return_value = {'success': True, 'errors': ''}
288288

289289
events = [{'foo': 'bar'}, {'xpto': 123}]
@@ -305,10 +305,10 @@ def test_send_events_with_user_id(self):
305305
'Content-Type': 'application/json',
306306
})
307307

308-
self.assertEqual(response['status_code'], 202)
308+
self.assertEqual(response['status_code'], codes.accepted)
309309

310310
def test_send_events_with_email(self):
311-
response = Mock(status_code=202, text='{"success": true, "errors": ""}')
311+
response = Mock(status_code=codes.accepted, text='{"success": true, "errors": ""}')
312312
response.json.return_value = {'success': True, 'errors': ''}
313313

314314
events = [{'foo': 'bar'}, {'xpto': 123}]
@@ -329,15 +329,15 @@ def test_send_events_with_email(self):
329329
'Content-Type': 'application/json',
330330
})
331331

332-
self.assertEqual(response['status_code'], 202)
332+
self.assertEqual(response['status_code'], codes.accepted)
333333

334334
def test_send_events_value_error(self):
335335
events = [{'foo': 'bar'}, {'xpto': 123}]
336336
self.client.requests = Mock()
337337
self.assertRaises(ValueError, self.client.send_events, events=events)
338338

339339
def test_send_events_request_exception_raised(self):
340-
response = Mock(status_code=202, text='{"success": true, "errors": ""}')
340+
response = Mock(status_code=codes.accepted, text='{"success": true, "errors": ""}')
341341
response.json.return_value = {'success': True, 'errors': ''}
342342

343343
events = [{'foo': 'bar'}, {'xpto': 123}]
@@ -362,7 +362,7 @@ def test_send_events_request_exception_raised(self):
362362
self.assertEqual(response['errors'], {'connection_error': 'exception raised'})
363363

364364
def test_send_events_exception_raised(self):
365-
response = Mock(status_code=202, text='{???}')
365+
response = Mock(status_code=codes.accepted, text='{???}')
366366
response.json.return_value = {'success': True, 'errors': ''}
367367

368368
events = [{'foo': 'bar'}, {'xpto': 123}]
@@ -387,7 +387,7 @@ def test_send_events_exception_raised(self):
387387
self.assertEqual(response['errors'], {'client_error': 'exception raised'})
388388

389389
def test_send_events_internal_server_error_response(self):
390-
response = Mock(status_code=500, text='Something went wrong')
390+
response = Mock(status_code=codes.server_error, text='Something went wrong')
391391
response.json.return_value = {}
392392

393393
events = [{'foo': 'bar'}, {'xpto': 123}]
@@ -412,7 +412,7 @@ def test_send_events_internal_server_error_response(self):
412412
self.assertEqual(response['errors'], {'server_error': 'error on crossengage side'})
413413

414414
def test_send_events_bad_request_error_response(self):
415-
response = Mock(status_code=400, text='{}')
415+
response = Mock(status_code=codes.bad_request, text='{}')
416416
response.json.return_value = {
417417
'id': 'some_id',
418418
'xngId': 'some_xngid',
@@ -455,7 +455,7 @@ def test_send_events_bad_request_error_response(self):
455455

456456
def test_batch_process(self):
457457
response = Mock(
458-
status_code=200,
458+
status_code=codes.ok,
459459
text='{"updated": [{"id": "updated_id","xngId": "updated_xngId","success": true}],'
460460
'"deleted": [{"id": "deleted_id","xngId": "deleted_xngId","success": true}]}')
461461

@@ -480,11 +480,11 @@ def test_batch_process(self):
480480
headers=self.default_headers_api_v1
481481
)
482482

483-
self.assertEqual(result, (200, json.loads(response.text)))
483+
self.assertEqual(result, (codes.ok, json.loads(response.text)))
484484

485485
def test_update_user_async(self):
486-
expected_response = {"status_code": 202, "trackingId": "2e312089-a987-45c6-adbd-b904bc4dfc97"}
487-
response = Mock(status_code=202)
486+
expected_response = {"status_code": codes.accepted, "trackingId": "2e312089-a987-45c6-adbd-b904bc4dfc97"}
487+
response = Mock(status_code=codes.accepted)
488488
response.json.return_value = expected_response
489489
requests = Mock()
490490
requests.put.return_value = response
@@ -500,8 +500,8 @@ def test_update_user_async(self):
500500
self.assertEqual(expected_response, result)
501501

502502
def test_delete_user_async(self):
503-
expected_response = {"status_code": 202, "trackingId": "2e312089-a987-45c6-adbd-b904bc4dfc97"}
504-
response = Mock(status_code=202)
503+
expected_response = {"status_code": codes.accepted, "trackingId": "2e312089-a987-45c6-adbd-b904bc4dfc97"}
504+
response = Mock(status_code=codes.accepted)
505505
response.json.return_value = expected_response
506506
requests = Mock()
507507
requests.delete.return_value = response
@@ -518,7 +518,7 @@ def test_delete_user_async(self):
518518

519519
def test_batch_process_async(self):
520520
expected_body = {"trackingId": "2e312089-a987-45c6-adbd-b904bc4dfc97"}
521-
response = Mock(status_code=202)
521+
response = Mock(status_code=codes.accepted)
522522

523523
response.json.return_value = expected_body
524524

@@ -541,23 +541,48 @@ def test_batch_process_async(self):
541541
headers=self.default_headers_api_v2
542542
)
543543

544-
self.assertEqual(result, (202, expected_body))
544+
self.assertEqual(result, (codes.accepted, expected_body))
545545

546-
def test_track_user_task(self):
546+
def test_track_user_task_ok(self):
547+
"""Crossengage returns status code 200"""
548+
# GIVEN
547549
expected_body = {"stage": "PROCESSED", "total": 2, "success": 1, "error": 1}
548-
response = Mock(status_code=200)
549550

551+
response = Mock(status_code=codes.ok)
550552
response.json.return_value = expected_body
551553

552554
requests = Mock()
553555
requests.get.return_value = response
554556
self.client.requests = requests
555557

558+
# WHEN
556559
result = self.client.track_user_task("trackingId")
557560

561+
# THEN
558562
requests.get.assert_called_once_with(
559563
self.CROSSENGAGE_URL + 'users/track/trackingId',
560564
headers=self.default_headers_api_v2
561565
)
562566

563-
self.assertEqual(result, (200, expected_body))
567+
self.assertEqual(result, (codes.ok, expected_body))
568+
569+
def test_track_user_task_not_found(self):
570+
"""Crossengage returns status code 404"""
571+
# GIVEN
572+
response = Mock(status_code=codes.not_found)
573+
response.json.side_effect = ValueError
574+
575+
requests = Mock()
576+
requests.get.return_value = response
577+
self.client.requests = requests
578+
579+
# WHEN
580+
result = self.client.track_user_task("trackingId")
581+
582+
# THEN
583+
requests.get.assert_called_once_with(
584+
self.CROSSENGAGE_URL + 'users/track/trackingId',
585+
headers=self.default_headers_api_v2
586+
)
587+
588+
self.assertEqual(result, (codes.not_found, None))

0 commit comments

Comments
 (0)