1 | # -*- coding: utf-8 -*- |
||
2 | # pylint: disable=attribute-defined-outside-init |
||
3 | |||
4 | from xmlrpc.client import Fault, ProtocolError |
||
5 | |||
6 | from django.contrib.auth.models import Permission |
||
7 | from tcms_api import xmlrpc |
||
8 | |||
9 | from tcms.management.models import Priority |
||
10 | from tcms.rpc.tests.utils import APITestCase |
||
11 | from tcms.testcases.models import Category, TestCase, TestCaseStatus |
||
12 | from tcms.tests import remove_perm_from_user |
||
13 | from tcms.tests.factories import (CategoryFactory, ComponentFactory, |
||
14 | ProductFactory, TagFactory, TestCaseFactory, |
||
15 | TestPlanFactory, UserFactory, VersionFactory) |
||
16 | |||
17 | |||
18 | class TestNotificationRemoveCC(APITestCase): |
||
19 | """ Tests the XML-RPC testcase.notication_remove_cc method """ |
||
20 | |||
21 | def _fixture_setup(self): |
||
22 | super(TestNotificationRemoveCC, self)._fixture_setup() |
||
23 | |||
24 | self.default_cc = '[email protected]' |
||
25 | self.testcase = TestCaseFactory() |
||
26 | self.testcase.emailing.add_cc(self.default_cc) |
||
27 | |||
28 | def tearDown(self): |
||
29 | super(TestNotificationRemoveCC, self).tearDown() |
||
30 | self.rpc_client.Auth.logout() |
||
31 | |||
32 | def test_remove_existing_cc(self): |
||
33 | # initially testcase has the default CC listed |
||
34 | # and we issue XMLRPC request to remove the cc |
||
35 | self.rpc_client.TestCase.remove_notification_cc(self.testcase.pk, [self.default_cc]) |
||
36 | |||
37 | # now verify that the CC email has been removed |
||
38 | self.testcase.emailing.refresh_from_db() |
||
39 | self.assertEqual([], self.testcase.emailing.get_cc_list()) |
||
40 | |||
41 | |||
42 | class TestFilterCases(APITestCase): |
||
43 | |||
44 | def _fixture_setup(self): |
||
45 | super(TestFilterCases, self)._fixture_setup() |
||
46 | |||
47 | self.tester = UserFactory(username='great tester') |
||
48 | self.product = ProductFactory(name='StarCraft') |
||
49 | self.version = VersionFactory(value='0.1', product=self.product) |
||
50 | self.plan = TestPlanFactory(name='Test product.get_cases', |
||
51 | author=self.tester, |
||
52 | product=self.product, |
||
53 | product_version=self.version) |
||
54 | self.case_category = CategoryFactory(product=self.product) |
||
55 | self.cases_count = 10 |
||
56 | self.cases = [] |
||
57 | for _ in range(self.cases_count): |
||
58 | test_case = TestCaseFactory( |
||
59 | category=self.case_category, |
||
60 | author=self.tester, |
||
61 | reviewer=self.tester, |
||
62 | default_tester=None, |
||
63 | plan=[self.plan]) |
||
64 | self.cases.append(test_case) |
||
65 | |||
66 | def test_filter_by_product_id(self): |
||
67 | cases = self.rpc_client.TestCase.filter({'category__product': self.product.pk}) |
||
68 | self.assertIsNotNone(cases) |
||
69 | self.assertEqual(len(cases), self.cases_count) |
||
70 | |||
71 | |||
72 | class TestUpdate(APITestCase): |
||
73 | non_existing_username = 'FakeUsername' |
||
74 | non_existing_user_id = 999 |
||
75 | non_existing_email = '[email protected]' |
||
76 | |||
77 | def _fixture_setup(self): |
||
78 | super()._fixture_setup() |
||
79 | |||
80 | self.testcase = TestCaseFactory(summary='Sanity test case', |
||
81 | text='Given-When-Then', |
||
82 | default_tester=None) |
||
83 | self.new_author = UserFactory() |
||
84 | |||
85 | def test_update_text_and_product(self): |
||
86 | author_pk = self.testcase.author.pk |
||
87 | self.assertEqual('Sanity test case', self.testcase.summary) |
||
88 | self.assertEqual('Given-When-Then', self.testcase.text) |
||
89 | |||
90 | # update the test case |
||
91 | updated = self.rpc_client.TestCase.update( # pylint: disable=objects-update-used |
||
92 | self.testcase.pk, |
||
93 | { |
||
94 | 'summary': 'This was updated', |
||
95 | 'text': 'new TC text', |
||
96 | } |
||
97 | ) |
||
98 | |||
99 | self.testcase.refresh_from_db() |
||
100 | |||
101 | self.assertEqual(updated['id'], self.testcase.pk) |
||
102 | self.assertEqual('This was updated', self.testcase.summary) |
||
103 | self.assertEqual('new TC text', self.testcase.text) |
||
104 | # FK for author not passed above. Make sure it didn't change! |
||
105 | self.assertEqual(author_pk, self.testcase.author.pk) |
||
106 | |||
107 | def test_update_author_issue_630(self): |
||
108 | self.assertNotEqual(self.new_author, self.testcase.author) |
||
109 | |||
110 | # update the test case |
||
111 | updated = self.rpc_client.TestCase.update( # pylint: disable=objects-update-used |
||
112 | self.testcase.pk, |
||
113 | { |
||
114 | 'author': self.new_author.pk, |
||
115 | } |
||
116 | ) |
||
117 | |||
118 | self.testcase.refresh_from_db() |
||
119 | self.assertEqual(self.new_author, self.testcase.author) |
||
120 | self.assertEqual(self.new_author.pk, updated['author_id']) |
||
121 | |||
122 | def test_update_author_should_fail_for_non_existing_user_id(self): |
||
123 | initial_author_id = self.testcase.author.pk |
||
124 | with self.assertRaises(Fault): |
||
125 | self.rpc_client.TestCase.update( # pylint: disable=objects-update-used |
||
126 | self.testcase.pk, |
||
127 | { |
||
128 | 'author': self.non_existing_user_id, |
||
129 | } |
||
130 | ) |
||
131 | |||
132 | self.testcase.refresh_from_db() |
||
133 | self.assertEqual(initial_author_id, self.testcase.author.pk) |
||
134 | |||
135 | def test_update_author_accepts_username(self): |
||
136 | self.assertNotEqual(self.new_author, self.testcase.author) |
||
137 | |||
138 | # update the test case |
||
139 | updated = self.rpc_client.TestCase.update( # pylint: disable=objects-update-used |
||
140 | self.testcase.pk, |
||
141 | { |
||
142 | 'author': self.new_author.username, |
||
143 | } |
||
144 | ) |
||
145 | |||
146 | self.testcase.refresh_from_db() |
||
147 | self.assertEqual(self.new_author, self.testcase.author) |
||
148 | self.assertEqual(self.new_author.pk, updated['author_id']) |
||
149 | |||
150 | def test_update_author_should_fail_for_non_existing_username(self): |
||
151 | initial_author_username = self.testcase.author.username |
||
152 | with self.assertRaises(Fault): |
||
153 | self.rpc_client.TestCase.update( # pylint: disable=objects-update-used |
||
154 | self.testcase.pk, |
||
155 | { |
||
156 | 'author': self.non_existing_username, |
||
157 | } |
||
158 | ) |
||
159 | |||
160 | self.testcase.refresh_from_db() |
||
161 | self.assertEqual(initial_author_username, self.testcase.author.username) |
||
162 | |||
163 | def test_update_author_accepts_email(self): |
||
164 | self.assertNotEqual(self.new_author, self.testcase.author) |
||
165 | |||
166 | # update the test case |
||
167 | updated = self.rpc_client.TestCase.update( # pylint: disable=objects-update-used |
||
168 | self.testcase.pk, |
||
169 | { |
||
170 | 'author': self.new_author.email, |
||
171 | } |
||
172 | ) |
||
173 | |||
174 | self.testcase.refresh_from_db() |
||
175 | self.assertEqual(self.new_author, self.testcase.author) |
||
176 | self.assertEqual(self.new_author.pk, updated['author_id']) |
||
177 | |||
178 | def test_update_author_should_fail_for_non_existing_email(self): |
||
179 | initial_author_email = self.testcase.author.email |
||
180 | with self.assertRaises(Fault): |
||
181 | self.rpc_client.TestCase.update( # pylint: disable=objects-update-used |
||
182 | self.testcase.pk, |
||
183 | { |
||
184 | 'author': self.non_existing_email, |
||
185 | } |
||
186 | ) |
||
187 | |||
188 | self.testcase.refresh_from_db() |
||
189 | self.assertEqual(initial_author_email, self.testcase.author.email) |
||
190 | |||
191 | def test_update_priority_issue_1318(self): |
||
192 | expected_priority = Priority.objects.exclude(pk=self.testcase.priority.pk).first() |
||
193 | |||
194 | self.assertNotEqual(expected_priority.pk, self.testcase.priority.pk) |
||
195 | self.assertEqual('Sanity test case', self.testcase.summary) |
||
196 | self.assertEqual('Given-When-Then', self.testcase.text) |
||
197 | |||
198 | # update the test case |
||
199 | self.rpc_client.TestCase.update( # pylint: disable=objects-update-used |
||
200 | self.testcase.pk, |
||
201 | { |
||
202 | 'priority': expected_priority.pk, |
||
203 | } |
||
204 | ) |
||
205 | |||
206 | self.testcase.refresh_from_db() |
||
207 | |||
208 | # priority has changed |
||
209 | self.assertEqual(expected_priority.pk, self.testcase.priority.pk) |
||
210 | |||
211 | # but nothing else changed, issue #1318 |
||
212 | self.assertEqual('Sanity test case', self.testcase.summary) |
||
213 | self.assertEqual('Given-When-Then', self.testcase.text) |
||
214 | |||
215 | def test_update_default_tester_accepts_user_id(self): |
||
216 | self.assertIsNone(self.testcase.default_tester) |
||
217 | |||
218 | self.rpc_client.TestCase.update( # pylint: disable=objects-update-used |
||
219 | self.testcase.pk, |
||
220 | { |
||
221 | 'default_tester': self.new_author.pk, |
||
222 | } |
||
223 | ) |
||
224 | |||
225 | self.testcase.refresh_from_db() |
||
226 | |||
227 | self.assertEqual(self.new_author.pk, self.testcase.default_tester.pk) |
||
228 | |||
229 | def test_update_default_tester_should_fail_with_non_existing_user_id(self): |
||
230 | self.assertIsNone(self.testcase.default_tester) |
||
231 | |||
232 | with self.assertRaises(Fault): |
||
233 | self.rpc_client.TestCase.update( # pylint: disable=objects-update-used |
||
234 | self.testcase.pk, |
||
235 | { |
||
236 | 'default_tester': self.non_existing_user_id, |
||
237 | } |
||
238 | ) |
||
239 | |||
240 | self.testcase.refresh_from_db() |
||
241 | |||
242 | self.assertIsNone(self.testcase.default_tester) |
||
243 | |||
244 | def test_update_default_tester_accepts_username(self): |
||
245 | self.assertIsNone(self.testcase.default_tester) |
||
246 | |||
247 | self.rpc_client.TestCase.update( # pylint: disable=objects-update-used |
||
248 | self.testcase.pk, |
||
249 | { |
||
250 | 'default_tester': self.new_author.username, |
||
251 | } |
||
252 | ) |
||
253 | |||
254 | self.testcase.refresh_from_db() |
||
255 | |||
256 | self.assertEqual(self.new_author.pk, self.testcase.default_tester.pk) |
||
257 | |||
258 | def test_update_default_tester_should_fail_with_non_existing_username(self): |
||
259 | self.assertIsNone(self.testcase.default_tester) |
||
260 | |||
261 | with self.assertRaises(Fault): |
||
262 | self.rpc_client.TestCase.update( # pylint: disable=objects-update-used |
||
263 | self.testcase.pk, |
||
264 | { |
||
265 | 'default_tester': self.non_existing_username, |
||
266 | } |
||
267 | ) |
||
268 | |||
269 | self.testcase.refresh_from_db() |
||
270 | |||
271 | self.assertIsNone(self.testcase.default_tester) |
||
272 | |||
273 | def test_update_default_tester_accepts_email(self): |
||
274 | self.assertIsNone(self.testcase.default_tester) |
||
275 | self.rpc_client.TestCase.update( # pylint: disable=objects-update-used |
||
276 | self.testcase.pk, |
||
277 | { |
||
278 | 'default_tester': self.new_author.email, |
||
279 | } |
||
280 | ) |
||
281 | |||
282 | self.testcase.refresh_from_db() |
||
283 | |||
284 | self.assertEqual(self.new_author.pk, self.testcase.default_tester.pk) |
||
285 | |||
286 | def test_update_default_tester_should_fail_with_non_existing_email(self): |
||
287 | self.assertIsNone(self.testcase.default_tester) |
||
288 | |||
289 | with self.assertRaises(Fault): |
||
290 | self.rpc_client.TestCase.update( # pylint: disable=objects-update-used |
||
291 | self.testcase.pk, |
||
292 | { |
||
293 | 'default_tester': self.non_existing_email, |
||
294 | } |
||
295 | ) |
||
296 | |||
297 | self.testcase.refresh_from_db() |
||
298 | |||
299 | self.assertIsNone(self.testcase.default_tester) |
||
300 | |||
301 | def test_update_reviewer_accepts_user_id(self): |
||
302 | self.assertNotEqual(self.new_author, self.testcase.reviewer) |
||
303 | |||
304 | self.rpc_client.TestCase.update( # pylint: disable=objects-update-used |
||
305 | self.testcase.pk, |
||
306 | { |
||
307 | 'reviewer': self.new_author.pk, |
||
308 | } |
||
309 | ) |
||
310 | |||
311 | self.testcase.refresh_from_db() |
||
312 | |||
313 | self.assertEqual(self.new_author.pk, self.testcase.reviewer.pk) |
||
314 | |||
315 | def test_update_reviewer_should_fail_with_non_existing_user_id(self): |
||
316 | initial_reviewer_id = self.testcase.reviewer.pk |
||
317 | with self.assertRaises(Fault): |
||
318 | self.rpc_client.TestCase.update( # pylint: disable=objects-update-used |
||
319 | self.testcase.pk, |
||
320 | { |
||
321 | 'reviewer': self.non_existing_user_id, |
||
322 | } |
||
323 | ) |
||
324 | |||
325 | self.testcase.refresh_from_db() |
||
326 | self.assertEqual(initial_reviewer_id, self.testcase.reviewer.pk) |
||
327 | |||
328 | def test_update_reviewer_accepts_username(self): |
||
329 | self.assertNotEqual(self.new_author, self.testcase.reviewer) |
||
330 | |||
331 | self.rpc_client.TestCase.update( # pylint: disable=objects-update-used |
||
332 | self.testcase.pk, |
||
333 | { |
||
334 | 'reviewer': self.new_author.username, |
||
335 | } |
||
336 | ) |
||
337 | |||
338 | self.testcase.refresh_from_db() |
||
339 | self.assertEqual(self.new_author, self.testcase.reviewer) |
||
340 | |||
341 | def test_update_reviewer_should_fail_for_non_existing_username(self): |
||
342 | initial_reviewer_username = self.testcase.reviewer.username |
||
343 | with self.assertRaises(Fault): |
||
344 | self.rpc_client.TestCase.update( # pylint: disable=objects-update-used |
||
345 | self.testcase.pk, |
||
346 | { |
||
347 | 'reviewer': self.non_existing_username, |
||
348 | } |
||
349 | ) |
||
350 | |||
351 | self.testcase.refresh_from_db() |
||
352 | self.assertEqual(initial_reviewer_username, self.testcase.reviewer.username) |
||
353 | |||
354 | def test_update_reviewer_accepts_email(self): |
||
355 | self.assertNotEqual(self.new_author, self.testcase.author) |
||
356 | |||
357 | self.rpc_client.TestCase.update( # pylint: disable=objects-update-used |
||
358 | self.testcase.pk, |
||
359 | { |
||
360 | 'reviewer': self.new_author.email, |
||
361 | } |
||
362 | ) |
||
363 | |||
364 | self.testcase.refresh_from_db() |
||
365 | self.assertEqual(self.new_author, self.testcase.reviewer) |
||
366 | |||
367 | def test_update_reviewer_should_fail_for_non_existing_email(self): |
||
368 | initial_reviewer_email = self.testcase.reviewer.email |
||
369 | with self.assertRaises(Fault): |
||
370 | self.rpc_client.TestCase.update( # pylint: disable=objects-update-used |
||
371 | self.testcase.pk, |
||
372 | { |
||
373 | 'reviewer': self.non_existing_email, |
||
374 | } |
||
375 | ) |
||
376 | |||
377 | self.testcase.refresh_from_db() |
||
378 | self.assertEqual(initial_reviewer_email, self.testcase.reviewer.email) |
||
379 | |||
380 | |||
381 | class TestCreate(APITestCase): |
||
382 | def _fixture_setup(self): |
||
383 | super()._fixture_setup() |
||
384 | |||
385 | for _ in range(5): |
||
386 | CategoryFactory() |
||
387 | |||
388 | def test_passes_with_valid_data(self): |
||
389 | result = self.rpc_client.TestCase.create( |
||
390 | { |
||
391 | 'summary': 'Newly created TC via API', |
||
392 | 'text': 'Given-When-Then', |
||
393 | 'case_status': TestCaseStatus.objects.first().pk, |
||
394 | 'priority': Priority.objects.first().pk, |
||
395 | 'category': Category.objects.first().pk, |
||
396 | } |
||
397 | ) |
||
398 | |||
399 | tc_from_db = TestCase.objects.get(summary=result['summary'], text=result['text']) |
||
400 | |||
401 | self.assertEqual(result['id'], tc_from_db.pk) |
||
402 | # author field is auto-configured if not passed |
||
403 | self.assertEqual(result['author'], tc_from_db.author.username) |
||
404 | self.assertEqual(self.api_user, tc_from_db.author) |
||
405 | |||
406 | def test_author_can_be_specified(self): |
||
407 | new_author = UserFactory() |
||
408 | result = self.rpc_client.TestCase.create( |
||
409 | { |
||
410 | 'summary': 'TC via API with author', |
||
411 | 'case_status': TestCaseStatus.objects.last().pk, |
||
412 | 'priority': Priority.objects.last().pk, |
||
413 | 'category': Category.objects.last().pk, |
||
414 | 'author': new_author.pk, |
||
415 | } |
||
416 | ) |
||
417 | |||
418 | tc_from_db = TestCase.objects.get(summary=result['summary'], author=new_author) |
||
419 | |||
420 | self.assertEqual(result['id'], tc_from_db.pk) |
||
421 | self.assertEqual(new_author, tc_from_db.author) |
||
422 | |||
423 | def test_fails_when_mandatory_fields_not_specified(self): |
||
424 | with self.assertRaises(Fault): |
||
425 | self.rpc_client.TestCase.create( |
||
426 | { |
||
427 | 'summary': 'TC via API without mandatory FK fields', |
||
428 | } |
||
429 | ) |
||
430 | |||
431 | |||
432 | View Code Duplication | class TestAddTag(APITestCase): |
|
0 ignored issues
–
show
Duplication
introduced
by
Loading history...
|
|||
433 | |||
434 | def _fixture_setup(self): |
||
435 | super()._fixture_setup() |
||
436 | |||
437 | self.testcase = TestCaseFactory() |
||
438 | |||
439 | self.tag1 = TagFactory() |
||
440 | self.tag2 = TagFactory() |
||
441 | |||
442 | def test_add_tag(self): |
||
443 | self.rpc_client.TestCase.add_tag(self.testcase.pk, self.tag1.name) |
||
444 | tag_exists = TestCase.objects.filter(pk=self.testcase.pk, tag__pk=self.tag1.pk).exists() |
||
445 | self.assertTrue(tag_exists) |
||
446 | |||
447 | def test_add_tag_without_permissions(self): |
||
448 | unauthorized_user = UserFactory() |
||
449 | unauthorized_user.set_password('api-testing') |
||
450 | unauthorized_user.save() |
||
451 | |||
452 | unauthorized_user.user_permissions.add(*Permission.objects.all()) |
||
453 | remove_perm_from_user(unauthorized_user, 'testcases.add_testcasetag') |
||
454 | |||
455 | rpc_client = xmlrpc.TCMSXmlrpc(unauthorized_user.username, |
||
456 | 'api-testing', |
||
457 | '%s/xml-rpc/' % self.live_server_url).server |
||
458 | |||
459 | with self.assertRaisesRegex(ProtocolError, '403 Forbidden'): |
||
460 | rpc_client.TestCase.add_tag(self.testcase.pk, self.tag1.name) |
||
461 | |||
462 | # tags were not modified |
||
463 | tag_exists = TestCase.objects.filter(pk=self.testcase.pk, tag__pk=self.tag1.pk).exists() |
||
464 | self.assertFalse(tag_exists) |
||
465 | |||
466 | |||
467 | View Code Duplication | class TestRemoveTag(APITestCase): |
|
0 ignored issues
–
show
|
|||
468 | |||
469 | def _fixture_setup(self): |
||
470 | super()._fixture_setup() |
||
471 | |||
472 | self.tag0 = TagFactory() |
||
473 | self.tag1 = TagFactory() |
||
474 | |||
475 | self.testcase = TestCaseFactory() |
||
476 | self.testcase.add_tag(self.tag0) |
||
477 | |||
478 | def test_remove_tag(self): |
||
479 | self.rpc_client.TestCase.remove_tag(self.testcase.pk, self.tag0.name) |
||
480 | tag_exists = TestCase.objects.filter(pk=self.testcase.pk, tag__pk=self.tag0.pk).exists() |
||
481 | self.assertFalse(tag_exists) |
||
482 | |||
483 | def test_remove_tag_without_permissions(self): |
||
484 | unauthorized_user = UserFactory() |
||
485 | unauthorized_user.set_password('api-testing') |
||
486 | unauthorized_user.save() |
||
487 | |||
488 | unauthorized_user.user_permissions.add(*Permission.objects.all()) |
||
489 | remove_perm_from_user(unauthorized_user, 'testcases.delete_testcasetag') |
||
490 | |||
491 | rpc_client = xmlrpc.TCMSXmlrpc(unauthorized_user.username, |
||
492 | 'api-testing', |
||
493 | '%s/xml-rpc/' % self.live_server_url).server |
||
494 | |||
495 | with self.assertRaisesRegex(ProtocolError, '403 Forbidden'): |
||
496 | rpc_client.TestCase.remove_tag(self.testcase.pk, self.tag0.name) |
||
497 | |||
498 | # tags were not modified |
||
499 | tag_exists = TestCase.objects.filter(pk=self.testcase.pk, tag__pk=self.tag0.pk).exists() |
||
500 | self.assertTrue(tag_exists) |
||
501 | |||
502 | tag_exists = TestCase.objects.filter(pk=self.testcase.pk, tag__pk=self.tag1.pk).exists() |
||
503 | self.assertFalse(tag_exists) |
||
504 | |||
505 | |||
506 | class TestAddComponent(APITestCase): |
||
507 | |||
508 | def _fixture_setup(self): |
||
509 | super()._fixture_setup() |
||
510 | self.test_case = TestCaseFactory() |
||
511 | self.good_component = ComponentFactory(product=self.test_case.category.product) |
||
512 | self.bad_component = ComponentFactory() |
||
513 | |||
514 | def test_add_component_from_same_product_is_allowed(self): |
||
515 | result = self.rpc_client.TestCase.add_component(self.test_case.pk, |
||
516 | self.good_component.name) |
||
517 | self.assertEqual(result['component'][0], self.good_component.pk) |
||
518 | |||
519 | def test_add_component_from_another_product_is_not_allowed(self): |
||
520 | with self.assertRaisesRegex(Fault, 'Component matching query does not exist'): |
||
521 | self.rpc_client.TestCase.add_component(self.test_case.pk, self.bad_component.name) |
||
522 |