Skip to content

Commit 09aceca

Browse files
committed
Undeleted update project function, added path validation, fixed body validation.
1 parent 21fb454 commit 09aceca

File tree

5 files changed

+326
-0
lines changed

5 files changed

+326
-0
lines changed

dynatademand/api.py

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@
77

88
REQUEST_BODY_SCHEMAS = [
99
'create_project',
10+
"update_project",
1011
'update_line_item',
1112
]
1213

@@ -20,6 +21,7 @@
2021
'get_project',
2122
'get_project_detailed_report',
2223
'update_line_item',
24+
'update_project'
2325
]
2426

2527
REQUEST_QUERY_SCHEMAS = [
@@ -219,6 +221,21 @@ def get_projects(self):
219221
# No schemas to validate.
220222
return self._api_get('/projects')
221223

224+
def update_project(self, project_id, update_data):
225+
# Validate path and request body.
226+
self._validate_object('request_path', 'update_project', {
227+
'extProjectId': '{}'.format(project_id)
228+
})
229+
self._validate_object('request_body', 'update_project', update_data)
230+
response_data = self._api_post('/projects/{}'.format(project_id), update_data)
231+
if response_data.get('status').get('message') != 'success':
232+
raise DemandAPIError(
233+
"Could not update project. Demand API responded with: {}".format(
234+
response_data
235+
)
236+
)
237+
return response_data
238+
222239
def get_project_detailed_report(self, project_id):
223240
# Validate path
224241
self._validate_object('request_path', 'get_project_detailed_report', {
Lines changed: 180 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,180 @@
1+
{
2+
"type": "object",
3+
"title": "Update Project",
4+
"properties": {
5+
"title": {
6+
"type": "string"
7+
},
8+
"notificationEmails": {
9+
"type": "array",
10+
"items": {
11+
"type": "string"
12+
}
13+
},
14+
"devices": {
15+
"type": "array",
16+
"items": {
17+
"type": "string"
18+
}
19+
},
20+
"category": {
21+
"type": "object",
22+
"properties": {
23+
"surveyTopic": {
24+
"type": "array",
25+
"items": {
26+
"type": "string"
27+
}
28+
}
29+
}
30+
},
31+
"lineItems": {
32+
"type": "array",
33+
"items": {
34+
"type": "object",
35+
"required": [
36+
"extLineItemId"
37+
],
38+
"title": "Update Line Item",
39+
"properties": {
40+
"extLineItemId": {
41+
"type": "string"
42+
},
43+
"title": {
44+
"type": "string"
45+
},
46+
"countryISOCode": {
47+
"type": "string"
48+
},
49+
"languageISOCode": {
50+
"type": "string"
51+
},
52+
"surveyURL": {
53+
"type": "string"
54+
},
55+
"surveyTestURL": {
56+
"type": "string"
57+
},
58+
"indicativeIncidence": {
59+
"type": "integer"
60+
},
61+
"daysInField": {
62+
"type": "integer"
63+
},
64+
"lengthOfInterview": {
65+
"type": "integer"
66+
},
67+
"deliveryType": {
68+
"type": "string"
69+
},
70+
"sources": {
71+
"type": "array",
72+
"items": {
73+
"type": "object",
74+
"properties": {
75+
"id": {
76+
"type": "integer"
77+
}
78+
}
79+
}
80+
},
81+
"targets": {
82+
"type": "array",
83+
"items": {
84+
"type": "object",
85+
"properties": {
86+
"count": {
87+
"type": "integer"
88+
},
89+
"dailyLimit": {
90+
"type": "integer"
91+
},
92+
"type": {
93+
"type": "string",
94+
"enum": [
95+
"COMPLETE"
96+
]
97+
}
98+
}
99+
}
100+
},
101+
"quotaPlan": {
102+
"type": "object",
103+
"properties": {
104+
"filters": {
105+
"type": "array",
106+
"items": {
107+
"type": "object",
108+
"properties": {
109+
"attributeId": {
110+
"type": "string"
111+
},
112+
"options": {
113+
"type": "array",
114+
"items": {
115+
"type": "string"
116+
}
117+
}
118+
}
119+
}
120+
},
121+
"quotaGroups": {
122+
"type": "array",
123+
"items": {
124+
"type": "object",
125+
"properties": {
126+
"name": {
127+
"type": "string"
128+
},
129+
"quotaCells": {
130+
"type": "array",
131+
"items": {
132+
"type": "object",
133+
"properties": {
134+
"quotaNodes": {
135+
"type": "array",
136+
"items": {
137+
"type": "object",
138+
"properties": {
139+
"attributeId": {
140+
"type": "string"
141+
},
142+
"options": {
143+
"type": "array",
144+
"items": {
145+
"type": "string"
146+
}
147+
}
148+
}
149+
}
150+
},
151+
"count": {
152+
"type": "integer"
153+
}
154+
}
155+
}
156+
}
157+
}
158+
}
159+
}
160+
}
161+
}
162+
}
163+
}
164+
},
165+
"exclusions": {
166+
"type": "object",
167+
"properties": {
168+
"type": {
169+
"type": "string"
170+
},
171+
"list": {
172+
"type": "array",
173+
"items": {
174+
"type": "object"
175+
}
176+
}
177+
}
178+
}
179+
}
180+
}
Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
{
2+
"type": "object",
3+
"properties": {
4+
"extProjectId": {
5+
"type": "string"
6+
}
7+
},
8+
"required": [
9+
"extProjectId"
10+
]
11+
}
Lines changed: 89 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,89 @@
1+
{
2+
"title": "Test Survey",
3+
"jobNumber": "PO-1234",
4+
"notificationEmails": [
5+
"api-test@dynata.com"
6+
],
7+
"devices": [
8+
"mobile",
9+
"desktop",
10+
"tablet"
11+
],
12+
"category": {
13+
"surveyTopic": [
14+
"AUTOMOTIVE",
15+
"BUSINESS"
16+
]
17+
},
18+
"lineItems": [
19+
{
20+
"extLineItemId": "lineItem001",
21+
"title": "US College",
22+
"countryISOCode": "US",
23+
"languageISOCode": "en",
24+
"surveyURL": "www.mysurvey.com/live/survey?pid=<#DubKnowledge[1500/Entity id]>&k2=<#Project[Secure Key 2]>&psid=<#IdParameter[Value]>",
25+
"surveyTestURL": "www.mysurvey.com/test/survey?pid=<#DubKnowledge[1500/Entity id]>&k2=<#Project[Secure Key 2]>&psid=<#IdParameter[Value]>",
26+
"indicativeIncidence": 20,
27+
"daysInField": 20,
28+
"lengthOfInterview": 10,
29+
"deliveryType": "BALANCED",
30+
"sources": [
31+
{
32+
"id": 100
33+
}
34+
],
35+
"targets": [
36+
{
37+
"count": 160,
38+
"dailyLimit": 0,
39+
"type": "COMPLETE"
40+
}
41+
],
42+
"quotaPlan": {
43+
"filters": [
44+
{
45+
"attributeId": "61961",
46+
"options": [
47+
"3",
48+
"4"
49+
],
50+
"operator": "include"
51+
}
52+
],
53+
"quotaGroups": [
54+
{
55+
"name": "Gender Distribution",
56+
"quotaCells": [
57+
{
58+
"quotaNodes": [
59+
{
60+
"attributeId": "11",
61+
"options": [
62+
"1"
63+
]
64+
}
65+
],
66+
"count": 100
67+
},
68+
{
69+
"quotaNodes": [
70+
{
71+
"attributeId": "11",
72+
"options": [
73+
"2"
74+
]
75+
}
76+
],
77+
"count": 60
78+
}
79+
]
80+
}
81+
]
82+
}
83+
}
84+
],
85+
"exclusions": {
86+
"type": "PROJECT",
87+
"list": []
88+
}
89+
}

tests/test_projects.py

Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@
66
import responses
77

88
from dynatademand.api import DemandAPIClient
9+
from dynatademand.errors import DemandAPIError
910

1011
BASE_HOST = "http://test-url.example"
1112

@@ -58,3 +59,31 @@ def test_create_project(self):
5859
status=200)
5960
self.api.create_project(new_project_data)
6061
self.assertEqual(len(responses.calls), 1)
62+
63+
@responses.activate
64+
def test_update_project(self):
65+
# Tests creating a project. This also tests validating the project data as part of `api.create_project`.
66+
with open('./tests/test_files/update_project.json', 'r') as update_project_file:
67+
update_project_data = json.load(update_project_file)
68+
69+
# Success response
70+
responses.add(
71+
responses.POST,
72+
'{}/sample/v1/projects/24'.format(BASE_HOST),
73+
json={'status': {'message': 'success'}},
74+
status=200)
75+
# Error message included
76+
responses.add(
77+
responses.POST,
78+
'{}/sample/v1/projects/24'.format(BASE_HOST),
79+
json={'status': {'message': 'error'}},
80+
status=200)
81+
82+
# Test successful response.
83+
self.api.update_project(24, update_project_data)
84+
self.assertEqual(len(responses.calls), 1)
85+
86+
# Test response with error included.
87+
with self.assertRaises(DemandAPIError):
88+
self.api.update_project(24, update_project_data)
89+
self.assertEqual(len(responses.calls), 2)

0 commit comments

Comments
 (0)