Fakultas Ilmu Komputer UI

Commit bd4d4d1d authored by Dave Nathanael's avatar Dave Nathanael
Browse files

Merge branch 'staging' into 'dave/PBI-9-Case-pagination-filter'

# Conflicts:
#   apps/cases/views.py
#   project/settings.py
parents 2f50446e 73b4cecf
Pipeline #37018 passed with stages
in 2 minutes and 53 seconds
......@@ -14,6 +14,8 @@ test:
- python manage.py runserver 8000 &
when: on_success
script:
- echo "Starting linter"
- sh lint.sh
- echo "Starting tests"
- coverage erase
- coverage run --include="./*/*" --omit="./env/*","./project/*","./manage.py" manage.py test apps
......
......@@ -43,6 +43,6 @@ class Migration(migrations.Migration):
),
),
],
options={"verbose_name_plural": "accounts", "db_table": "account",},
options={"verbose_name_plural": "accounts", "db_table": "account", },
),
]
......@@ -40,6 +40,4 @@ class AccountRegisterSerializer(serializers.ModelSerializer):
"phone_number",
"area",
"is_admin",
"is_verified",
"is_active",
]
......@@ -27,3 +27,4 @@ class AccountFactory(factory.DjangoModelFactory):
email = faker.email()
phone_number = faker.phone_number()
area = faker.city()
is_active = True
import json
from django.test import TestCase
from django.urls import reverse
from faker import Faker
from django.urls import reverse
from rest_framework import status
from rest_framework.authtoken.models import Token
from rest_framework.test import APITestCase, APIClient
from apps.accounts.models import Account
from apps.accounts.tests.factories.accounts import AccountFactory, UserFactory
from apps.constants import HEADER_PREFIX
class AccountViewTest(TestCase):
def setUp(self):
self.user_1 = UserFactory(username="user_1")
self.user_2 = UserFactory(username="user_2")
class AccountViewTest(APITestCase):
@classmethod
def setUpTestData(self):
self.user_1 = UserFactory(username="user_1", password="justpass")
self.user_2 = UserFactory(username="user_2", password="justpass")
self.admin = AccountFactory(admin=True, user=self.user_1)
self.officer = AccountFactory(admin=False, user=self.user_2)
self.accounts = [self.admin, self.officer]
self.token_1, _ = Token.objects.get_or_create(user=self.user_1)
self.token_2, _ = Token.objects.get_or_create(user=self.user_2)
self.faker = Faker()
def test_list_all_accounts(self):
def setUp(self):
self.client = APIClient(
HTTP_AUTHORIZATION=HEADER_PREFIX + self.token_1.key
)
def test_list_all_accounts_success(self):
url = "/accounts/"
response = self.client.get(url)
self.assertEqual(response.status_code, status.HTTP_200_OK)
def test_retrieve_account(self):
def test_retrieve_account_success(self):
url = "/accounts/" + str(self.officer.id) + "/"
response = self.client.get(url)
data = {
"id": str(self.officer.id),
"name": self.officer.name,
......@@ -38,13 +47,13 @@ class AccountViewTest(TestCase):
"area": self.officer.area,
"is_admin": False,
"is_verified": False,
"is_active": False,
"is_active": True,
}
self.assertJSONEqual(json.dumps(response.data), data)
self.assertEqual(response.status_code, status.HTTP_200_OK)
def test_create_new_admin(self):
def test_create_new_admin_success(self):
url = "/accounts/"
_account_id = self.faker.email()
......@@ -60,15 +69,13 @@ class AccountViewTest(TestCase):
"is_admin": True,
}
response = self.client.post(
path=url, data=data, content_type="application/json", format="json",
)
response = self.client.post(path=url, data=data, format="json",)
admin_current_count = Account.objects.filter(is_admin=True).count()
self.assertEqual(response.status_code, status.HTTP_201_CREATED)
self.assertEqual(admin_current_count, admin_prev_count + 1)
def test_create_new_officer(self):
def test_create_new_officer_success(self):
url = "/accounts/"
_account_id = self.faker.email()
......@@ -84,15 +91,13 @@ class AccountViewTest(TestCase):
"is_admin": False,
}
response = self.client.post(
path=url, data=data, content_type="application/json", format="json",
)
response = self.client.post(path=url, data=data, format="json",)
officer_current_count = Account.objects.filter(is_admin=False).count()
self.assertEqual(response.status_code, status.HTTP_201_CREATED)
self.assertEqual(officer_current_count, officer_prev_count + 1)
def test_fail_create_new_account_with_no_auth_info(self):
def test_create_new_account_fails_with_no_auth_info(self):
url = "/accounts/"
_account_id = self.faker.email()
......@@ -105,12 +110,10 @@ class AccountViewTest(TestCase):
"is_admin": False,
}
response = self.client.post(
path=url, data=data, content_type="application/json", format="json",
)
response = self.client.post(path=url, data=data, format="json",)
self.assertEqual(response.status_code, status.HTTP_400_BAD_REQUEST)
def test_edit_account(self):
def test_edit_account_success_by(self):
url = "/accounts/" + str(self.officer.id) + "/"
data = {
......@@ -124,9 +127,10 @@ class AccountViewTest(TestCase):
"is_active": True,
}
response = self.client.put(
path=url, data=data, content_type="application/json", format="json",
self.client = APIClient(
HTTP_AUTHORIZATION=HEADER_PREFIX + self.token_2.key
)
response = self.client.put(path=url, data=data, format="json",)
expected_returned_data = data
expected_returned_data["username"] = self.officer.user.username
......@@ -145,7 +149,12 @@ class AccountViewTest(TestCase):
"area": self.faker.city(),
}
response = self.client.put(
path=url, data=data, content_type="application/json", format="json",
)
response = self.client.put(path=url, data=data, format="json",)
self.assertEqual(response.status_code, status.HTTP_400_BAD_REQUEST)
def test_delete_success(self):
url = "/accounts/" + str(self.officer.id) + "/"
response = self.client.delete(url)
self.assertEqual(response.status_code, status.HTTP_200_OK)
......@@ -24,7 +24,5 @@ router = DefaultRouter()
router.register(r"", AccountViewSet, basename="account")
urlpatterns = [
path("auth/", include("django.contrib.auth.urls")),
path("", include(router.urls)),
]
urlpatterns += router.urls
......@@ -8,10 +8,17 @@ from apps.accounts.serializers import (
AccountSerializer,
AccountRegisterSerializer,
)
from apps.commons.permissions import (
IsSelfOrAdministrator,
CreateOnly,
)
class AccountViewSet(viewsets.ViewSet):
queryset = Account.objects.all().select_related("user")
permission_classes = [
IsSelfOrAdministrator | CreateOnly,
]
def list(self, request):
queryset = self.queryset
......@@ -20,6 +27,7 @@ class AccountViewSet(viewsets.ViewSet):
def retrieve(self, request, pk=None):
instance = get_object_or_404(self.queryset, pk=pk)
self.check_object_permissions(request, instance)
serializer = AccountSerializer(instance)
return Response(serializer.data, status=status.HTTP_200_OK)
......@@ -31,6 +39,7 @@ class AccountViewSet(viewsets.ViewSet):
password = serializer.validated_data.pop("password")
user = User.objects.create_user(username=username, password=password)
account = Account.objects.create(user=user, **serializer.validated_data)
return Response(
......@@ -39,8 +48,16 @@ class AccountViewSet(viewsets.ViewSet):
def update(self, request, pk=None):
instance = get_object_or_404(self.queryset, pk=pk)
self.check_object_permissions(request, instance)
serializer = AccountSerializer(instance, data=request.data)
serializer.is_valid(raise_exception=True)
serializer.save()
return Response(serializer.data, status=status.HTTP_200_OK)
def destroy(self, request, pk=None):
instance = get_object_or_404(self.queryset, pk=pk)
self.check_object_permissions(request, instance)
instance.delete()
serializer = AccountSerializer(instance=instance)
return Response(serializer.data, status=status.HTTP_200_OK)
......@@ -6,7 +6,7 @@ from django.db import models
from apps.accounts.models import Account
from apps.commons.managers import SoftObjectManager
from apps.constants import TIMEZONE
class CaseSubject(models.Model):
revision_id = models.UUIDField(primary_key=True, default=uuid.uuid4, editable=False)
......@@ -31,7 +31,7 @@ class CaseSubject(models.Model):
def delete(self):
if self.deleted_at is None:
self.is_active = False
self.deleted_at = datetime.now(tz=pytz.timezone("Asia/Jakarta"))
self.deleted_at = datetime.now(tz=pytz.timezone(TIMEZONE))
self.save()
......@@ -61,7 +61,7 @@ class PositiveCase(models.Model):
def delete(self):
if self.deleted_at is None:
self.is_active = False
self.deleted_at = datetime.now(tz=pytz.timezone("Asia/Jakarta"))
self.deleted_at = datetime.now(tz=pytz.timezone(TIMEZONE))
self.save()
@property
......@@ -102,7 +102,7 @@ class InvestigationCase(models.Model):
def delete(self):
if self.deleted_at is None:
self.is_active = False
self.deleted_at = datetime.now(tz=pytz.timezone("Asia/Jakarta"))
self.deleted_at = datetime.now(tz=pytz.timezone(TIMEZONE))
self.save()
@property
......@@ -164,7 +164,7 @@ class MonitoringCase(models.Model):
def delete(self):
if self.deleted_at is None:
self.is_active = False
self.deleted_at = datetime.now(tz=pytz.timezone("Asia/Jakarta"))
self.deleted_at = datetime.now(tz=pytz.timezone(TIMEZONE))
self.save()
@property
......
import json
import pytz
from datetime import datetime
from django.test import TestCase
from rest_framework import status
from rest_framework.authtoken.models import Token
from rest_framework.test import APITestCase, APIClient
from apps.accounts.tests.factories.accounts import AccountFactory, UserFactory
from apps.cases.models import CaseSubject
from apps.cases.tests.factories.case_subjects import CaseSubjectFactory
from apps.constants import HEADER_PREFIX
from apps.constants import TIMEZONE
class CaseSubjectViewTest(TestCase):
def setUp(self):
class CaseSubjectViewTest(APITestCase):
@classmethod
def setUpTestData(self):
self.user_1 = UserFactory(username="user_1", password="justpass")
self.user_2 = UserFactory(username="user_2", password="justpass")
self.admin = AccountFactory(admin=True, user=self.user_1)
self.officer = AccountFactory(admin=False, user=self.user_2)
self.token_1, _ = Token.objects.get_or_create(user=self.user_1)
self.case_subject_1 = CaseSubjectFactory(is_active=True)
self.case_subject_2 = CaseSubjectFactory(
is_active=True, deleted_at=datetime.now(tz=pytz.timezone("Asia/Jakarta"))
is_active=True, deleted_at=datetime.now(tz=pytz.timezone(TIMEZONE))
)
self.case_subject_3 = CaseSubjectFactory(is_active=False)
def test_list_case_subjects_only_shows_active_entries(self):
def setUp(self):
self.client = APIClient(HTTP_AUTHORIZATION=HEADER_PREFIX + self.token_1.key)
def test_list_case_subjects_only_shows_active_entries_success(self):
url = "/cases/case-subjects/"
response = self.client.get(url)
......@@ -111,9 +125,7 @@ class CaseSubjectViewTest(TestCase):
"sub_district": self.case_subject_1.sub_district,
}
response = self.client.post(
path=url, data=data, content_type="application/json", format="json",
)
response = self.client.post(path=url, data=data, format="json",)
response.data["is_active"] = self.case_subject_1.is_active
case_subject_current_active_count = (
......@@ -139,9 +151,7 @@ class CaseSubjectViewTest(TestCase):
"sub_district": self.case_subject_1.sub_district,
}
response = self.client.post(
path=url, data=data, content_type="application/json", format="json",
)
response = self.client.post(path=url, data=data, format="json",)
self.assertEqual(response.status_code, status.HTTP_400_BAD_REQUEST)
def test_edit_case_subject_success(self):
......@@ -162,9 +172,7 @@ class CaseSubjectViewTest(TestCase):
CaseSubject.objects.active_revisions().count()
)
response = self.client.put(
path=url, data=data, content_type="application/json", format="json",
)
response = self.client.put(path=url, data=data, format="json",)
response.data.pop("revision_id")
response.data.pop("is_active")
......@@ -194,9 +202,7 @@ class CaseSubjectViewTest(TestCase):
prev_all_case_subject_revision_count = CaseSubject.objects.all().count()
response = self.client.put(
path=url, data=data, content_type="application/json", format="json",
)
response = self.client.put(path=url, data=data, format="json",)
self.assertEqual(response.status_code, status.HTTP_400_BAD_REQUEST)
current_all_case_subject_revision_count = CaseSubject.objects.all().count()
......@@ -210,9 +216,7 @@ class CaseSubjectViewTest(TestCase):
prev_deleted_all_count = CaseSubject.objects.all(with_deleted=True).count()
prev_deleted_count = CaseSubject.objects.deleted().count()
response = self.client.delete(
path=url, content_type="application/json", format="json",
)
response = self.client.delete(path=url, format="json",)
self.assertEqual(response.status_code, status.HTTP_200_OK)
self.assertIsNotNone(
CaseSubject.objects.all(with_deleted=True)
......@@ -228,5 +232,6 @@ class CaseSubjectViewTest(TestCase):
def test_delete_inactive_case_subject_fails(self):
url = "/cases/case-subjects/" + str(self.case_subject_3.revision_id) + "/"
response = self.client.delete(url)
self.assertEqual(response.status_code, status.HTTP_404_NOT_FOUND)
import json
import pytz
from datetime import datetime
from django.test import TestCase
from rest_framework import status
from rest_framework.authtoken.models import Token
from rest_framework.test import APITestCase, APIClient
from apps.accounts.tests.factories.accounts import AccountFactory, UserFactory
from apps.cases.models import PositiveCase, InvestigationCase
......@@ -11,13 +12,17 @@ from apps.cases.tests.factories.cases import (
PositiveCaseFactory,
InvestigationCaseFactory,
)
from apps.constants import HEADER_PREFIX
from apps.constants import TIMEZONE
class InvestigationCaseViewTest(TestCase):
class InvestigationCaseViewTest(APITestCase):
@classmethod
def setUpTestData(self):
self.user = UserFactory()
self.author = AccountFactory(user=self.user, admin=False)
self.user_1 = UserFactory(username="user_1", password="justpass")
self.author = AccountFactory(user=self.user_1, admin=True)
self.token_1, _ = Token.objects.get_or_create(user=self.user_1)
self.case_subject = CaseSubjectFactory()
self.reference_case = PositiveCaseFactory(
case_subject_id=self.case_subject.subject_id, author=self.author,
......@@ -31,7 +36,7 @@ class InvestigationCaseViewTest(TestCase):
author=self.author,
case_subject_id=self.case_subject.subject_id,
reference_case_id=self.reference_case.case_id,
deleted_at=datetime.now(tz=pytz.timezone("Asia/Jakarta")),
deleted_at=datetime.now(tz=pytz.timezone(TIMEZONE)),
)
self.other_inactive_case = InvestigationCaseFactory(
author=self.author,
......@@ -40,6 +45,9 @@ class InvestigationCaseViewTest(TestCase):
is_active=False,
)
def setUp(self):
self.client = APIClient(HTTP_AUTHORIZATION=HEADER_PREFIX + self.token_1.key)
def test_list_investigation_cases_success(self):
url = "/cases/investigation-cases/"
......@@ -102,6 +110,7 @@ class InvestigationCaseViewTest(TestCase):
+ str(self.other_deleted_case.revision_id)
+ "/"
)
response = self.client.get(url)
self.assertEqual(response.status_code, status.HTTP_404_NOT_FOUND)
......@@ -124,9 +133,7 @@ class InvestigationCaseViewTest(TestCase):
"author": str(self.case.author.id),
}
response = self.client.post(
path=url, data=data, content_type="application/json", format="json",
)
response = self.client.post(path=url, data=data, format="json",)
case_current_active_count = InvestigationCase.objects.active_revisions().count()
case_current_all_count = InvestigationCase.objects.all().count()
......@@ -142,9 +149,7 @@ class InvestigationCaseViewTest(TestCase):
"author": str(self.case.author.id),
}
response = self.client.post(
path=url, data=data, content_type="application/json", format="json",
)
response = self.client.post(path=url, data=data, format="json",)
self.assertEqual(response.status_code, status.HTTP_400_BAD_REQUEST)
def test_edit_investigation_success(self):
......@@ -167,9 +172,7 @@ class InvestigationCaseViewTest(TestCase):
InvestigationCase.objects.active_revisions().count()
)
response = self.client.put(
path=url, data=data, content_type="application/json", format="json",
)
response = self.client.put(path=url, data=data, format="json",)
self.assertEqual(response.status_code, status.HTTP_200_OK)
self.assertEqual(
response.data["is_referral_needed"], not self.case.is_referral_needed
......@@ -210,9 +213,8 @@ class InvestigationCaseViewTest(TestCase):
"medical_facility_reference": self.other_inactive_case.medical_facility_reference,
"author": str(self.other_inactive_case.author.id),
}
response = self.client.put(
path=url, data=data, content_type="application/json", format="json",
)
response = self.client.put(path=url, data=data, format="json",)
self.assertEqual(response.status_code, status.HTTP_404_NOT_FOUND)
def test_edit_investigation_case_fails_with_incomplete_data(self):
......@@ -227,9 +229,8 @@ class InvestigationCaseViewTest(TestCase):
prev_active_investigation_case_revision_count = (
InvestigationCase.objects.active_revisions().count()
)
response = self.client.put(
path=url, data=data, content_type="application/json", format="json",
)
response = self.client.put(path=url, data=data, format="json",)
self.assertEqual(response.status_code, status.HTTP_400_BAD_REQUEST)
current_active_investigation_case_revision_count = (
InvestigationCase.objects.active_revisions().count()
......@@ -250,9 +251,7 @@ class InvestigationCaseViewTest(TestCase):
).count()
prev_deleted_count = InvestigationCase.objects.deleted().count()
response = self.client.delete(
path=url, content_type="application/json", format="json",
)
response = self.client.delete(path=url, format="json",)
self.assertEqual(response.status_code, status.HTTP_200_OK)
self.assertIsNotNone(
InvestigationCase.objects.all(with_deleted=True)
......@@ -274,5 +273,6 @@ class InvestigationCaseViewTest(TestCase):
+ str(self.other_inactive_case.revision_id)
+ "/"
)
response = self.client.delete(url)
self.assertEqual(response.status_code, status.HTTP_404_NOT_FOUND)
......@@ -13,7 +13,7 @@ from apps.cases.tests.factories.cases import (
InvestigationCaseFactory,
MonitoringCaseFactory,
)
from apps.constants import TIMEZONE
class MonitoringCaseViewTest(TestCase):
@classmethod
......@@ -38,7 +38,7 @@ class MonitoringCaseViewTest(TestCase):
self.other_deleted_case = MonitoringCaseFactory(
author=self.author,
positive_case_id=self.positive_case.case_id,
deleted_at=datetime.now(tz=pytz.timezone("Asia/Jakarta")),
deleted_at=datetime.now(tz=pytz.timezone(TIMEZONE)),
)
self.other_inactive_case = MonitoringCaseFactory(
author=self.author,
......
import json
import pytz
from datetime import datetime
from django.test import TestCase
from rest_framework import status
from rest_framework.authtoken.models import Token
from rest_framework.test import APITestCase, APIClient
from apps.accounts.tests.factories.accounts import AccountFactory, UserFactory
from apps.cases.models import PositiveCase
from apps.cases.tests.factories.case_subjects import CaseSubjectFactory
from apps.cases.tests.factories.cases import PositiveCaseFactory
from apps.constants import HEADER_PREFIX
from apps.constants import TIMEZONE
class PositiveCaseViewTest(TestCase):
class PositiveCaseViewTest(APITestCase):
@classmethod
def setUpTestData(self):
self.user = UserFactory()
self.author = AccountFactory(user=self.user, admin=False)
self.user_1 = UserFactory(username="user_1", password="justpass")
self.author = AccountFactory(user=self.user_1, admin=False)
self.token_1, _ = Token.objects.get_or_create(user=self.user_1)
self.case_subject = CaseSubjectFactory()
self.case = PositiveCaseFactory(
author=self.author, case_subject_id=self.case_subject.subject_id,
......@@ -22,7 +27,7 @@ class PositiveCaseViewTest(TestCase):
self.other_deleted_case = PositiveCaseFactory(
author=self.author,
case_subject_id=self.case_subject.subject_id,
deleted_at=datetime.now(tz=pytz.timezone("Asia/Jakarta")),
deleted_at=datetime.now(tz=pytz.timezone(TIMEZONE)),
)
self.other_inactive_case = PositiveCaseFactory(
author=self.author,
......@@ -30,6 +35,9 @@ class PositiveCaseViewTest(TestCase):
is_active=False,
)
def setUp(self):
self.client = APIClient(HTTP_AUTHORIZATION=HEADER_PREFIX + self.token_1.key)
def test_list_positive_cases_success(self):
url = "/cases/positive-cases/"
......@@ -100,9 +108,7 @@ class PositiveCaseViewTest(TestCase):
"author": str(self.case.author.id),
}