Coverage for CIResults/tests/test_rest_views.py: 100%
435 statements
« prev ^ index » next coverage.py v7.4.4, created at 2024-04-23 13:11 +0000
« prev ^ index » next coverage.py v7.4.4, created at 2024-04-23 13:11 +0000
1import json
3from unittest.mock import patch, MagicMock
4from rest_framework.test import APIRequestFactory, APITestCase
5from django.conf import settings
6from django.db import transaction
7from django.test import TestCase
8from django.http.response import Http404
9from django.urls import reverse
11from CIResults.models import Build, Component, Test, Machine, RunConfigTag, TestResult, TestSuite, RunConfig
12from CIResults.models import TextStatus, IssueFilter, MachineTag, Issue, Bug, BugTracker
13from CIResults.rest_views import CustomPagination, IssueFilterViewSet, RunConfigViewSet, get_obj_by_id_or_name
14from CIResults.rest_views import BuildViewSet
15from CIResults.tests.test_views import create_user_and_log_in
17from shortener.models import Shortener
20# HACK: Massively speed up the login primitive. We don't care about security in tests
21settings.PASSWORD_HASHERS = ('django.contrib.auth.hashers.MD5PasswordHasher', )
24class UtilsTests(TestCase):
25 def test_get_obj_by_id_or_name__id(self):
26 rc = RunConfig.objects.create(name='valid', temporary=True)
27 self.assertEqual(get_obj_by_id_or_name(RunConfig, 1), rc)
29 def test_get_obj_by_id_or_name__name(self):
30 rc = RunConfig.objects.create(name='valid', temporary=True)
31 self.assertEqual(get_obj_by_id_or_name(RunConfig, "valid"), rc)
33 def test_get_obj_by_id_or_name__not_exist(self):
34 self.assertRaises(RunConfig.DoesNotExist, get_obj_by_id_or_name, RunConfig, 1)
37class CustomPaginationTests(TestCase):
38 def get_page_size(self, query_params, page_size_query_param='page_size', max_page_size=None):
39 request = MagicMock(query_params=query_params)
41 pagination = CustomPagination()
42 pagination.page_size_query_param = page_size_query_param
43 pagination.max_page_size = max_page_size
45 return pagination.get_page_size(request)
47 def test_default_page_size(self):
48 self.assertEqual(self.get_page_size({}), CustomPagination.page_size)
50 def test_default_page_size_without_page_size_field(self):
51 self.assertEqual(self.get_page_size({}, page_size_query_param=None), CustomPagination.page_size)
53 def test_invalid_page_size(self):
54 self.assertEqual(self.get_page_size({'page_size': 'toto'}), CustomPagination.page_size)
56 def test_negative_page_size(self):
57 self.assertEqual(self.get_page_size({CustomPagination.page_size_query_param: -0}), None)
59 def test_page_size_too_big(self):
60 self.assertEqual(self.get_page_size({'page_size': '1000'}, max_page_size=10), 10)
62 def test_page_size_big_but_no_limits(self):
63 self.assertEqual(self.get_page_size({'page_size': '1000'}, max_page_size=None), 1000)
65 def test_acceptable_page_size(self):
66 self.assertEqual(self.get_page_size({'page_size2': '42'}, page_size_query_param='page_size2'), 42)
69class IssueFilterTests(APITestCase):
70 maxDiff = None
72 def setUp(self):
73 self.view = IssueFilterViewSet()
74 self.user = None
76 def __post__(self, body_dict, logged_in=True, permissions=['add_issuefilter']):
77 if logged_in:
78 self.user = create_user_and_log_in(self.client, permissions=permissions)
80 return self.client.post(reverse('api:issuefilter-list'), body_dict, format='json')
82 def test__get_or_None__empty_field(self):
83 errors = []
84 self.assertIsNone(self.view.__get_or_None__(Machine, 'field', {'field': ''}, errors))
85 self.assertEqual(errors, [])
87 def test__get_or_None__invalid_id(self):
88 errors = []
89 self.assertIsNone(self.view.__get_or_None__(Machine, 'field', {'field': '12'}, errors))
90 self.assertEqual(errors, ["The object referenced by 'field' does not exist"])
92 def test_get_filter_by_description(self):
93 IssueFilter.objects.create(description="filter one")
94 IssueFilter.objects.create(description="filter two")
95 response = self.client.get(reverse('api:issuefilter-list'), {'description': 'one'})
96 self.assertEqual(response.status_code, 200)
97 self.assertEqual(response.data["count"], 1)
98 self.assertEqual(response.data["results"][0]["description"], "filter one")
100 def test_create_empty(self):
101 response = self.__post__({})
102 self.assertEqual(response.status_code, 400)
103 self.assertEqual(response.data, ["The field 'description' cannot be empty"])
105 def test_invalid_regexps(self):
106 response = self.__post__({"description": "Minimal IssueFilter",
107 "stdout_regex": '(', "stderr_regex": '(',
108 "dmesg_regex": '('})
109 self.assertEqual(response.status_code, 400)
110 self.assertEqual(response.data, ["The field 'stdout_regex' does not contain a valid regular expression",
111 "The field 'stderr_regex' does not contain a valid regular expression",
112 "The field 'dmesg_regex' does not contain a valid regular expression"])
114 def test_create_minimal__unauthenticated(self):
115 response = self.__post__({"description": "Minimal IssueFilter"}, logged_in=False)
116 self.assertEqual(response.status_code, 401)
118 # FIXME: This is not currently working
119 # def test_create_minimal__invalid_permissions(self):
120 # response = self.__post__({"description": "Minimal IssueFilter"}, logged_in=True, permissions=[])
121 # self.assertEqual(response.status_code, 403)
123 def test_create_minimal(self):
124 response = self.__post__({"description": "Minimal IssueFilter"})
125 self.assertEqual(response.status_code, 201)
126 self.assertEqual(response.data,
127 {'id': response.data['id'], 'description': 'Minimal IssueFilter',
128 'tags': [], 'machine_tags': [], 'machines': [], 'tests': [],
129 'statuses': [], 'stdout_regex': '',
130 'stderr_regex': '', 'dmesg_regex': '',
131 'user_query': '', '__str__': 'Minimal IssueFilter'})
133 def test_create_invalid(self):
134 response = self.__post__({
135 "description": "Invalid tags, machines, tests, and statuses",
136 'tags': [1], 'machines': [2], 'tests': [3], 'statuses': [4]
137 })
138 self.assertEqual(response.status_code, 400, response.data)
139 self.assertEqual(response.data, ['At least one tag does not exist',
140 'At least one machine does not exist',
141 'At least one test does not exist',
142 'At least one status does not exist'])
144 def test_create_complete(self):
145 # Create some objects before referencing them
146 ts = TestSuite.objects.create(name="ts", description="", url="", public=True)
147 for i in range(1, 6):
148 RunConfigTag.objects.create(id=i, name="tag{}".format(i), description="", url="", public=True)
149 Machine.objects.create(id=i, name="machine{}".format(i), public=True)
150 Test.objects.create(id=i, name="test{}".format(i), testsuite=ts, public=True)
151 TextStatus.objects.create(id=i, testsuite=ts, name="status{}".format(i))
152 MachineTag.objects.create(id=i, name="TAG{}".format(i), public=True)
154 # Make the request and check that we get the expected output
155 with transaction.atomic():
156 response = self.__post__({
157 "description": "Minimal IssueFilter",
158 'tags': [1, 2], 'machine_tags': [1, 5], 'machines': [2, 3], 'tests': [3, 4], 'statuses': [4, 5],
159 'stdout_regex': 'stdout', 'stderr_regex': 'stderr', 'dmesg_regex': 'dmesg'
160 })
162 self.assertEqual(response.status_code, 201, response.data)
163 self.assertEqual(dict(response.data),
164 {'id': response.data['id'], 'description': 'Minimal IssueFilter',
165 'tags': [
166 {'id': 1, 'description': '', 'url': '', 'public': True, '__str__': 'tag1'},
167 {'id': 2, 'description': '', 'url': '', 'public': True, '__str__': 'tag2'}
168 ],
169 'machine_tags': [
170 {'id': 1, 'name': 'TAG1', 'public': True},
171 {'id': 5, 'name': 'TAG5', 'public': True},
172 ],
173 'machines': [
174 {'id': 2, 'vetted_on': None, 'public': True, '__str__': 'machine2'},
175 {'id': 3, 'vetted_on': None, 'public': True, '__str__': 'machine3'},
176 ],
177 'tests': [
178 {'id': 3, 'testsuite': {'id': ts.id, '__str__': 'ts'}, 'public': True,
179 'vetted_on': None, 'first_runconfig': None, 'name': 'test3', '__str__': 'ts: test3'},
180 {'id': 4, 'testsuite': {'id': ts.id, '__str__': 'ts'}, 'public': True,
181 'vetted_on': None, 'first_runconfig': None, 'name': 'test4', '__str__': 'ts: test4'},
182 ],
183 'statuses': [
184 {'id': 4, 'testsuite': {'id': ts.id, '__str__': 'ts'}, 'name': 'status4',
185 '__str__': 'ts: status4'},
186 {'id': 5, 'testsuite': {'id': ts.id, '__str__': 'ts'}, 'name': 'status5',
187 '__str__': 'ts: status5'},
188 ],
189 'stdout_regex': 'stdout', 'stderr_regex': 'stderr',
190 'dmesg_regex': 'dmesg', '__str__': 'Minimal IssueFilter',
191 'user_query': ''})
193 def test_edit_invalid(self):
194 response = self.__post__({"description": "new filter",
195 "edit_filter": "a", "edit_issue": "b"})
196 self.assertEqual(response.status_code, 400, response.data)
197 self.assertEqual(response.data, ["The field 'edit_filter' needs to be an integer",
198 "The field 'edit_issue' needs to be an integer"])
200 @patch('CIResults.models.IssueFilter.replace')
201 @patch('CIResults.models.Issue.replace_filter')
202 def test_edit_all_issues(self, mock_replace_filter, mock_filter_replace):
203 filter = IssueFilter.objects.create(description="old filter")
205 with transaction.atomic():
206 response = self.__post__({"description": "new filter", "edit_filter": filter.id})
207 self.assertEqual(response.status_code, 201, response.data)
208 self.assertEqual(response.data,
209 {'id': response.data['id'], 'description': 'new filter',
210 'tags': [], 'machine_tags': [], 'machines': [], 'tests': [],
211 'statuses': [], 'stdout_regex': '',
212 'stderr_regex': '', 'dmesg_regex': '',
213 'user_query': '', '__str__': 'new filter'})
215 new_filter = IssueFilter.objects.get(pk=response.data['id'])
216 mock_replace_filter.assert_not_called()
217 mock_filter_replace.assert_called_once_with(new_filter, self.user)
218 self.assertEqual(mock_filter_replace.call_args_list[0][0][0].id, response.data['id'])
220 @patch('CIResults.models.IssueFilter.replace')
221 @patch('CIResults.models.Issue.replace_filter')
222 def test_edit_one_issue(self, mock_replace_filter, mock_filter_replace):
223 filter = IssueFilter.objects.create(description="desc")
224 issue = Issue.objects.create(description="issue")
226 with transaction.atomic():
227 response = self.__post__({"description": "new filter",
228 "edit_filter": "{}".format(filter.id),
229 "edit_issue": issue.id})
231 self.assertEqual(response.status_code, 201, response.data)
232 self.assertEqual(response.data,
233 {'id': response.data['id'], 'description': 'new filter',
234 'tags': [], 'machine_tags': [], 'machines': [], 'tests': [],
235 'statuses': [], 'stdout_regex': '',
236 'stderr_regex': '', 'dmesg_regex': '',
237 'user_query': '', '__str__': 'new filter'})
239 new_filter = IssueFilter.objects.get(pk=response.data['id'])
240 mock_filter_replace.assert_not_called()
241 mock_replace_filter.assert_called_once_with(filter, new_filter, self.user)
242 self.assertEqual(mock_replace_filter.call_args_list[0][0][0].id, filter.id)
243 self.assertEqual(mock_replace_filter.call_args_list[0][0][1].id, response.data['id'])
246class RunConfigTests(TestCase):
247 def setUp(self):
248 self.view = RunConfigViewSet()
249 self.arf = APIRequestFactory()
251 @patch('CIResults.models.RunConfig.objects.get')
252 def test_get_runcfg__by_id(self, runcfg_get_mocked):
253 self.assertEqual(self.view._get_runcfg('1'), runcfg_get_mocked.return_value)
254 runcfg_get_mocked.assert_called_once_with(pk=1)
256 @patch('CIResults.models.RunConfig.objects.get')
257 def test_get_runcfg__by_invalid_name(self, runcfg_get_mocked):
258 self.assertRaises(Http404, self.view._get_runcfg, 'missing')
259 runcfg_get_mocked.assert_not_called()
261 @patch('CIResults.models.RunConfig.objects.get')
262 def test_get_runcfg__by_valid_name(self, runcfg_get_mocked):
263 rc = RunConfig.objects.create(name='valid', temporary=True)
264 self.assertEqual(self.view._get_runcfg('valid').pk, rc.id)
265 runcfg_get_mocked.assert_not_called()
267 def test_retrieve__by_id(self):
268 rc = RunConfig.objects.create(name='valid', temporary=True)
269 data = self.view.retrieve(self.arf.get("/", {}, format="json"), pk="valid").data
270 self.assertEqual(data["id"], rc.id)
271 self.assertEqual(data["name"], "valid")
272 self.assertEqual(data["tags"], [])
273 self.assertIsNone(data["url"])
274 self.assertIsNotNone(data["added_on"])
276 def test_known_failures(self):
277 # TODO: Revisit the test whenever we start generating fixtures
278 RunConfig.objects.create(name='valid', temporary=True)
279 response = self.view.known_failures(self.arf.get('/', {}, format='json'),
280 pk='valid')
281 self.assertEqual(response.data, [])
283 @patch('CIResults.serializers.RunConfigDiffSerializer.data')
284 @patch('CIResults.models.RunConfig.compare')
285 def test_compare(self, compare_mocked, serializer_mocked):
286 RunConfig.objects.create(name='runcfg1', temporary=True)
287 runcfg2 = RunConfig.objects.create(name='runcfg2', temporary=True)
288 response = self.view.compare(self.arf.get('/', {'to': 'runcfg2'}, format='json'),
289 pk='runcfg1')
290 compare_mocked.assert_called_once_with(runcfg2, no_compress=False)
291 self.assertEqual(response.data, serializer_mocked)
293 @patch('CIResults.models.RunConfig.compare')
294 def test_compare__no_compress(self, compare_mocked):
295 RunConfig.objects.create(name='runcfg1', temporary=True)
296 runcfg2 = RunConfig.objects.create(name='runcfg2', temporary=True)
297 self.view.compare(self.arf.get('/', {'to': 'runcfg2', 'no_compress': '1'}, format='json'),
298 pk='runcfg1')
299 compare_mocked.assert_called_once_with(runcfg2, no_compress=True)
301 def test_compare__only_summary(self):
302 RunConfig.objects.create(name='runcfg1', temporary=True)
303 RunConfig.objects.create(name='runcfg2', temporary=True)
304 response = self.view.compare(self.arf.get('/', {'to': 'runcfg2', 'summary': ''}, format='json'),
305 pk='runcfg1')
306 self.assertIn('CI Bug Log', response.content.decode())
308 def test_create__no_permissions(self):
309 response = self.client.post(reverse('api:runconfig-list'),
310 data={"name": "runcfg", "tags": ["tag1"], "temporary": False},
311 content_type="application/json")
312 self.assertEqual(response.status_code, 401)
314 def test_create(self):
315 RunConfigTag.objects.create(id=1, name="tag1", public=True)
316 create_user_and_log_in(self.client, admin=True)
317 response = self.client.post(reverse('api:runconfig-list'),
318 data={"name": "runcfg", "tags": ["tag1"], "builds": [], "temporary": False},
319 content_type="application/json")
320 self.assertEqual(response.status_code, 201)
321 self.assertEqual(response.data["name"], "runcfg")
322 self.assertEqual(response.data["tags"], ["tag1"])
324 def test_create__invalid_data(self):
325 create_user_and_log_in(self.client, admin=True)
326 response = self.client.post(reverse('api:runconfig-list'), data={"name": "runcfg"},
327 content_type="application/json")
328 self.assertEqual(response.status_code, 400)
330 def test_create__invalid_data_missing_tag(self):
331 create_user_and_log_in(self.client, admin=True)
332 response = self.client.post(reverse('api:runconfig-list'),
333 data={"name": "runcfg", "tags": ["tag1"], "temporary": False},
334 content_type="application/json")
335 self.assertEqual(response.status_code, 400)
337 def test_import_testsuite_run(self):
338 RunConfig.objects.create(name='runcfg1', temporary=False)
339 component = TestSuite.objects.create(id=1, name='testsuite', public=True)
340 Build.objects.create(name='testsuite-1', component=component)
341 create_user_and_log_in(self.client, admin=True)
342 response = self.client.post("/api/runconfig/runcfg1/testsuiterun/", content_type="application/json", data={
343 "test_suite": "testsuite-1",
344 "test_results": {
345 "machine-1": {
346 "001": {
347 "test1": {
348 "status": "pass",
349 "stdout": "output"
350 }
351 },
352 "002": {
353 "test2": {
354 "status": "pass",
355 "stdout": "output"
356 }
357 }
358 }
359 }
360 })
361 self.assertEqual(response.status_code, 200)
362 self.assertIsNotNone(Machine.objects.get(name="machine-1"))
363 self.assertIsNotNone(Test.objects.get(name="test1"))
364 self.assertIsNotNone(TextStatus.objects.get(name="pass"))
365 self.assertEqual(TestResult.objects.count(), 2)
366 for test_name in ["test1", "test2"]:
367 result = TestResult.objects.filter(test__name=test_name).first()
368 self.assertEqual(result.status.name, "pass")
369 self.assertEqual(result.stdout, "output")
371 def test_import_testsuite_run__no_permissions(self):
372 response = self.client.post("/api/runconfig/runcfg1/testsuiterun/", content_type="application/json", data={})
373 self.assertEqual(response.status_code, 401)
375 def test_import_testsuite_run__invalid_data(self):
376 RunConfig.objects.create(name='runcfg1', temporary=False)
377 component = TestSuite.objects.create(id=1, name='testsuite', public=True)
378 Build.objects.create(name='testsuite-1', component=component)
379 create_user_and_log_in(self.client, admin=True)
380 response = self.client.post("/api/runconfig/runcfg1/testsuiterun/", content_type="application/json", data={
381 "test_suite": "testsuite-1",
382 "test_results": "invalid_data"
383 })
384 self.assertEqual(response.status_code, 400)
385 self.assertEqual(response.json()["message"]["test_results"],
386 ['Expected a dictionary of items but got type "str".'])
388 def test_import_testsuite_run__invalid_data_no_testsuite(self):
389 RunConfig.objects.create(name='runcfg1', temporary=False)
390 create_user_and_log_in(self.client, admin=True)
391 response = self.client.post("/api/runconfig/runcfg1/testsuiterun/", content_type="application/json", data={
392 "test_suite": "testsuite-1",
393 "test_results": {
394 "machine-1": {
395 "001": {
396 "test1": {
397 "status": "pass",
398 "stdout": "output"
399 }
400 }
401 }
402 }
403 })
404 self.assertEqual(response.status_code, 400)
405 self.assertEqual(response.json()["message"], 'Testsuite build testsuite-1 does not exist')
408class BuildViewSetTests(APITestCase):
409 def setUp(self) -> None:
410 self.component = Component.objects.create(name="component", public=False)
411 self.view = BuildViewSet()
412 self.arf = APIRequestFactory()
414 def test_retrieve(self):
415 rc = Build.objects.create(name='valid', component=self.component)
416 data = self.view.retrieve(self.arf.get("/", {}, format="json"), pk="valid").data
417 self.assertEqual(data["id"], rc.id)
418 self.assertEqual(data["name"], "valid")
419 self.assertIsNotNone(data["added_on"])
421 def test_create_build_without_permissions(self):
422 response = self.client.post(reverse('api:build-list'),
423 data={"name": "test-build", "component": "component", "version": "1"},
424 format="json")
425 self.assertEqual(response.status_code, 401)
427 def test_create_build(self):
428 create_user_and_log_in(self.client, admin=True)
429 response = self.client.post(reverse('api:build-list'),
430 data={"name": "build1", "component": "component", "version": "1", "parents": []},
431 format="json")
432 self.assertEqual(response.status_code, 201)
433 self.assertEqual(response.data["name"], "build1")
435 def test_create_build__invalid_data_schema(self):
436 create_user_and_log_in(self.client, admin=True)
437 response = self.client.post(reverse('api:build-list'),
438 data={"name": "test-build", "component": "component"},
439 format="json")
440 self.assertEqual(response.status_code, 400)
441 self.assertEqual(json.loads(response.content)["version"], ["This field is required."])
443 def test_create_build__invalid_data(self):
444 create_user_and_log_in(self.client, admin=True)
445 response = self.client.post(reverse('api:build-list'),
446 data={"name": "test-build", "component": "no-component", "version": "1"},
447 format="json")
448 self.assertEqual(response.status_code, 400)
451class BugViewSetTests(TestCase):
452 def setUp(self):
453 self.arf = APIRequestFactory()
455 @classmethod
456 def setUpTestData(cls):
457 cls.bt1 = BugTracker.objects.create(name='Test Suite 1', short_name='ts1', public=True)
458 cls.bt2 = BugTracker.objects.create(name='Test Suite 2', short_name='ts2', public=True)
460 cls.bugs = dict()
461 for bt in (cls.bt1, cls.bt2):
462 cls.bugs[bt] = []
463 for i in range(2):
464 cls.bugs[bt].append(Bug.objects.create(tracker=bt, bug_id='b_'+str(i)))
466 def test_retrieving_by_tracker_id(self):
467 tracker = self.bt2
468 bug = self.bugs[self.bt2][1]
469 response = self.client.get(reverse('api-bugtracker-get-bug',
470 kwargs={'tracker': tracker.id, 'bug_id': bug.bug_id}), format='json')
471 self.assertEqual(response.status_code, 200)
472 self.assertEqual(response.data['bug_id'], bug.bug_id)
473 self.assertEqual(response.data['tracker']['short_name'], tracker.short_name)
475 def test_retrieving_by_tracker_name(self):
476 tracker = self.bt1
477 bug = self.bugs[self.bt2][0]
478 response = self.client.get(reverse('api-bugtracker-get-bug',
479 kwargs={'tracker': tracker.name, 'bug_id': bug.bug_id}), format='json')
480 self.assertEqual(response.status_code, 200)
481 self.assertEqual(response.data['bug_id'], bug.bug_id)
482 self.assertEqual(response.data['tracker']['short_name'], tracker.short_name)
484 def test_retrieving_by_tracker_short_name(self):
485 tracker = self.bt2
486 bug = self.bugs[self.bt2][0]
487 response = self.client.get(reverse('api-bugtracker-get-bug',
488 kwargs={'tracker': tracker.short_name, 'bug_id': bug.bug_id}), format='json')
489 self.assertEqual(response.status_code, 200)
490 self.assertEqual(response.data['bug_id'], bug.bug_id)
491 self.assertEqual(response.data['tracker']['short_name'], tracker.short_name)
494class ShortenerViewSetTests(TestCase):
495 def setUp(self):
496 self.arf = APIRequestFactory()
498 @classmethod
499 def setUpTestData(cls):
500 cls.short1 = Shortener.get_or_create("Some sort of long query!")
502 def test_create_invalid_request(self):
503 with self.assertRaisesMessage(ValueError, "Only JSON POST requests are supported"):
504 self.client.post(reverse('api:shortener-list'), data={})
506 def test_create_empty(self):
507 with self.assertRaisesMessage(ValueError,
508 "Missing the field 'full' which should contain the full text to be shortened"):
509 self.client.post(reverse('api:shortener-list'), data={}, content_type="application/json")
511 def test_create_single(self):
512 full = 'Some sort of long query, but different!'
514 response = self.client.post(reverse('api:shortener-list'), data={'full': full}, content_type="application/json")
515 self.assertEqual(response.status_code, 200)
517 data = response.json()
518 self.assertNotEqual(data['id'], self.short1.id)
519 self.assertEqual(data['full'], full)
521 def test_create_multiple(self):
522 fulls = ["query1", "query2"]
524 response = self.client.post(reverse('api:shortener-list'), data={'full': fulls},
525 content_type="application/json")
526 self.assertEqual(response.status_code, 200)
528 data = response.json()
529 self.assertEqual(data[0]['full'], fulls[0])
530 self.assertEqual(data[1]['full'], fulls[1])
532 def test_retrieving_existing(self):
533 response = self.client.post(reverse('api:shortener-list'), data={'full': self.short1.full},
534 content_type="application/json")
535 self.assertEqual(response.status_code, 200)
537 data = response.json()
538 self.assertEqual(data['id'], self.short1.id)
541class MachineViewSetTests(TestCase):
542 def setUp(self):
543 self.arf = APIRequestFactory()
545 def test_list_machines(self):
546 Machine.objects.create(name="machine_1", public=True)
547 response = self.client.get(reverse('api:machine-list'), content_type="application/json")
548 self.assertEqual(response.status_code, 200)
549 self.assertEqual(json.loads(response.content)["results"],
550 [{'id': 1,
551 'name': 'machine_1',
552 'description': None,
553 'public': True,
554 'vetted_on': None,
555 'aliases': None,
556 'tags': []}])
558 def test_create_machine_without_permission(self):
559 response = self.client.post(reverse('api:machine-list'), data={'name': 'machine_1', 'tags': ['tag1']},
560 content_type="application/json")
561 self.assertEqual(response.status_code, 401)
563 def test_create_machine(self):
564 self.user = create_user_and_log_in(self.client, admin=True)
565 response = self.client.post(reverse('api:machine-list'), data={'name': 'machine_1', 'tags': ['tag1']},
566 content_type="application/json")
567 self.assertEqual(response.status_code, 201)
568 self.assertEqual(json.loads(response.content), {
569 "data": {
570 "id": 1,
571 "name": "machine_1",
572 "description": None,
573 "public": False,
574 "vetted_on": None,
575 "aliases": None,
576 "tags": ["tag1"]
578 },
579 "status": "success"
580 })
582 def test_create_machine_invalid_data(self):
583 self.user = create_user_and_log_in(self.client, admin=True)
584 response = self.client.post(reverse('api:machine-list'), data={'name': True},
585 content_type="application/json")
586 self.assertEqual(response.status_code, 400)
587 self.assertEqual(json.loads(response.content), {
588 "message": {"name": ["Not a valid string."]},
589 "status": "error"
590 })
592 def test_create_machine_import_error(self):
593 self.user = create_user_and_log_in(self.client, admin=True)
594 response = self.client.post(reverse('api:machine-list'), data={'name': 'machine_1', 'alias': 'machine_2'},
595 content_type="application/json")
596 self.assertEqual(response.status_code, 400)
597 self.assertEqual(json.loads(response.content), {
598 "message": "The machine this machine is supposed to alias does not exist. "
599 "Create it first...",
600 "status": "error"
601 })
604class IssueViewSetTests(TestCase):
605 def setUp(self):
606 self.arf = APIRequestFactory()
608 def test_archive_issue_without_permission(self):
609 response = self.client.get(reverse('api:issue-archive', kwargs={"pk": 1}))
610 self.assertEqual(response.status_code, 401)
611 self.assertEqual(response.json(), {"message": "User AnonymousUser doesn't have sufficient permissions"})
613 def test_archive_issue(self):
614 Issue.objects.create()
615 self.user = create_user_and_log_in(self.client, admin=True)
616 response = self.client.get(reverse('api:issue-archive', kwargs={"pk": 1}))
617 self.assertEqual(response.status_code, 200)
619 def test_archive_archived_issue(self):
620 self.user = create_user_and_log_in(self.client, admin=True)
621 Issue.objects.create().archive(self.user)
622 response = self.client.get(reverse('api:issue-archive', kwargs={"pk": 1}))
623 self.assertEqual(response.status_code, 400)
624 self.assertEqual(response.json(), {"message": "The issue is already archived"})
626 def test_restore_issue_without_permission(self):
627 response = self.client.get(reverse('api:issue-restore', kwargs={"pk": 1}))
628 self.assertEqual(response.status_code, 401)
629 self.assertEqual(response.json(), {"message": "User AnonymousUser doesn't have sufficient permissions"})
631 def test_restore_issue(self):
632 self.user = create_user_and_log_in(self.client, admin=True)
633 Issue.objects.create().archive(self.user)
634 response = self.client.get(reverse('api:issue-restore', kwargs={"pk": 1}))
635 self.assertEqual(response.status_code, 200)
637 def test_restore_not_archived_issue(self):
638 Issue.objects.create()
639 self.user = create_user_and_log_in(self.client, admin=True)
640 response = self.client.get(reverse('api:issue-restore', kwargs={"pk": 1}))
641 self.assertEqual(response.status_code, 400)
642 self.assertEqual(response.json(), {"message": "The issue is not currently archived"})
644 def test_update_to_expected(self):
645 Issue.objects.create(expected=False)
646 self.user = create_user_and_log_in(self.client, admin=True)
647 response = self.client.patch(reverse('api:issue-detail', kwargs={"pk": 1}), data={"id": 1, "expected": True},
648 content_type="application/json")
649 self.assertEqual(response.status_code, 200)
650 self.assertEqual(response.json()["expected"], True)
651 self.assertEqual(Issue.objects.get(pk=1).expected, True)
653 def test_update_to_expected_wrong_value(self):
654 Issue.objects.create(expected=False)
655 self.user = create_user_and_log_in(self.client, admin=True)
656 response = self.client.patch(reverse('api:issue-detail', kwargs={"pk": 1}), data={"id": 1, "expected": "Str"},
657 content_type="application/json")
658 self.assertEqual(response.status_code, 400)
659 self.assertEqual(response.json()["expected"], ["Must be a valid boolean."])
661 def test_try_to_update_read_only_field(self):
662 Issue.objects.create(runconfigs_covered_count=100)
663 self.user = create_user_and_log_in(self.client, admin=True)
664 response = self.client.patch(reverse('api:issue-detail', kwargs={"pk": 1}),
665 data={"id": 1, "runconfigs_covered_count": 99}, content_type="application/json")
666 self.assertEqual(response.status_code, 200)
667 self.assertEqual(response.json()["runconfigs_covered_count"], 100)
670class TestSetTests(TestCase):
671 def setUp(self):
672 self.arf = APIRequestFactory()
673 ts = TestSuite.objects.create(name="ts", description="", url="", public=True)
674 Test.objects.create(id=1, name="test1", testsuite=ts, public=True)
676 def test_vet_test_without_permission(self):
677 response = self.client.get(reverse('api:test-vet', kwargs={"pk": 1}))
678 self.assertEqual(response.status_code, 403)
680 def test_vet_test(self):
681 self.user = create_user_and_log_in(self.client, admin=True)
682 response = self.client.get(reverse('api:test-vet', kwargs={"pk": 1}))
683 self.assertEqual(response.status_code, 200)
685 def test_vet_already_vetted(self):
686 self.user = create_user_and_log_in(self.client, admin=True)
687 Test.objects.get(pk=1).vet()
688 response = self.client.get(reverse('api:test-vet', kwargs={"pk": 1}))
689 self.assertEqual(response.status_code, 200)
691 def test_suppress_test_without_permission(self):
692 response = self.client.get(reverse('api:test-suppress', kwargs={"pk": 1}))
693 self.assertEqual(response.status_code, 403)
695 def test_suppress_test(self):
696 Test.objects.get(pk=1).vet()
697 self.user = create_user_and_log_in(self.client, admin=True)
698 response = self.client.get(reverse('api:test-suppress', kwargs={"pk": 1}))
699 self.assertEqual(response.status_code, 200)
702class metrics_passrate_trend_viewTests(TestCase):
703 def setUp(self):
704 self.arf = APIRequestFactory()
706 def test_basic(self):
707 # TODO: Add a fixture that would return useful data here
708 response = self.client.get(reverse('api-metrics-passrate-per-runconfig'),
709 {'query': ""}, format='json')
710 self.assertEqual(response.status_code, 200)
713class metrics_passrate_viewTests(TestCase):
714 def setUp(self):
715 self.arf = APIRequestFactory()
717 def test_basic(self):
718 # TODO: Add a fixture that would return useful data here
719 response = self.client.get(reverse('api-metrics-passrate-per-test'),
720 {'query': ""}, format='json')
721 self.assertEqual(response.status_code, 200)