import datetime import json from datetime import datetime, timedelta from unittest import mock from urllib.parse import urlencode import pytest from django.contrib.auth.models import User from django.urls import reverse from django.utils import timezone from rest_framework.test import APIClient from incident.models import Incident, IncidentRecommendations, IncidentEffect from perms.models import Perm @pytest.mark.django_db class TestIncidentsListAPI: @pytest.fixture def now(self): return datetime.now(tz=timezone.utc) @pytest.fixture def incidents(self, now): Incident.objects.bulk_create([ Incident(timestamp=now, title='Test1', importance=50, event_count=10, events=''), Incident(timestamp=now - timedelta(hours=1), title='Test2', importance=20, event_count=10, events=''), Incident(timestamp=now - timedelta(days=1), title='Test3', importance=10, event_count=10, events=''), ]) @pytest.fixture def users_and_incidents(self, add_user_with_permissions): for number in range(1, 4): user = add_user_with_permissions(username=f'user_{number}', password='pwd12', permissions=[Perm.can_view_incidents_list]) Incident.objects.create( timestamp=datetime.now() - timedelta(hours=1), title=f'Test_{number}', importance=20, event_count=10, status=1, assigned_to=user, events='') Incident.objects.create( timestamp=datetime.now() - timedelta(hours=1), title=f'Test_{number + 1}', importance=20 + 2, event_count=10 + 3, status=1, assigned_to=user, events='') Incident.objects.create( timestamp=datetime.now() - timedelta(hours=1), title=f'Test_{number}', importance=20, event_count=10, status=2, assigned_to=user, events='') Incident.objects.create( timestamp=datetime.now() - timedelta(hours=1), title=f'Test_{number}', importance=20, event_count=10, status=3, assigned_to=user, events='') add_user_with_permissions(username=f'user_admin', password='pwd12', permissions=[Perm.can_view_incidents_list]) @pytest.fixture(autouse=True) def setup_tests(self, client, django_user_model, test_server, add_user_with_permissions): # User who can work with incidents self.user = add_user_with_permissions(username="pro100ton3", password="ponala61", permissions=[ Perm.can_view_incidents_list, Perm.can_view_incidents, Perm.can_work_with_incidents ], is_superuser=False) @pytest.mark.unit def test_full_list(self, incidents, client): response = client.get(reverse('incident-list')) assert response.status_code == 403 @pytest.mark.unit @pytest.mark.skip(reason='Works 1.3, 1.5 waiting of products') def test_sorted_list_var_1(self, incidents, client, django_user_model): """Test user see all unseegned incidents""" client.force_login(django_user_model.objects.get(username='pro100ton3')) response = client.get(reverse('incident-list')) assert response.status_code == 200 data = json.loads(response.content.decode('utf-8')) assert data["count"] == 3 @pytest.mark.unit @pytest.mark.skip(reason='Works 1.3, 1.5 waiting of products') def test_sorted_list_var_2(self, incidents, client, django_user_model): """Check that the user see the incidents assigned to him and does not see the resolved ones """ user = django_user_model.objects.get(username='pro100ton3') incident_signed = Incident.objects.get(title='Test1') incident_signed.assigned_to = user incident_signed.save() for incident in Incident.objects.filter(assigned_to=None): incident.status = 3 incident.save() client.force_login(user) response = client.get(reverse('incident-list')) assert response.status_code == 200 data = json.loads(response.content.decode('utf-8')) assert data["count"] == 1 assert data["results"][0]["assigned_to"] == "pro100ton3" assert data["results"][0]["status"] == 1 @pytest.mark.unit @pytest.mark.skip(reason='Works 1.3, 1.5 waiting of products') def test_sorted_list_var_3(self, incidents, client, django_user_model, add_user_with_permissions): """Check that the user sees the incidents assigned to him and all the unassigned ones """ user = django_user_model.objects.get(username='pro100ton3') user_2 = add_user_with_permissions(username='any_one', password='ao_pwd', is_superuser=False) incident_assigned = Incident.objects.get(title='Test1') incident_assigned.assigned_to = user incident_assigned.save() incident_assigned_to_any = Incident.objects.get(title='Test2') incident_assigned_to_any.assigned_to = user_2 incident_assigned_to_any.save() client.force_login(user) response = client.get(reverse('incident-list')) assert response.status_code == 200 data = json.loads(response.content.decode('utf-8')) assert data["count"] == 3 count = 0 for item in data["results"]: if (item["assigned_to"] == 'pro100ton3' or item["assigned_to"] == 'any_one') and item["status"] == 1: count += 1 assert count == 2 @pytest.mark.unit @pytest.mark.skip(reason='Works 1.3, 1.5 waiting of products') def test_list_with_search(self, incidents, client, add_user_with_permissions) -> None: _url = reverse('incident-list') user = add_user_with_permissions(username='test_user1', password='pwd12', permissions=[Perm.can_view_incidents_list]) client.force_login(user=user) querystring = urlencode({ 'format': 'datatables', 'draw': '14', 'columns[0][data]': 'user_friendly_id', 'columns[0][name]': '', 'columns[0][searchable]': 'true', 'columns[0][orderable]': 'true', 'columns[0][search][value]': '', 'columns[0][search][regex]': 'false', 'start': '0', 'length': '10', 'search[value]': 'test_search', 'search[regex]': 'false', '_': '1635401184016', }) url = f'{_url}?{querystring}' response = client.get(url) assert response.status_code == 200 @pytest.mark.unit @pytest.mark.skip(reason='Works 1.3, 1.5 waiting of products') def test_filter_show_resolve_incident(self, incidents, client, add_user_with_permissions) -> None: _url = reverse('incident-list') user = add_user_with_permissions(username='test_user1', password='pwd12', permissions=[Perm.can_view_incidents_list]) stats_resolved = Incident.Status.RESOLVED.value incident = Incident.objects.last() incident.status = stats_resolved incident.save() client.force_login(user=user) querystring = urlencode({ 'format': 'datatables', 'draw': '14', 'columns[0][data]': 'status', 'columns[0][name]': '', 'columns[0][searchable]': 'false', 'columns[0][orderable]': 'true', 'columns[0][search][value]': '', 'columns[0][search][regex]': ' false', 'start': '0', 'length': '10', 'search[value]': '', 'search[regex]': 'false', 'filter[0][field]': 'status', 'filter[0][value][]': str(stats_resolved), 'filter[0][filter_type]': 'exact-match', '_': '1635500017602', }) url = f'{_url}?{querystring}' response = client.get(url) assert response.status_code == 200 data = json.loads(response.content.decode('utf-8')) assert data['recordsFiltered'] == 1 assert data['data'][0]['status'] == stats_resolved @pytest.mark.unit @mock.patch('incident.views.incidents_api.incident_count_notification_to_ws') def test_update_action_valid(self, _, incidents): incident = Incident.objects.first() client = APIClient() client.force_login(self.user) url = reverse('incident-detail', args=[incident.pk]) data = {'status': 3} response = client.put(url, data, format='json') assert response.status_code == 200 response_data = response.data assert 'status' in response_data assert 'deadline' in response_data assert 'category' in response_data assert 'comment' in response_data assert 'assigned_to' in response_data assert response_data['status'] == 3 @pytest.mark.unit def test_update_action_not_valid(self, incidents): data = { 'title': 'must be not change', 'status': 'string', } incident = Incident.objects.first() client = APIClient() client.force_login(self.user) url = reverse('incident-detail', args=[incident.pk]) response = client.put(url, data, format='json') print(response.data) assert response.status_code == 400 @pytest.mark.unit def test_effects_and_recommendation_in_incident(self, incidents): incident = Incident.objects.first() rec = IncidentRecommendations.objects.create(name='rec') eff = IncidentEffect.objects.create(name='eff') incident.close_recommendations.add(rec) incident.effects.add(eff) client = APIClient() client.force_authenticate(self.user) url = reverse('incident-detail', args=[incident.pk]) response = client.get(url) assert response.status_code == 200 assert response.data['close_recommendations'][0] == {'id': rec.pk, 'name': 'rec', 'description': None} assert response.data['effects'][0] == {'id': eff.pk, 'name': 'eff', 'description': None} @pytest.mark.unit def test_incident_ordering(self, users_and_incidents): """The check is that we are logged in by different users and the first 2 incidents in the list should be incidents assigned to this user. We also log in as a user who has no incidents assigned at all and the list should have incidents sorted by user""" self.check_list_ordering() # Login user with assigned incidents for user in ["user_1", "user_2", "user_3"]: self.check_list_ordering_assigned(user) def check_list_ordering_assigned(self, username): client = APIClient() url = reverse('incident-list') logout_url = reverse('logout') user = User.objects.get(username=username) client.force_login(user=user) response = client.get(url) data = json.loads(response.content.decode('utf-8')) assert response.status_code == 200 assert data['results'][0]['assigned_to'] == username assert data['results'][1]['assigned_to'] == username response = client.post(logout_url) assert response.status_code == 200 def check_list_ordering(self): client = APIClient() url = reverse('incident-list') logout_url = reverse('logout') user = User.objects.get(username="user_admin") client.force_login(user=user) response = client.get(url) data = json.loads(response.content.decode('utf-8')) assert response.status_code == 200 assert data['results'][0]['assigned_to'] == "user_1" assert data['results'][1]['assigned_to'] == "user_1" response = client.post(logout_url) assert response.status_code == 200