Skip to content

Commit 5dfd449

Browse files
committed
fix attribute property names. add unit tests for camelcase and more end to end
1 parent 5d33d3a commit 5dfd449

10 files changed

Lines changed: 217 additions & 50 deletions

File tree

identify/main/identify_sync_client.py

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -66,17 +66,17 @@ def create_attribute_for_traffic_type(self, traffic_type_id, attr_data):
6666
:param attr_data: Dictionary with the the data to create the new
6767
attribute. Should include the followind fields:
6868
- 'id': Id of the new attribute
69-
- 'display_name': Display Name of the new attribute
69+
- 'displayName': Display Name of the new attribute
7070
- 'description': Description of the new attribute
71-
- 'data_type': Data type of the new attribute
71+
- 'dataType': Data type of the new attribute
7272
'''
7373
return Attribute.create(
7474
self._client,
7575
attr_data.get('id'),
7676
traffic_type_id,
77-
attr_data.get('display_name'),
77+
attr_data.get('displayName'),
7878
attr_data.get('description'),
79-
attr_data.get('data_type')
79+
attr_data.get('dataType')
8080
)
8181

8282
def delete_attribute_from_schema(self, traffic_type_id, attribute_id):

identify/resources/attribute.py

Lines changed: 11 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -94,25 +94,14 @@ def _build_single_from_collection_response(cls, client, response):
9494
response['dataType']
9595
)
9696

97-
def to_dict(self):
98-
temp = {
99-
'id': self.id,
100-
'trafficTypeId': self.traffic_type_id,
101-
'displayName': self.display_name,
102-
'description': self.description,
103-
'dataType': self.data_type
104-
}
105-
106-
return temp
107-
10897
@classmethod
10998
def create(cls, client, id, traffic_type_id, display_name, description,
11099
data_type):
111100
'''
112101
'''
113102
# TODO: Validate!
114103
try:
115-
client.make_request(
104+
response = client.make_request(
116105
cls._endpoint['create'],
117106
{
118107
'id': id,
@@ -123,6 +112,16 @@ def create(cls, client, id, traffic_type_id, display_name, description,
123112
},
124113
trafficTypeId=traffic_type_id
125114
)
115+
116+
return Attribute(
117+
client,
118+
response['id'],
119+
response['trafficTypeId'],
120+
response['displayName'],
121+
response['description'],
122+
response['dataType']
123+
)
124+
126125
except HTTPResponseError as e:
127126
LOGGER.error('Call to Identify API failed. Attribute not created.')
128127
raise e

identify/resources/base_resource.py

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -113,13 +113,15 @@ def _validate(cls, response_item):
113113

114114
def to_dict(self):
115115
'''
116+
Returns a dictionary with the property names in camelCase, in compliance
117+
with the Identify backend
116118
'''
117119
try:
118120
temp = {
119121
attribute: getattr(
120122
self, '_' + camelcase.to_underscore(attribute),
121-
None)
122-
for attribute in self._schema
123+
None
124+
) for attribute in self._schema
123125
}
124126
return temp
125127
except Exception as e:

identify/resources/identity.py

Lines changed: 8 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -148,7 +148,7 @@ def create_many(cls, client, traffic_type_id, environment_id, entities):
148148
'''
149149
# TODO: Validate!
150150
try:
151-
client.make_request(
151+
response = client.make_request(
152152
cls._endpoint['create_many'],
153153
[
154154
{
@@ -162,6 +162,13 @@ def create_many(cls, client, traffic_type_id, environment_id, entities):
162162
trafficTypeId=traffic_type_id,
163163
environmentId=environment_id
164164
)
165+
return [
166+
Identity(
167+
client, i['key'], i['trafficTypeId'],
168+
i['environmentId'], i['values']
169+
) for i in response
170+
]
171+
165172
except HTTPResponseError as e:
166173
LOGGER.error('Call to Identify API failed. Identities not created.')
167174
raise e

identify/resources/traffic_type.py

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -28,12 +28,12 @@ class TrafficType(BaseResource):
2828
'displayAttributeId': 'string'
2929
}
3030

31-
def __init__(self, client, id, name=None, display_name=None):
31+
def __init__(self, client, id, name=None, display_attribute_id=None):
3232
'''
3333
'''
3434
BaseResource.__init__(self, client, id)
3535
self._name = name
36-
self._display_name = display_name
36+
self._display_attribute_id = display_attribute_id
3737

3838
@property
3939
def id(self):
@@ -44,22 +44,22 @@ def name(self):
4444
return self._name
4545

4646
@property
47-
def display_name(self):
48-
return self._display_name
47+
def display_attribute_id(self):
48+
return self._display_attribute_id
4949

5050
def fetch_attributes(self):
5151
'''
5252
'''
5353
return Attribute.retrieve_all(self._client, trafficTypeId=self._id)
5454

55-
def add_attribute(self, id, display_name, description, data_type):
55+
def add_attribute(self, id, display_attribute_id, description, data_type):
5656
'''
5757
'''
5858
return Attribute.create(
5959
self._client,
6060
id,
6161
self._id,
62-
display_name,
62+
display_attribute_id,
6363
description,
6464
data_type
6565
)

identify/tests/e2e/e2etests.py

Lines changed: 94 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,10 @@
33
import os
44
import os.path
55
from identify.main import get_client
6+
from identify.resources.traffic_type import TrafficType
7+
from identify.resources.environment import Environment
8+
from identify.resources.attribute import Attribute
9+
from identify.resources.identity import Identity
610

711

812
class TestEndToEnd:
@@ -16,12 +20,10 @@ def setup_class(cls):
1620
cls.mock_server_subprocess = subprocess.Popen(
1721
['python', os.path.join(dir_path, 'server.py')]
1822
)
19-
time.sleep(5)
23+
time.sleep(3)
2024

21-
def test_successful_command_sequence(self):
25+
def test_traffic_type_endpoint(self):
2226
'''
23-
Test a basic command sequence using the get_client entry point function,
24-
issuing calls to a mocked API running in background.
2527
'''
2628
c = get_client({
2729
'base_url': 'http://localhost:8888',
@@ -30,39 +32,112 @@ def test_successful_command_sequence(self):
3032

3133
tts = c.get_traffic_types()
3234
assert isinstance(tts, list)
35+
assert all(isinstance(tt, TrafficType) for tt in tts)
36+
assert all(
37+
{
38+
'id': tt.id,
39+
'name': tt.name,
40+
'displayAttributeId': tt.display_attribute_id
41+
} == tt.to_dict()
42+
for tt in tts
43+
)
44+
45+
def test_environments_endpoint(self):
46+
'''
47+
'''
48+
c = get_client({
49+
'base_url': 'http://localhost:8888',
50+
'apikey': 'Admin'
51+
})
3352

3453
envs = c.get_environments()
3554
assert isinstance(envs, list)
55+
assert all(isinstance(env, Environment) for env in envs)
56+
assert all(
57+
{
58+
'id': env.id,
59+
'name': env.name,
60+
} == env.to_dict()
61+
for env in envs
62+
)
3663

37-
attrs = c.get_attributes_for_traffic_type(tts[0].id)
64+
def test_attribute_endpoints(self):
65+
'''
66+
'''
67+
c = get_client({
68+
'base_url': 'http://localhost:8888',
69+
'apikey': 'Admin'
70+
})
71+
72+
attrs = c.get_attributes_for_traffic_type('1')
3873
assert isinstance(attrs, list)
74+
assert all(isinstance(attr, Attribute) for attr in attrs)
75+
assert all(
76+
{
77+
'id': attr.id,
78+
'trafficTypeId': attr.traffic_type_id,
79+
'displayName': attr.display_name,
80+
'description': attr.description,
81+
'dataType': attr.data_type,
82+
} == attr.to_dict()
83+
for attr in attrs
84+
)
3985

86+
new_attr_props = {
87+
'id': 'aa',
88+
'trafficTypeId': '1',
89+
'displayName': 'AA',
90+
'description': 'DESC',
91+
'dataType': 'STRING'
92+
}
4093
new_attr = c.create_attribute_for_traffic_type(
41-
1,
94+
'1',
4295
{
4396
'id': 'aa',
44-
'display_name': 'AA',
97+
'displayName': 'AA',
4598
'description': 'DESC',
46-
'data_type': 'STRING'
99+
'dataType': 'STRING'
47100
}
48101
)
49-
assert isinstance(new_attr, object)
102+
assert new_attr_props == new_attr.to_dict()
50103

51-
attrs_2 = c.get_attributes_for_traffic_type(tts[0].id)
52-
assert isinstance(attrs_2, list)
104+
res_delete = c.delete_attribute_from_schema(1, 'aa')
105+
assert res_delete is None
53106

54-
c.delete_attribute_from_schema(1, 'aa')
55-
attrs_3 = c.get_attributes_for_traffic_type(tts[0].id)
56-
assert isinstance(attrs_3, list)
107+
def test_identity_endpoints(self):
108+
'''
109+
'''
110+
c = get_client({
111+
'base_url': 'http://localhost:8888',
112+
'apikey': 'Admin'
113+
})
57114

58115
i1 = c.add_identity('1', '1', 'keycita', {'a1': 'qwe'})
59-
assert isinstance(i1, object)
116+
assert isinstance(i1, Identity)
117+
assert {
118+
'key': i1.key,
119+
'environmentId': i1.environment_id,
120+
'trafficTypeId': i1.traffic_type_id,
121+
'values': i1.values
122+
} == i1.to_dict()
60123

61124
i2 = c.update_identity('1', '1', 'keycita', {'a1': 'qwe2'})
62-
assert isinstance(i2, object)
125+
assert isinstance(i2, Identity)
126+
assert {
127+
'key': i2.key,
128+
'environmentId': i2.environment_id,
129+
'trafficTypeId': i2.traffic_type_id,
130+
'values': i2.values
131+
} == i2.to_dict()
63132

64133
i3 = c.patch_identity('1', '1', 'keycita', {'a1': 'qwe3'})
65-
assert isinstance(i3, object)
134+
assert isinstance(i3, Identity)
135+
assert {
136+
'key': i3.key,
137+
'environmentId': i3.environment_id,
138+
'trafficTypeId': i3.traffic_type_id,
139+
'values': i3.values
140+
} == i3.to_dict()
66141

67142
res_add_identities = c.add_identities(
68143
'1',
@@ -73,6 +148,8 @@ def test_successful_command_sequence(self):
73148
}
74149
)
75150
assert res_add_identities is None
151+
assert isinstance(res_add_identities, list)
152+
assert all(isinstance(i, Identity) for i in res_add_identities)
76153

77154
res_delete_attr = c.delete_attributes_from_key('1', '1', 'keycita')
78155
assert res_delete_attr is None

identify/tests/util/__init__.py

Whitespace-only changes.
Lines changed: 76 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,76 @@
1+
from __future__ import absolute_import, division, print_function, \
2+
unicode_literals
3+
4+
from identify.util.camelcase import to_underscore, from_underscore
5+
6+
7+
class TestCamelCaseUtils:
8+
'''
9+
Tests for the camelcase module utilities
10+
'''
11+
12+
def test_to_underscore(self):
13+
'''
14+
Test that camelcase names are correctly converted to underscores.
15+
'''
16+
cases = [{
17+
'in': 'camelCase',
18+
'out': 'camel_case',
19+
}, {
20+
'in': 'camelcase',
21+
'out': 'camelcase',
22+
}, {
23+
'in': 'CamelCase',
24+
'out': 'camel_case',
25+
}, {
26+
'in': 'camelCCase',
27+
'out': 'camel_c_case',
28+
}, {
29+
'in': '',
30+
'out': '',
31+
}, {
32+
'in': 'camel3Case',
33+
'out': 'camel3_case',
34+
}, {
35+
'in': 'camelCaseMultipleWords',
36+
'out': 'camel_case_multiple_words',
37+
}, {
38+
'in': 'camelCase_Underscore',
39+
'out': 'camel_case__underscore',
40+
}]
41+
42+
for case in cases:
43+
assert to_underscore(case['in']) == case['out']
44+
45+
def test_from_underscore(self):
46+
'''
47+
Test that camelcase names are correctly converted to underscores.
48+
'''
49+
cases = [{
50+
'out': 'camelCase',
51+
'in': 'camel_case',
52+
}, {
53+
'out': 'camelcase',
54+
'in': 'camelcase',
55+
}, {
56+
'out': 'camelCase',
57+
'in': 'camel_case',
58+
}, {
59+
'out': 'camelCCase',
60+
'in': 'camel_c_case',
61+
}, {
62+
'out': '',
63+
'in': '',
64+
}, {
65+
'out': 'camel3Case',
66+
'in': 'camel3_case',
67+
}, {
68+
'out': 'camelCaseMultipleWords',
69+
'in': 'camel_case_multiple_words',
70+
}, {
71+
'out': 'camelCase_Underscore',
72+
'in': 'camel_case__underscore',
73+
}]
74+
75+
for case in cases:
76+
assert from_underscore(case['in']) == case['out']

0 commit comments

Comments
 (0)