Merge lp:~cjohnston/ubuntu-ci-services-itself/ticket-complete into lp:ubuntu-ci-services-itself
- ticket-complete
- Merge into trunk
Status: | Merged |
---|---|
Approved by: | Chris Johnston |
Approved revision: | 131 |
Merged at revision: | 144 |
Proposed branch: | lp:~cjohnston/ubuntu-ci-services-itself/ticket-complete |
Merge into: | lp:ubuntu-ci-services-itself |
Diff against target: |
470 lines (+220/-33) 9 files modified
docs/components/ticket-system.rst (+10/-1) ticket_system/project/admin.py (+2/-2) ticket_system/project/api.py (+0/-5) ticket_system/project/migrations/0001_initial.py (+1/-3) ticket_system/project/models.py (+0/-1) ticket_system/project/tests.py (+4/-15) ticket_system/ticket/api.py (+37/-0) ticket_system/ticket/models.py (+12/-0) ticket_system/ticket/tests/test_write_api.py (+154/-6) |
To merge this branch: | bzr merge lp:~cjohnston/ubuntu-ci-services-itself/ticket-complete |
Related bugs: |
Reviewer | Review Type | Date Requested | Status |
---|---|---|---|
Andy Doan (community) | Approve | ||
Chris Johnston (community) | Needs Resubmitting | ||
Review via email:
|
Commit message
Add ticket complete API call to the TS
Description of the change
- Update docs
- Remove sourcepackage from BinaryPackage object as it isn't needed
- Add a updateticketsta
What this new url does:
This URL can be called by a get api call. When called it does a few things.
- It takes all binaries that the owner of the ticket added as 'added binaries' and adds them to the 'master list' of binaries.
- It takes all binaries that the owner of the ticket added as 'removed binaries' and removes them from the 'master list' of binaries.
- Marks the ticket workflow step and status as complete.
![](/+icing/build/overlay/assets/skins/sam/images/close.gif)
Andy Doan (doanac) wrote : | # |
![](/+icing/build/overlay/assets/skins/sam/images/close.gif)
Chris Johnston (cjohnston) wrote : | # |
On Wed, Jan 22, 2014 at 11:36 AM, Andy Doan <email address hidden>wrote:
> do we really want this API to be an HTTP GET and not a PATCH?
>
You aren't actually patching anything. I'm not sure though?
![](/+icing/build/overlay/assets/skins/sam/images/close.gif)
Andy Doan (doanac) wrote : | # |
On 01/22/2014 10:54 AM, Chris Johnston wrote:
> On Wed, Jan 22, 2014 at 11:36 AM, Andy Doan <email address hidden>wrote:
>
>> do we really want this API to be an HTTP GET and not a PATCH?
>>
> You aren't actually patching anything. I'm not sure though?
Things are being changed:
219 + queryset.
220 + queryset.status = TicketWorkflowS
221 + queryset.save()
Normally a GET implies a read-only operation. This is doing writes. If
we move to a secure model someday - we could easily forget about this
method.
- 126. By Chris Johnston
-
Update per review
- 127. By Chris Johnston
-
Merge trunk
![](/+icing/build/overlay/assets/skins/sam/images/close.gif)
Chris Johnston (cjohnston) : | # |
- 128. By Chris Johnston
-
Fix tests
![](/+icing/build/overlay/assets/skins/sam/images/close.gif)
Andy Doan (doanac) wrote : | # |
191 + if (
192 + update[
193 + update["status"] == "1000"
194 + ):
you forgot to update to using the new str functions you implemented
24 + curl --dump-header - http://
you need to update the doc for the updated usage
- 129. By Chris Johnston
-
Update per review
![](/+icing/build/overlay/assets/skins/sam/images/close.gif)
Chris Johnston (cjohnston) : | # |
- 130. By Chris Johnston
-
Merge trunk
- 131. By Chris Johnston
-
Merge trunk
![](/+icing/build/overlay/assets/skins/sam/images/close.gif)
Andy Doan (doanac) : | # |
Preview Diff
1 | === modified file 'docs/components/ticket-system.rst' |
2 | --- docs/components/ticket-system.rst 2014-01-24 20:33:49 +0000 |
3 | +++ docs/components/ticket-system.rst 2014-01-24 20:49:45 +0000 |
4 | @@ -204,7 +204,7 @@ |
5 | |
6 | curl --dump-header - http://localhost:8000/api/v1/ticketstatus/ |
7 | |
8 | -*New* |
9 | +*Queued* |
10 | |
11 | :: |
12 | |
13 | @@ -256,6 +256,15 @@ |
14 | |
15 | curl --dump-header - -H "Content-Type: application/json" -X PATCH --data '{"current_workflow_step": "100", "status": "000"}' http://localhost:8000/api/v1/updateticketstatus/1/ |
16 | |
17 | +Mark ticket complete |
18 | +~~~~~~~~~~~~~~~~~~~~ |
19 | + |
20 | +To be used by the lander. The act of marking a ticket complete will modify the master list of binary packages which are tested by adding to the list any of the 'added_binaries' from the ticket and removing any of the 'removed_binaries' from the ticket. |
21 | + |
22 | +:: |
23 | + |
24 | + curl --dump-header - -H "Content-Type: application/json" -X PATCH --data '{"current_workflow_step": "1000", "status": "1000"}' http://localhost:8000/api/v1/updateticketstatus/1/ |
25 | + |
26 | Update subticket status |
27 | ~~~~~~~~~~~~~~~~~~~~~~~ |
28 | |
29 | |
30 | === modified file 'ticket_system/project/admin.py' |
31 | --- ticket_system/project/admin.py 2013-12-20 19:41:18 +0000 |
32 | +++ ticket_system/project/admin.py 2014-01-24 20:49:45 +0000 |
33 | @@ -23,8 +23,8 @@ |
34 | |
35 | |
36 | class BinaryPackageAdmin(admin.ModelAdmin): |
37 | - search_fields = ['name', 'sourcepackage'] |
38 | - list_display = ('name', 'sourcepackage') |
39 | + search_fields = ['name'] |
40 | + list_display = ('name',) |
41 | |
42 | admin.site.register(SourcePackage, SourcePackageAdmin) |
43 | admin.site.register(BinaryPackage, BinaryPackageAdmin) |
44 | |
45 | === modified file 'ticket_system/project/api.py' |
46 | --- ticket_system/project/api.py 2013-12-16 18:52:37 +0000 |
47 | +++ ticket_system/project/api.py 2014-01-24 20:49:45 +0000 |
48 | @@ -13,10 +13,8 @@ |
49 | # You should have received a copy of the GNU Affero General Public License |
50 | # along with this program. If not, see <http://www.gnu.org/licenses/>. |
51 | |
52 | -from tastypie import fields |
53 | from tastypie.authorization import Authorization |
54 | from tastypie.resources import ModelResource |
55 | -from tastypie.constants import ALL |
56 | from project.models import SourcePackage, BinaryPackage |
57 | |
58 | |
59 | @@ -32,8 +30,6 @@ |
60 | |
61 | |
62 | class BinaryPackageResource(ModelResource): |
63 | - sourcepackage = fields.ToOneField(SourcePackageResource, 'sourcepackage', |
64 | - full=True) |
65 | |
66 | class Meta: |
67 | queryset = BinaryPackage.objects.all() |
68 | @@ -41,5 +37,4 @@ |
69 | authorization = Authorization() |
70 | filtering = { |
71 | "name": ('exact', 'iexact', 'startswith', 'istartswith'), |
72 | - "seeded": ALL, |
73 | } |
74 | |
75 | === modified file 'ticket_system/project/migrations/0001_initial.py' |
76 | --- ticket_system/project/migrations/0001_initial.py 2014-01-22 16:33:53 +0000 |
77 | +++ ticket_system/project/migrations/0001_initial.py 2014-01-24 20:49:45 +0000 |
78 | @@ -19,7 +19,6 @@ |
79 | db.create_table('binarypackage', ( |
80 | (u'id', self.gf('django.db.models.fields.AutoField')(primary_key=True)), |
81 | ('name', self.gf('django.db.models.fields.CharField')(max_length=4096)), |
82 | - ('sourcepackage', self.gf('django.db.models.fields.related.ForeignKey')(to=orm['project.SourcePackage'])), |
83 | )) |
84 | db.send_create_signal(u'project', ['BinaryPackage']) |
85 | |
86 | @@ -36,8 +35,7 @@ |
87 | u'project.binarypackage': { |
88 | 'Meta': {'object_name': 'BinaryPackage', 'db_table': "'binarypackage'"}, |
89 | u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), |
90 | - 'name': ('django.db.models.fields.CharField', [], {'max_length': '4096'}), |
91 | - 'sourcepackage': ('django.db.models.fields.related.ForeignKey', [], {'to': u"orm['project.SourcePackage']"}) |
92 | + 'name': ('django.db.models.fields.CharField', [], {'max_length': '4096'}) |
93 | }, |
94 | u'project.sourcepackage': { |
95 | 'Meta': {'object_name': 'SourcePackage', 'db_table': "'sourcepackage'"}, |
96 | |
97 | === modified file 'ticket_system/project/models.py' |
98 | --- ticket_system/project/models.py 2014-01-23 17:31:52 +0000 |
99 | +++ ticket_system/project/models.py 2014-01-24 20:49:45 +0000 |
100 | @@ -31,7 +31,6 @@ |
101 | db_table = "binarypackage" |
102 | |
103 | name = models.CharField(max_length=4096) |
104 | - sourcepackage = models.ForeignKey("SourcePackage") |
105 | |
106 | def __unicode__(self): |
107 | return self.name |
108 | |
109 | === modified file 'ticket_system/project/tests.py' |
110 | --- ticket_system/project/tests.py 2014-01-24 15:10:17 +0000 |
111 | +++ ticket_system/project/tests.py 2014-01-24 20:49:45 +0000 |
112 | @@ -43,8 +43,7 @@ |
113 | |
114 | def setUp(self): |
115 | self.sourcepackage = sourcepackage_recipe.make() |
116 | - self.binarypackage = mommy.make('BinaryPackage', |
117 | - sourcepackage=self.sourcepackage) |
118 | + self.binarypackage = mommy.make('BinaryPackage') |
119 | |
120 | def test_creating_binarypackage(self): |
121 | binarypackage_in_database = BinaryPackage.objects.all() |
122 | @@ -122,25 +121,15 @@ |
123 | def setUp(self): |
124 | super(BinaryPackageResourceTest, self).setUp('/api/v1') |
125 | self.sourcepackage = sourcepackage_recipe.make() |
126 | - self.binarypackage = mommy.make('BinaryPackage', |
127 | - sourcepackage=self.sourcepackage) |
128 | + self.binarypackage = mommy.make('BinaryPackage') |
129 | self.detail_url = 'binarypackage/{0}/'.format(self.binarypackage.pk) |
130 | - self.post_binarypackage_data = { |
131 | - 'name': 'ubuntu-ci', |
132 | - 'sourcepackage': '/api/v1/sourcepackage/{0}/'.format( |
133 | - self.sourcepackage.pk) |
134 | - } |
135 | + self.post_binarypackage_data = {'name': 'ubuntu-ci'} |
136 | |
137 | def test_get_binarypackage_list_json(self): |
138 | obj = self.getResource('binarypackage/') |
139 | self.assertEqual(obj['objects'][0], { |
140 | u'id': self.binarypackage.pk, |
141 | u'name': unicode(self.binarypackage.name), |
142 | - u'sourcepackage': { |
143 | - u'id': self.sourcepackage.pk, |
144 | - u'name': unicode(self.sourcepackage.name), |
145 | - u'resource_uri': u'/api/v1/sourcepackage/{0}/'.format( |
146 | - self.sourcepackage.pk)}, |
147 | u'resource_uri': u'/api/v1/binarypackage/{0}/'.format( |
148 | self.binarypackage.pk) |
149 | }) |
150 | @@ -149,7 +138,7 @@ |
151 | obj = self.getResource(self.detail_url) |
152 | |
153 | # We use ``assertKeys`` here to just verify the keys, not all the data. |
154 | - self.assertKeys(obj, ['id', 'name', 'resource_uri', 'sourcepackage']) |
155 | + self.assertKeys(obj, ['id', 'name', 'resource_uri']) |
156 | self.assertEqual(obj['name'], self.binarypackage.name) |
157 | |
158 | def test_post_binarypackage(self): |
159 | |
160 | === modified file 'ticket_system/ticket/api.py' |
161 | --- ticket_system/ticket/api.py 2014-01-24 16:39:35 +0000 |
162 | +++ ticket_system/ticket/api.py 2014-01-24 20:49:45 +0000 |
163 | @@ -13,6 +13,10 @@ |
164 | # You should have received a copy of the GNU Affero General Public License |
165 | # along with this program. If not, see <http://www.gnu.org/licenses/>. |
166 | |
167 | +import json |
168 | + |
169 | +from django.shortcuts import get_object_or_404 |
170 | + |
171 | from tastypie import fields |
172 | from tastypie.constants import ALL |
173 | from tastypie.authorization import Authorization |
174 | @@ -23,6 +27,7 @@ |
175 | TicketWorkflowStep, TicketWorkflowStepStatus, |
176 | get_enum_title) |
177 | |
178 | +from project.models import BinaryPackage |
179 | from project.api import SourcePackageResource |
180 | |
181 | |
182 | @@ -161,6 +166,38 @@ |
183 | "id": ('exact'), |
184 | } |
185 | |
186 | + def patch_detail(self, request, **kwargs): |
187 | + update = json.loads(request.body) |
188 | + if ( |
189 | + update["current_workflow_step"] == str( |
190 | + TicketWorkflowStep.COMPLETED.value) and |
191 | + update["status"] == str(TicketWorkflowStepStatus.COMPLETED.value) |
192 | + ): |
193 | + queryset = get_object_or_404(Ticket, pk=kwargs['pk']) |
194 | + added_binaries = queryset.added_binaries |
195 | + if added_binaries is not None: |
196 | + added_binaries = added_binaries.split(",") |
197 | + else: |
198 | + added_binaries = [] |
199 | + removed_binaries = queryset.removed_binaries |
200 | + if removed_binaries is not None: |
201 | + removed_binaries = removed_binaries.split(",") |
202 | + else: |
203 | + removed_binaries = [] |
204 | + for binary in added_binaries: |
205 | + #Use get or create incase the binary already exists in the list |
206 | + BinaryPackage.objects.get_or_create(name=binary) |
207 | + for binary in removed_binaries: |
208 | + try: |
209 | + # If the binary specified exists in the list, delete it |
210 | + bp = BinaryPackage.objects.get(name=binary) |
211 | + bp.delete() |
212 | + except BinaryPackage.DoesNotExist: |
213 | + # If the binary specified does not exist, move on |
214 | + pass |
215 | + return super(TicketUpdateStatusResource, self).patch_detail(request, |
216 | + **kwargs) |
217 | + |
218 | |
219 | class TicketStatusResource(TicketTranslatedResource): |
220 | |
221 | |
222 | === modified file 'ticket_system/ticket/models.py' |
223 | --- ticket_system/ticket/models.py 2014-01-24 20:33:49 +0000 |
224 | +++ ticket_system/ticket/models.py 2014-01-24 20:49:45 +0000 |
225 | @@ -31,6 +31,9 @@ |
226 | PKG_BUILDING = Item(200, "Package building") |
227 | COMPLETED = Item(1000, "Completed") |
228 | |
229 | + def __str__(self): |
230 | + return str(self.value) |
231 | + |
232 | |
233 | class SubTicketWorkflowStepStatus(DBEnumeratedType): |
234 | |
235 | @@ -40,6 +43,9 @@ |
236 | PKG_BUILDING_COMPLETED = Item(230, "Completed") |
237 | PKG_BUILDING_FAILED = Item(240, "Failed") |
238 | |
239 | + def __str__(self): |
240 | + return str(self.value) |
241 | + |
242 | |
243 | class TicketWorkflowStep(DBEnumeratedType): |
244 | |
245 | @@ -52,6 +58,9 @@ |
246 | FAILED = Item(999, "Failed") |
247 | COMPLETED = Item(1000, "Completed") |
248 | |
249 | + def __str__(self): |
250 | + return str(self.value) |
251 | + |
252 | |
253 | class TicketWorkflowStepStatus(DBEnumeratedType): |
254 | |
255 | @@ -74,6 +83,9 @@ |
256 | PKG_PUBLISHING_FAILED = Item(540, "Package Publishing Failed") |
257 | COMPLETED = Item(1000, "Completed") |
258 | |
259 | + def __str__(self): |
260 | + return str(self.value) |
261 | + |
262 | |
263 | def _choices(enum): |
264 | return [ |
265 | |
266 | === modified file 'ticket_system/ticket/tests/test_write_api.py' |
267 | --- ticket_system/ticket/tests/test_write_api.py 2014-01-24 17:44:14 +0000 |
268 | +++ ticket_system/ticket/tests/test_write_api.py 2014-01-24 20:49:45 +0000 |
269 | @@ -21,6 +21,11 @@ |
270 | SubTicketWorkflowStep, SubTicketWorkflowStepStatus, |
271 | Ticket, TicketWorkflowStep, SubTicketArtifact, |
272 | TicketWorkflowStepStatus) |
273 | +from project.models import BinaryPackage |
274 | + |
275 | + |
276 | +def create_ticket(added=None, removed=None): |
277 | + return mommy.make('Ticket', removed_binaries=removed, added_binaries=added) |
278 | |
279 | |
280 | sourcepackage_recipe = Recipe(SourcePackage, name=seq('foobar')) |
281 | @@ -30,7 +35,7 @@ |
282 | |
283 | def setUp(self): |
284 | super(APICreateTicketResourceTest, self).setUp('/api/v1') |
285 | - self.ticket = mommy.make('Ticket') |
286 | + self.ticket = create_ticket() |
287 | self.resource = 'ticket/' |
288 | self.detail_url = self.resource + '{0}/'.format(self.ticket.pk) |
289 | self.post_ticket_data = { |
290 | @@ -264,21 +269,38 @@ |
291 | |
292 | def setUp(self): |
293 | super(APIUpdateTicketStatuses, self).setUp('/api/v1') |
294 | - self.ticket = mommy.make('Ticket') |
295 | + mommy.make('BinaryPackage', name='binary3') |
296 | + mommy.make('BinaryPackage', name='binary4') |
297 | + mommy.make('BinaryPackage', name='binary5') |
298 | + self.ticket = create_ticket(added='binary1,binary2,binary6', |
299 | + removed='binary3,binary4') |
300 | self.ticket_detail_url = 'updateticketstatus/{0}/'.format( |
301 | self.ticket.pk) |
302 | |
303 | def test_patch_ticket_status(self): |
304 | new_data = { |
305 | - 'current_workflow_step': int(TicketWorkflowStep.IMAGE_BUILDING), |
306 | - 'status': int(TicketWorkflowStepStatus.IMAGE_BUILDING_COMPLETED), |
307 | + 'current_workflow_step': str( |
308 | + TicketWorkflowStep.IMAGE_BUILDING.value), |
309 | + 'status': str( |
310 | + TicketWorkflowStepStatus.IMAGE_BUILDING_COMPLETED.value), |
311 | } |
312 | self.assertEqual(Ticket.objects.count(), 1) |
313 | - self.patch('/api/v1/' + self.ticket_detail_url, |
314 | - new_data) |
315 | + self.assertEqual(BinaryPackage.objects.count(), 3) |
316 | + binaries = BinaryPackage.objects.all() |
317 | + self.assertQuerysetEqual(binaries, |
318 | + ["<BinaryPackage: binary3>", |
319 | + "<BinaryPackage: binary4>", |
320 | + "<BinaryPackage: binary5>"], ordered=False) |
321 | + self.patch('/api/v1/' + self.ticket_detail_url, new_data) |
322 | # Make sure the count hasn't changed & we did an update. |
323 | self.assertEqual(Ticket.objects.count(), 1) |
324 | # Check for updated data. |
325 | + self.assertEqual(BinaryPackage.objects.count(), 3) |
326 | + binaries = BinaryPackage.objects.all() |
327 | + self.assertQuerysetEqual(binaries, |
328 | + ["<BinaryPackage: binary3>", |
329 | + "<BinaryPackage: binary4>", |
330 | + "<BinaryPackage: binary5>"], ordered=False) |
331 | self.assertEqual(Ticket.objects.get( |
332 | pk=self.ticket.pk).current_workflow_step, |
333 | int(TicketWorkflowStep.IMAGE_BUILDING)) |
334 | @@ -286,6 +308,128 @@ |
335 | Ticket.objects.get(pk=self.ticket.pk).status, |
336 | int(TicketWorkflowStepStatus.IMAGE_BUILDING_COMPLETED)) |
337 | |
338 | + def test_update_ticket_status_complete(self): |
339 | + new_data = { |
340 | + "current_workflow_step": str(TicketWorkflowStep.COMPLETED.value), |
341 | + "status": str(TicketWorkflowStepStatus.COMPLETED.value), |
342 | + } |
343 | + self.assertEqual(Ticket.objects.count(), 1) |
344 | + self.assertEqual(BinaryPackage.objects.count(), 3) |
345 | + binaries = BinaryPackage.objects.all() |
346 | + self.assertQuerysetEqual(binaries, |
347 | + ["<BinaryPackage: binary3>", |
348 | + "<BinaryPackage: binary4>", |
349 | + "<BinaryPackage: binary5>"], ordered=False) |
350 | + self.assertEqual(Ticket.objects.get( |
351 | + pk=self.ticket.pk).current_workflow_step, |
352 | + self.ticket.current_workflow_step) |
353 | + self.assertEqual(Ticket.objects.get( |
354 | + pk=self.ticket.pk).status, |
355 | + self.ticket.status) |
356 | + self.patch('/api/v1/' + self.ticket_detail_url, new_data) |
357 | + self.assertEqual(Ticket.objects.count(), 1) |
358 | + self.assertEqual(BinaryPackage.objects.count(), 4) |
359 | + binaries = BinaryPackage.objects.all() |
360 | + self.assertQuerysetEqual(binaries, |
361 | + ["<BinaryPackage: binary1>", |
362 | + "<BinaryPackage: binary2>", |
363 | + "<BinaryPackage: binary5>", |
364 | + "<BinaryPackage: binary6>"], ordered=False) |
365 | + self.assertEqual(Ticket.objects.get( |
366 | + pk=self.ticket.pk).current_workflow_step, |
367 | + int(TicketWorkflowStep.COMPLETED)) |
368 | + self.assertEqual(Ticket.objects.get( |
369 | + pk=self.ticket.pk).status, |
370 | + int(TicketWorkflowStepStatus.COMPLETED)) |
371 | + |
372 | + def test_try_adding_binary_already_in_list(self): |
373 | + """ |
374 | + Test what happens when a ticket attempts to add a binary to the master |
375 | + list that is already in the master list |
376 | + """ |
377 | + new_data = { |
378 | + "current_workflow_step": str(TicketWorkflowStep.COMPLETED.value), |
379 | + "status": str(TicketWorkflowStepStatus.COMPLETED.value), |
380 | + } |
381 | + self.ticket_2 = create_ticket(added='binary1,binary2,binary3') |
382 | + self.assertEqual(Ticket.objects.count(), 2) |
383 | + self.assertEqual(BinaryPackage.objects.count(), 3) |
384 | + binaries = BinaryPackage.objects.all() |
385 | + self.assertQuerysetEqual(binaries, |
386 | + ["<BinaryPackage: binary3>", |
387 | + "<BinaryPackage: binary4>", |
388 | + "<BinaryPackage: binary5>"], ordered=False) |
389 | + self.client.patch('/api/v1/updateticketstatus/{0}/'.format( |
390 | + self.ticket_2.pk), data=new_data) |
391 | + self.assertEqual(BinaryPackage.objects.count(), 5) |
392 | + binaries = BinaryPackage.objects.all() |
393 | + self.assertQuerysetEqual(binaries, |
394 | + ["<BinaryPackage: binary1>", |
395 | + "<BinaryPackage: binary2>", |
396 | + "<BinaryPackage: binary3>", |
397 | + "<BinaryPackage: binary4>", |
398 | + "<BinaryPackage: binary5>"], ordered=False) |
399 | + |
400 | + def test_try_removing_binary_not_in_list(self): |
401 | + """ |
402 | + Test what happens when a ticket attempts to remove a binary from the |
403 | + master list when it isn't in the master list |
404 | + """ |
405 | + new_data = { |
406 | + "current_workflow_step": str(TicketWorkflowStep.COMPLETED.value), |
407 | + "status": str(TicketWorkflowStepStatus.COMPLETED.value), |
408 | + } |
409 | + self.ticket_2 = create_ticket(removed='binary2,binary3') |
410 | + self.assertEqual(Ticket.objects.count(), 2) |
411 | + self.assertEqual(BinaryPackage.objects.count(), 3) |
412 | + binaries = BinaryPackage.objects.all() |
413 | + self.assertQuerysetEqual(binaries, |
414 | + ["<BinaryPackage: binary3>", |
415 | + "<BinaryPackage: binary4>", |
416 | + "<BinaryPackage: binary5>"], ordered=False) |
417 | + self.client.patch('/api/v1/updateticketstatus/{0}/'.format( |
418 | + self.ticket_2.pk), data=new_data) |
419 | + binaries = BinaryPackage.objects.all() |
420 | + self.assertEqual(BinaryPackage.objects.count(), 2) |
421 | + self.assertQuerysetEqual(binaries, |
422 | + ["<BinaryPackage: binary4>", |
423 | + "<BinaryPackage: binary5>"], ordered=False) |
424 | + |
425 | + def test_update_ticket_status_complete_404(self): |
426 | + """ |
427 | + Test trying to complete the status of a ticket that doesn't exist |
428 | + """ |
429 | + new_data = { |
430 | + "current_workflow_step": str(TicketWorkflowStep.COMPLETED.value), |
431 | + "status": str(TicketWorkflowStepStatus.COMPLETED.value), |
432 | + } |
433 | + self.assertEqual(Ticket.objects.count(), 1) |
434 | + self.assertEqual(BinaryPackage.objects.count(), 3) |
435 | + binaries = BinaryPackage.objects.all() |
436 | + self.assertQuerysetEqual(binaries, |
437 | + ["<BinaryPackage: binary3>", |
438 | + "<BinaryPackage: binary4>", |
439 | + "<BinaryPackage: binary5>"], ordered=False) |
440 | + self.assertEqual(Ticket.objects.get( |
441 | + pk=self.ticket.pk).current_workflow_step, |
442 | + self.ticket.current_workflow_step) |
443 | + self.assertEqual(Ticket.objects.get( |
444 | + pk=self.ticket.pk).status, |
445 | + self.ticket.status) |
446 | + resp = self.client.patch('updateticketstatus/17394/', data=new_data) |
447 | + self.assertEqual(Ticket.objects.count(), 1) |
448 | + self.assertEqual(BinaryPackage.objects.count(), 3) |
449 | + binaries = BinaryPackage.objects.all() |
450 | + self.assertQuerysetEqual(binaries, |
451 | + ["<BinaryPackage: binary3>", |
452 | + "<BinaryPackage: binary4>", |
453 | + "<BinaryPackage: binary5>"], ordered=False) |
454 | + self.assertEqual(resp.status_code, 404) |
455 | + |
456 | + def test_delete_ticket_not_allowed(self): |
457 | + resp = self.delete(resource=self.ticket_detail_url) |
458 | + self.assertHttpMethodNotAllowed(resp) |
459 | + |
460 | |
461 | class APIUpdateSubTicketStatuses(TastypieTestCase): |
462 | |
463 | @@ -316,3 +460,7 @@ |
464 | int(SubTicketWorkflowStep.PKG_BUILDING)) |
465 | self.assertEqual(SubTicket.objects.get(pk=self.subticket.pk).status, |
466 | int(SubTicketWorkflowStepStatus.PKG_BUILDING_WAITING)) |
467 | + |
468 | + def test_delete_subticket_not_allowed(self): |
469 | + resp = self.delete(resource=self.subticket_detail_url) |
470 | + self.assertHttpMethodNotAllowed(resp) |
do we really want this API to be an HTTP GET and not a PATCH?