From 9baa99b4cd6eb16aff1d07186607cdf8f9ea7906 Mon Sep 17 00:00:00 2001 From: Harison Gachuru Date: Sat, 6 Nov 2021 17:49:55 +0300 Subject: [PATCH 01/29] Add unit tests for core views --- core/tests/test_views_.py | 93 +++++++++++++++++++++++++++++++++++++++ 1 file changed, 93 insertions(+) create mode 100644 core/tests/test_views_.py diff --git a/core/tests/test_views_.py b/core/tests/test_views_.py new file mode 100644 index 00000000..589a7c7b --- /dev/null +++ b/core/tests/test_views_.py @@ -0,0 +1,93 @@ +from django.contrib.auth.models import AnonymousUser +from django.core.exceptions import PermissionDenied +from django.test import RequestFactory, TestCase +from django.urls import reverse + +from accounts.factories import UserFactory +from core import views +from people.factories import AdultFactory + + +class IndexViewTestCase(TestCase): + def setUp(self): + self.factory = RequestFactory() + self.request = self.factory.get("dummy_path/") + self.view_class = views.IndexView + self.view_func = self.view_class.as_view() + self.view = self.view_class() + + def test_template_name(self): + self.view.setup(self.request) + template_names = self.view.get_template_names() + self.assertIn("core/index.html", template_names) + + def test_response(self): + response = self.view_func(self.request) + self.assertEqual(response.status_code, 200) + + +class LoginRedirectViewTestCase(TestCase): + def setUp(self): + self.factory = RequestFactory() + self.request = self.factory.get("dummy_path/") + self.view_class = views.LoginRedirectView + self.view_func = self.view_class.as_view() + self.view = self.view_class() + + def test_login_required(self): + self.request.user = AnonymousUser() + response = self.view_func(self.request) + self.assertEqual(response.status_code, 302) + self.assertIn(reverse("account_login"), response.url) + + def test_redirect_url_for_user_with_person(self): + # setup + user = UserFactory() + AdultFactory(user=user) + self.request.user = user + self.view.setup(self.request) + + # test + url = self.view.get_redirect_url() + self.assertEqual(url, reverse("core:dashboard")) + + def test_redirect_url_for_user_without_person(self): + self.request.user = UserFactory() + self.view.setup(self.request) + url = self.view.get_redirect_url() + self.assertEqual(url, reverse("people:adult_self_register")) + + +class DashboardViewTestCase(TestCase): + def setUp(self): + self.factory = RequestFactory() + self.request = self.factory.get("dummy_path/") + self.view_class = views.DashboardView + self.view_func = self.view_class.as_view() + self.view = self.view_class() + + def test_template_name(self): + self.view.setup(self.request) + template_names = self.view.get_template_names() + self.assertIn("core/dashboard.html", template_names) + + def test_login_required(self): + self.request.user = AnonymousUser() + response = self.view_func(self.request) + self.assertEqual(response.status_code, 302) + self.assertIn(reverse("account_login"), response.url) + + def test_response_for_user_with_person(self): + # setup + user = UserFactory() + AdultFactory(user=user) + self.request.user = user + + # test + response = self.view_func(self.request) + self.assertEqual(response.status_code, 200) + + def test_response_for_user_without_person(self): + self.request.user = UserFactory() + with self.assertRaises(PermissionDenied): + self.view_func(self.request) From 0602cd759d7b8e66d2022f41cbc168e68cf7d642 Mon Sep 17 00:00:00 2001 From: Harison Gachuru Date: Sat, 6 Nov 2021 17:50:45 +0300 Subject: [PATCH 02/29] Add unit tests for TemperatureRecordsListView --- records/tests/test_views_.py | 160 +++++++++++++++++++++++++++++++++++ 1 file changed, 160 insertions(+) create mode 100644 records/tests/test_views_.py diff --git a/records/tests/test_views_.py b/records/tests/test_views_.py new file mode 100644 index 00000000..a4dc4e3c --- /dev/null +++ b/records/tests/test_views_.py @@ -0,0 +1,160 @@ +from django.contrib.auth.models import AnonymousUser, Permission +from django.test import RequestFactory, TestCase +from django.urls import reverse + +from accounts.factories import UserFactory +from records import views +from records.factories import TemperatureRecordFactory +from records.models import TemperatureRecord + +from .helpers import search_temperature_records + + +class TemperatureRecordsListViewTestCase(TestCase): + @classmethod + def setUpClass(cls): + super().setUpClass() + + cls.authorized_user = cls.get_authorized_user() + + def setUp(self): + self.factory = RequestFactory() + self.request = self.build_get_request() + self.view_class = views.TemperatureRecordsListView + self.view_func = self.view_class.as_view() + self.view = self.view_class() + + def build_get_request(self, data=None): + return self.factory.get("dummy_path", data=data) + + @staticmethod + def get_authorized_user(): + view_temp = Permission.objects.filter(name="Can view temperature record") + return UserFactory(user_permissions=tuple(view_temp)) + + @property + def table_head(self): + thead = """ + + + # + Username + Temperature + Time + + + """ + return thead + + def test_allow_empty(self): + self.view.setup(self.request) + allow_empty = self.view.get_allow_empty() + self.assertTrue(allow_empty) + + def test_ordering(self): + self.view.setup(self.request) + ordering = self.view.get_ordering() + self.assertIsNone(ordering) + + def test_search_fields(self): + self.view.setup(self.request) + search_fields = self.view.get_search_fields_with_filters() + expected_search_fields = [ + ("person__username", "icontains"), + ("person__full_name", "icontains"), + ] + self.assertEqual(search_fields, expected_search_fields) + + def test_search_query(self): + search_term = "search query" + self.request = self.build_get_request({"q": search_term}) + self.view.setup(self.request) + search_query = self.view.get_search_query() + self.assertEqual(search_query, search_term) + + def test_queryset_without_search_query(self): + self.view.setup(self.request) + queryset = self.view.get_queryset() + self.assertQuerysetEqual(queryset, TemperatureRecord.objects.all()) + + def test_queryset_with_search_query(self): + temp_records = TemperatureRecordFactory.create_batch(10) + search_term = temp_records[0].person.full_name.split()[0] + self.request = self.build_get_request({"q": search_term}) + self.view.setup(self.request) + queryset = self.view.get_queryset() + self.assertQuerysetEqual(queryset, search_temperature_records(search_term)) + + def test_paginate_by(self): + self.view.setup(self.request) + queryset = self.view.get_queryset() + paginate_by = self.view.get_paginate_by(queryset) + self.assertEqual(paginate_by, 10) + + def test_context_object_name(self): + self.view.setup(self.request) + queryset = self.view.get_queryset() + context_object_name = self.view.get_context_object_name(queryset) + self.assertEqual(context_object_name, "temperature_records") + + def test_template_name(self): + self.view.setup(self.request) + self.view.get(self.request) + template_names = self.view.get_template_names() + self.assertIn("records/temperature_records_list.html", template_names) + + def test_login_required(self): + self.request.user = AnonymousUser() + self.view.setup(self.request) + response = self.view.dispatch(self.request) + self.assertEqual(response.status_code, 302) + self.assertIn(reverse("account_login"), response.url) + + def test_permission_required(self): + self.request.user = UserFactory() + self.view.setup(self.request) + permission_required = self.view.get_permission_required() + self.assertEqual(permission_required, ("records.view_temperaturerecord",)) + + def test_response_with_no_temperature_records(self): + # setup + self.request.user = self.authorized_user + response = self.view_func(self.request) + response.render() + + # test + with self.assertRaises(AssertionError): + self.assertInHTML(self.table_head, response.content.decode()) + self.assertInHTML( + "There are no temperature records yet!", response.content.decode() + ) + + def test_response_with_temperature_records(self): + # setup + TemperatureRecordFactory() + self.request.user = self.authorized_user + response = self.view_func(self.request) + response.render() + + # test + with self.assertRaises(AssertionError): + self.assertInHTML( + "There are no temperature records yet!", response.content.decode() + ) + self.assertInHTML(self.table_head, response.content.decode()) + + def test_response_with_no_search_results(self): + # setup + TemperatureRecordFactory.create_batch(10) + search_term = "does not exist" + self.request = self.build_get_request({"q": search_term}) + self.request.user = self.authorized_user + response = self.view_func(self.request) + response.render() + + # test + with self.assertRaises(AssertionError): + self.assertInHTML(self.table_head, response.content.decode()) + self.assertInHTML( + "Your search didn't yield any results", response.content.decode() + ) From 23a6186cc4620826c9c05eac76964065919f1f2d Mon Sep 17 00:00:00 2001 From: Harison Gachuru Date: Sat, 6 Nov 2021 17:51:22 +0300 Subject: [PATCH 03/29] Add unit tests for PeopleListView and InterpersonalRelationshipsListView --- people/tests/test_views_.py | 311 ++++++++++++++++++++++++++++++++++++ 1 file changed, 311 insertions(+) create mode 100644 people/tests/test_views_.py diff --git a/people/tests/test_views_.py b/people/tests/test_views_.py new file mode 100644 index 00000000..e6bf276f --- /dev/null +++ b/people/tests/test_views_.py @@ -0,0 +1,311 @@ +from django.contrib.auth.models import AnonymousUser, Permission +from django.test import RequestFactory, TestCase +from django.urls import reverse + +from accounts.factories import UserFactory +from people import views +from people.factories import InterpersonalRelationshipFactory, PersonFactory +from people.models import InterpersonalRelationship, Person + +from .helpers import search_interpersonal_relationships, search_people + + +class PeopleListViewTestCase(TestCase): + @classmethod + def setUpClass(cls): + super().setUpClass() + + cls.authorized_user = cls.get_authorized_user() + + def setUp(self): + self.factory = RequestFactory() + self.request = self.build_get_request() + self.view_class = views.PeopleListView + self.view_func = self.view_class.as_view() + self.view = self.view_class() + + def build_get_request(self, data=None): + return self.factory.get("dummy_path", data=data) + + @staticmethod + def get_authorized_user(): + view_person = Permission.objects.filter(name="Can view person") + return UserFactory(user_permissions=tuple(view_person)) + + @property + def table_head(self): + thead = """ + + + # + Username + Full name + Age category + Actions + + + """ + return thead + + def test_allow_empty(self): + self.view.setup(self.request) + allow_empty = self.view.get_allow_empty() + self.assertTrue(allow_empty) + + def test_ordering(self): + self.view.setup(self.request) + ordering = self.view.get_ordering() + self.assertIsNone(ordering) + + def test_search_fields(self): + self.view.setup(self.request) + search_fields = self.view.get_search_fields_with_filters() + expected_search_fields = [("username", "icontains"), ("full_name", "icontains")] + self.assertEqual(search_fields, expected_search_fields) + + def test_search_query(self): + search_term = "search query" + self.request = self.build_get_request({"q": search_term}) + self.view.setup(self.request) + search_query = self.view.get_search_query() + self.assertEqual(search_query, search_term) + + def test_queryset_without_search_query(self): + self.view.setup(self.request) + queryset = self.view.get_queryset() + self.assertQuerysetEqual(queryset, Person.objects.all()) + + def test_queryset_with_search_query(self): + people = PersonFactory.create_batch(10) + search_term = people[0].full_name.split()[0] + self.request = self.build_get_request({"q": search_term}) + self.view.setup(self.request) + queryset = self.view.get_queryset() + self.assertQuerysetEqual(queryset, search_people(search_term)) + + def test_paginate_by(self): + self.view.setup(self.request) + queryset = self.view.get_queryset() + paginate_by = self.view.get_paginate_by(queryset) + self.assertEqual(paginate_by, 10) + + def test_context_object_name(self): + self.view.setup(self.request) + queryset = self.view.get_queryset() + context_object_name = self.view.get_context_object_name(queryset) + self.assertEqual(context_object_name, "people") + + def test_template_name(self): + self.view.setup(self.request) + self.view.get(self.request) + template_names = self.view.get_template_names() + self.assertIn("people/people_list.html", template_names) + + def test_login_required(self): + self.request.user = AnonymousUser() + self.view.setup(self.request) + response = self.view.dispatch(self.request) + self.assertEqual(response.status_code, 302) + self.assertIn(reverse("account_login"), response.url) + + def test_permission_required(self): + self.request.user = UserFactory() + self.view.setup(self.request) + permission_required = self.view.get_permission_required() + self.assertEqual(permission_required, ("people.view_person",)) + + def test_response_with_no_people(self): + # setup + self.request.user = self.authorized_user + response = self.view_func(self.request) + response.render() + + # test + with self.assertRaises(AssertionError): + self.assertInHTML(self.table_head, response.content.decode()) + self.assertInHTML("There are no people yet!", response.content.decode()) + + def test_response_with_people(self): + # setup + PersonFactory() + self.request.user = self.authorized_user + response = self.view_func(self.request) + response.render() + + # test + with self.assertRaises(AssertionError): + self.assertInHTML("There are no people yet!", response.content.decode()) + self.assertInHTML(self.table_head, response.content.decode()) + + def test_response_with_no_search_results(self): + # setup + PersonFactory.create_batch(10) + search_term = "does not exist" + self.request = self.build_get_request({"q": search_term}) + self.request.user = self.authorized_user + response = self.view_func(self.request) + response.render() + + # test + with self.assertRaises(AssertionError): + self.assertInHTML(self.table_head, response.content.decode()) + self.assertInHTML( + "Your search didn't yield any results", response.content.decode() + ) + + +class InterpersonalRelationshipsListViewTestCase(TestCase): + @classmethod + def setUpClass(cls): + super().setUpClass() + + cls.authorized_user = cls.get_authorized_user() + + def setUp(self): + self.factory = RequestFactory() + self.request = self.build_get_request() + self.view_class = views.RelationshipsListView + self.view_func = self.view_class.as_view() + self.view = self.view_class() + + def build_get_request(self, data=None): + return self.factory.get("dummy_path", data=data) + + @staticmethod + def get_authorized_user(): + view_relationship = Permission.objects.filter( + name="Can view interpersonal relationship" + ) + return UserFactory(user_permissions=tuple(view_relationship)) + + @property + def table_head(self): + thead = """ + + + # + Person + Relative + Relationship type + + + """ + return thead + + def test_allow_empty(self): + self.view.setup(self.request) + allow_empty = self.view.get_allow_empty() + self.assertTrue(allow_empty) + + def test_ordering(self): + self.view.setup(self.request) + ordering = self.view.get_ordering() + self.assertIsNone(ordering) + + def test_search_fields(self): + self.view.setup(self.request) + search_fields = self.view.get_search_fields_with_filters() + expected_search_fields = [ + ("person__username", "icontains"), + ("relative__username", "icontains"), + ] + self.assertEqual(search_fields, expected_search_fields) + + def test_search_query(self): + search_term = "search query" + self.request = self.build_get_request({"q": search_term}) + self.view.setup(self.request) + search_query = self.view.get_search_query() + self.assertEqual(search_query, search_term) + + def test_queryset_without_search_query(self): + self.view.setup(self.request) + queryset = self.view.get_queryset() + self.assertQuerysetEqual(queryset, InterpersonalRelationship.objects.all()) + + def test_queryset_with_search_query(self): + relationships = InterpersonalRelationshipFactory.create_batch(10) + search_term = relationships[0].person.full_name.split()[0] + self.request = self.build_get_request({"q": search_term}) + self.view.setup(self.request) + queryset = self.view.get_queryset() + self.assertQuerysetEqual( + queryset, search_interpersonal_relationships(search_term) + ) + + def test_paginate_by(self): + self.view.setup(self.request) + queryset = self.view.get_queryset() + paginate_by = self.view.get_paginate_by(queryset) + self.assertEqual(paginate_by, 10) + + def test_context_object_name(self): + self.view.setup(self.request) + queryset = self.view.get_queryset() + context_object_name = self.view.get_context_object_name(queryset) + self.assertEqual(context_object_name, "relationships") + + def test_template_name(self): + self.view.setup(self.request) + self.view.get(self.request) + template_names = self.view.get_template_names() + self.assertIn("people/relationships_list.html", template_names) + + def test_login_required(self): + self.request.user = AnonymousUser() + self.view.setup(self.request) + response = self.view.dispatch(self.request) + self.assertEqual(response.status_code, 302) + self.assertIn(reverse("account_login"), response.url) + + def test_permission_required(self): + self.request.user = UserFactory() + self.view.setup(self.request) + permission_required = self.view.get_permission_required() + self.assertEqual( + permission_required, ("people.view_interpersonalrelationship",) + ) + + def test_response_with_no_relationships(self): + # setup + self.request.user = self.authorized_user + response = self.view_func(self.request) + response.render() + + # test + with self.assertRaises(AssertionError): + self.assertInHTML(self.table_head, response.content.decode()) + self.assertInHTML( + "There are no interpersonal relationships yet!", response.content.decode() + ) + + def test_response_with_relationships(self): + # setup + InterpersonalRelationshipFactory() + self.request.user = self.authorized_user + response = self.view_func(self.request) + response.render() + + # test + with self.assertRaises(AssertionError): + self.assertInHTML( + "There are no interpersonal relationships yet!", + response.content.decode(), + ) + self.assertInHTML(self.table_head, response.content.decode()) + + def test_response_with_no_search_results(self): + # setup + InterpersonalRelationshipFactory.create_batch(10) + search_term = "does not exist" + self.request = self.build_get_request({"q": search_term}) + self.request.user = self.authorized_user + response = self.view_func(self.request) + response.render() + + # test + with self.assertRaises(AssertionError): + self.assertInHTML(self.table_head, response.content.decode()) + self.assertInHTML( + "Your search didn't yield any results", response.content.decode() + ) From 175b00f1613baea916ab429ed0858321c4d374fa Mon Sep 17 00:00:00 2001 From: Harison Gachuru Date: Sat, 6 Nov 2021 23:18:18 +0300 Subject: [PATCH 04/29] Add the object list explicitly in list view tests --- people/tests/test_views_.py | 4 ++-- records/tests/test_views_.py | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/people/tests/test_views_.py b/people/tests/test_views_.py index e6bf276f..0c91d433 100644 --- a/people/tests/test_views_.py +++ b/people/tests/test_views_.py @@ -97,7 +97,7 @@ def test_context_object_name(self): def test_template_name(self): self.view.setup(self.request) - self.view.get(self.request) + self.view.object_list = self.view.get_queryset() template_names = self.view.get_template_names() self.assertIn("people/people_list.html", template_names) @@ -247,7 +247,7 @@ def test_context_object_name(self): def test_template_name(self): self.view.setup(self.request) - self.view.get(self.request) + self.view.object_list = self.view.get_queryset() template_names = self.view.get_template_names() self.assertIn("people/relationships_list.html", template_names) diff --git a/records/tests/test_views_.py b/records/tests/test_views_.py index a4dc4e3c..370c46b1 100644 --- a/records/tests/test_views_.py +++ b/records/tests/test_views_.py @@ -99,7 +99,7 @@ def test_context_object_name(self): def test_template_name(self): self.view.setup(self.request) - self.view.get(self.request) + self.view.object_list = self.view.get_queryset() template_names = self.view.get_template_names() self.assertIn("records/temperature_records_list.html", template_names) From c2e7331a81618666dfa40ae4dd9cd1fea44c175e Mon Sep 17 00:00:00 2001 From: Harison Gachuru Date: Sat, 6 Nov 2021 23:34:26 +0300 Subject: [PATCH 05/29] Add unit tests for PersonDetailView --- people/tests/test_views_.py | 55 +++++++++++++++++++++++++++++++++++++ 1 file changed, 55 insertions(+) diff --git a/people/tests/test_views_.py b/people/tests/test_views_.py index 0c91d433..90a296e9 100644 --- a/people/tests/test_views_.py +++ b/people/tests/test_views_.py @@ -1,4 +1,5 @@ from django.contrib.auth.models import AnonymousUser, Permission +from django.http.response import Http404 from django.test import RequestFactory, TestCase from django.urls import reverse @@ -154,6 +155,60 @@ def test_response_with_no_search_results(self): ) +class PersonDetailViewTestCase(TestCase): + def setUp(self): + self.factory = RequestFactory() + self.request = self.factory.get("dummy_path") + self.view_class = views.PersonDetailView + self.view_func = self.view_class.as_view() + self.view = self.view_class() + + def test_queryset(self): + self.view.setup(self.request) + queryset = self.view.get_queryset() + self.assertEqual(list(queryset), []) + + def test_slug_field(self): + self.view.setup(self.request) + slug_field = self.view.get_slug_field() + self.assertEqual(slug_field, "username") + + def test_object_with_existing_person(self): + person = PersonFactory() + self.view.setup(self.request, username=person.username) + obj = self.view.get_object() + self.assertEqual(obj, person) + + def test_object_with_non_existent_person(self): + self.view.setup(self.request, username="non-existent-person") + with self.assertRaises(Http404): + self.view.get_object() + + def test_context_object_name(self): + self.view.setup(self.request) + queryset = self.view.get_queryset() + context_object_name = self.view.get_context_object_name(queryset) + self.assertIsNone(context_object_name) + + def test_template_name(self): + self.view.setup(self.request) + template_names = self.view.get_template_names() + self.assertIn("people/person_detail.html", template_names) + + def test_login_required(self): + self.request.user = AnonymousUser() + self.view.setup(self.request) + response = self.view.dispatch(self.request) + self.assertEqual(response.status_code, 302) + self.assertIn(reverse("account_login"), response.url) + + def test_permission_required(self): + self.request.user = UserFactory() + self.view.setup(self.request) + permission_required = self.view.get_permission_required() + self.assertEqual(permission_required, ("people.view_person",)) + + class InterpersonalRelationshipsListViewTestCase(TestCase): @classmethod def setUpClass(cls): From 9ce7a8d11a8bb5300d05c0ec081bf38d3a661b74 Mon Sep 17 00:00:00 2001 From: Harison Gachuru Date: Thu, 18 Nov 2021 18:17:52 +0300 Subject: [PATCH 06/29] Add unit tests for class TemperatureRecordCreateView --- records/tests/test_views_.py | 164 +++++++++++++++++++++++++++++++++++ 1 file changed, 164 insertions(+) diff --git a/records/tests/test_views_.py b/records/tests/test_views_.py index 370c46b1..5190243b 100644 --- a/records/tests/test_views_.py +++ b/records/tests/test_views_.py @@ -1,8 +1,14 @@ +from unittest.mock import patch + from django.contrib.auth.models import AnonymousUser, Permission +from django.core.exceptions import ImproperlyConfigured +from django.http.response import Http404 from django.test import RequestFactory, TestCase from django.urls import reverse +from django.utils.module_loading import import_string from accounts.factories import UserFactory +from people.factories import PersonFactory from records import views from records.factories import TemperatureRecordFactory from records.models import TemperatureRecord @@ -158,3 +164,161 @@ def test_response_with_no_search_results(self): self.assertInHTML( "Your search didn't yield any results", response.content.decode() ) + + +class TemperatureRecordCreateViewTestCase(TestCase): + @classmethod + def setUpClass(cls): + super().setUpClass() + + cls.person = PersonFactory() + cls.user = UserFactory() + cls.temp_record = TemperatureRecordFactory.build(person=cls.person) + cls.form_data = { + "person": cls.person, + "body_temperature": cls.temp_record.body_temperature, + } + + def setUp(self): + self.factory = RequestFactory() + self.request = self.factory.get("dummy_path") + self.view_class = views.TemperatureRecordCreateView + self.view_func = self.view_class.as_view() + self.view = self.view_class() + + # FormMixin + def test_initial(self): + self.view.setup(self.request) + initial = self.view.get_initial() + self.assertEqual(initial, {}) + + def test_prefix(self): + self.view.setup(self.request) + prefix = self.view.get_prefix() + self.assertIsNone(prefix) + + def test_form_class(self): + self.view.setup(self.request) + form_class = self.view.get_form_class() + self.assertEqual( + form_class, import_string("records.forms.TemperatureRecordCreationForm") + ) + + def test_form_kwargs(self): + self.view.setup(self.request) + form_kwargs = { + "initial": self.view.get_initial(), + "prefix": self.view.get_prefix(), + } + self.assertEqual(self.view.get_form_kwargs(), form_kwargs) + + def test_success_url(self): + self.view.setup(self.request) + self.view.object = TemperatureRecordFactory.build() + success_url = self.view.get_success_url() + self.assertEqual(success_url, reverse("people:people_list")) + + def test_form_invalid(self): + self.request.user = self.user + self.view.object = None + self.view.setup(self.request, username=self.person.username) + form = self.view.get_form() + response = self.view.form_invalid(form) + self.assertEqual(response.status_code, 200) + + # SuccessMessageMixin + def test_success_message(self): + self.request.user = self.user + self.view.setup(self.request, username=self.person.username) + self.view.object = self.temp_record + success_message = self.view.get_success_message(self.form_data) + self.assertEqual( + success_message, + f"A temperature record for {self.person} has been added successfully.", + ) + + @patch("django.contrib.messages.success") + def test_form_valid_without_duplicate(self, mock_success): + self.request.user = self.user + self.view.setup(self.request, username=self.person.username) + form_class = self.view.get_form_class() + form = form_class(self.form_data) + response = self.view.form_valid(form) + self.assertTrue(mock_success.called) + self.assertEqual(response.status_code, 302) + + # ModelFormMixin + def test_form_valid_with_duplicate(self): + TemperatureRecordFactory(**self.form_data) + self.request.user = self.user + self.view.object = None + self.view.setup(self.request, username=self.person.username) + form_class = self.view.get_form_class() + form = form_class(self.form_data) + response = self.view.form_valid(form) + self.assertEqual(response.status_code, 200) + response.render() + error_message = f"{self.person}'s temperature record already exists" + self.assertInHTML(error_message, str(response.content)) + + # SingleObjectMixin + def test_queryset(self): + self.view.setup(self.request) + with self.assertRaises(ImproperlyConfigured): + queryset = self.view.get_queryset() + self.assertEqual(list(queryset), []) + + def test_slug_field(self): + self.view.setup(self.request) + slug_field = self.view.get_slug_field() + self.assertEqual(slug_field, "slug") + + def test_object(self): + self.view.setup(self.request, username=self.person.username) + with self.assertRaises(ImproperlyConfigured): + obj = self.view.get_object() + self.assertIsNone(obj) + + def test_person_with_existing_person(self): + self.view.setup(self.request, username=self.person.username) + obj = self.view.get_person() + self.assertEqual(obj, self.person) + + def test_person_with_non_existent_person(self): + self.view.setup(self.request, username="non-existent-person") + with self.assertRaises(Http404): + self.view.get_person() + + def test_context_object_name(self): + self.view.setup(self.request) + with self.assertRaises(ImproperlyConfigured): + queryset = self.view.get_queryset() + context_object_name = self.view.get_context_object_name(queryset) + self.assertIsNone(context_object_name) + + def test_context_data(self): + self.view.setup(self.request, username=self.person.username) + self.view.object = None + context_data = self.view.get_context_data() + self.assertEqual(list(context_data.keys()), ["form", "view", "person"]) + + # SingleObjectTemplateResponseMixin + def test_template_name(self): + self.view.setup(self.request) + template_names = self.view.get_template_names() + self.assertIn("records/temperature_record_form.html", template_names) + + # LoginRequiredMixin + def test_login_required(self): + self.request.user = AnonymousUser() + self.view.setup(self.request) + response = self.view.dispatch(self.request) + self.assertEqual(response.status_code, 302) + self.assertIn(reverse("account_login"), response.url) + + # PermissionRequiredMixin + def test_permission_required(self): + self.request.user = UserFactory() + self.view.setup(self.request) + permission_required = self.view.get_permission_required() + self.assertEqual(permission_required, ("records.add_temperaturerecord",)) From 7826bdbcb483ba2dc583ae5fd9b5ea1c87faa607 Mon Sep 17 00:00:00 2001 From: Harison Gachuru Date: Thu, 18 Nov 2021 18:35:03 +0300 Subject: [PATCH 07/29] Add comments in list and detail view unit tests --- people/tests/test_views_.py | 18 ++++++++++++++++++ records/tests/test_views_.py | 7 +++++++ 2 files changed, 25 insertions(+) diff --git a/people/tests/test_views_.py b/people/tests/test_views_.py index 90a296e9..3471c807 100644 --- a/people/tests/test_views_.py +++ b/people/tests/test_views_.py @@ -48,6 +48,7 @@ def table_head(self): """ return thead + # MultipleObjectMixin def test_allow_empty(self): self.view.setup(self.request) allow_empty = self.view.get_allow_empty() @@ -58,6 +59,7 @@ def test_ordering(self): ordering = self.view.get_ordering() self.assertIsNone(ordering) + # SearchableListMixin def test_search_fields(self): self.view.setup(self.request) search_fields = self.view.get_search_fields_with_filters() @@ -84,6 +86,7 @@ def test_queryset_with_search_query(self): queryset = self.view.get_queryset() self.assertQuerysetEqual(queryset, search_people(search_term)) + # MultipleObjectMixin def test_paginate_by(self): self.view.setup(self.request) queryset = self.view.get_queryset() @@ -96,12 +99,14 @@ def test_context_object_name(self): context_object_name = self.view.get_context_object_name(queryset) self.assertEqual(context_object_name, "people") + # MultipleObjectTemplateResponseMixin def test_template_name(self): self.view.setup(self.request) self.view.object_list = self.view.get_queryset() template_names = self.view.get_template_names() self.assertIn("people/people_list.html", template_names) + # LoginRequiredMixin def test_login_required(self): self.request.user = AnonymousUser() self.view.setup(self.request) @@ -109,12 +114,14 @@ def test_login_required(self): self.assertEqual(response.status_code, 302) self.assertIn(reverse("account_login"), response.url) + # PermissionRequiredMixin def test_permission_required(self): self.request.user = UserFactory() self.view.setup(self.request) permission_required = self.view.get_permission_required() self.assertEqual(permission_required, ("people.view_person",)) + # template logic def test_response_with_no_people(self): # setup self.request.user = self.authorized_user @@ -163,6 +170,7 @@ def setUp(self): self.view_func = self.view_class.as_view() self.view = self.view_class() + # SingleObjectMixin def test_queryset(self): self.view.setup(self.request) queryset = self.view.get_queryset() @@ -190,11 +198,13 @@ def test_context_object_name(self): context_object_name = self.view.get_context_object_name(queryset) self.assertIsNone(context_object_name) + # SingleObjectTemplateResponseMixin def test_template_name(self): self.view.setup(self.request) template_names = self.view.get_template_names() self.assertIn("people/person_detail.html", template_names) + # LoginRequiredMixin def test_login_required(self): self.request.user = AnonymousUser() self.view.setup(self.request) @@ -202,6 +212,7 @@ def test_login_required(self): self.assertEqual(response.status_code, 302) self.assertIn(reverse("account_login"), response.url) + # PermissionRequiredMixin def test_permission_required(self): self.request.user = UserFactory() self.view.setup(self.request) @@ -247,6 +258,7 @@ def table_head(self): """ return thead + # MultipleObjectMixin def test_allow_empty(self): self.view.setup(self.request) allow_empty = self.view.get_allow_empty() @@ -257,6 +269,7 @@ def test_ordering(self): ordering = self.view.get_ordering() self.assertIsNone(ordering) + # SearchableListMixin def test_search_fields(self): self.view.setup(self.request) search_fields = self.view.get_search_fields_with_filters() @@ -288,6 +301,7 @@ def test_queryset_with_search_query(self): queryset, search_interpersonal_relationships(search_term) ) + # MultipleObjectMixin def test_paginate_by(self): self.view.setup(self.request) queryset = self.view.get_queryset() @@ -300,12 +314,14 @@ def test_context_object_name(self): context_object_name = self.view.get_context_object_name(queryset) self.assertEqual(context_object_name, "relationships") + # MultipleObjectTemplateResponseMixin def test_template_name(self): self.view.setup(self.request) self.view.object_list = self.view.get_queryset() template_names = self.view.get_template_names() self.assertIn("people/relationships_list.html", template_names) + # LoginRequiredMixin def test_login_required(self): self.request.user = AnonymousUser() self.view.setup(self.request) @@ -313,6 +329,7 @@ def test_login_required(self): self.assertEqual(response.status_code, 302) self.assertIn(reverse("account_login"), response.url) + # PermissionRequiredMixin def test_permission_required(self): self.request.user = UserFactory() self.view.setup(self.request) @@ -321,6 +338,7 @@ def test_permission_required(self): permission_required, ("people.view_interpersonalrelationship",) ) + # template logic def test_response_with_no_relationships(self): # setup self.request.user = self.authorized_user diff --git a/records/tests/test_views_.py b/records/tests/test_views_.py index 5190243b..513250cb 100644 --- a/records/tests/test_views_.py +++ b/records/tests/test_views_.py @@ -52,6 +52,7 @@ def table_head(self): """ return thead + # MultipleObjectMixin def test_allow_empty(self): self.view.setup(self.request) allow_empty = self.view.get_allow_empty() @@ -62,6 +63,7 @@ def test_ordering(self): ordering = self.view.get_ordering() self.assertIsNone(ordering) + # SearchableListMixin def test_search_fields(self): self.view.setup(self.request) search_fields = self.view.get_search_fields_with_filters() @@ -91,6 +93,7 @@ def test_queryset_with_search_query(self): queryset = self.view.get_queryset() self.assertQuerysetEqual(queryset, search_temperature_records(search_term)) + # MultipleObjectMixin def test_paginate_by(self): self.view.setup(self.request) queryset = self.view.get_queryset() @@ -103,12 +106,14 @@ def test_context_object_name(self): context_object_name = self.view.get_context_object_name(queryset) self.assertEqual(context_object_name, "temperature_records") + # MultipleObjectTemplateResponseMixin def test_template_name(self): self.view.setup(self.request) self.view.object_list = self.view.get_queryset() template_names = self.view.get_template_names() self.assertIn("records/temperature_records_list.html", template_names) + # LoginRequiredMixin def test_login_required(self): self.request.user = AnonymousUser() self.view.setup(self.request) @@ -116,12 +121,14 @@ def test_login_required(self): self.assertEqual(response.status_code, 302) self.assertIn(reverse("account_login"), response.url) + # PermissionRequiredMixin def test_permission_required(self): self.request.user = UserFactory() self.view.setup(self.request) permission_required = self.view.get_permission_required() self.assertEqual(permission_required, ("records.view_temperaturerecord",)) + # template logic def test_response_with_no_temperature_records(self): # setup self.request.user = self.authorized_user From 43803d5ca36d0b89e81c9ab03a5d096e7adda5de Mon Sep 17 00:00:00 2001 From: Harison Gachuru Date: Thu, 18 Nov 2021 19:21:48 +0300 Subject: [PATCH 08/29] Add context data tests for list and detail views --- people/tests/test_views_.py | 42 ++++++++++++++++++++++++++++++++++++ records/tests/test_views_.py | 16 ++++++++++++++ 2 files changed, 58 insertions(+) diff --git a/people/tests/test_views_.py b/people/tests/test_views_.py index 3471c807..20485949 100644 --- a/people/tests/test_views_.py +++ b/people/tests/test_views_.py @@ -99,6 +99,22 @@ def test_context_object_name(self): context_object_name = self.view.get_context_object_name(queryset) self.assertEqual(context_object_name, "people") + def test_context_data(self): + self.view.setup(self.request) + queryset = self.view.get_queryset() + self.view.object_list = queryset + context_object_name = self.view.get_context_object_name(queryset) + context_data = self.view.get_context_data() + expected_context_data_keys = [ + "paginator", + "page_obj", + "is_paginated", + "object_list", + context_object_name, + "view", + ] + self.assertEqual(list(context_data.keys()), expected_context_data_keys) + # MultipleObjectTemplateResponseMixin def test_template_name(self): self.view.setup(self.request) @@ -198,6 +214,16 @@ def test_context_object_name(self): context_object_name = self.view.get_context_object_name(queryset) self.assertIsNone(context_object_name) + def test_context_data(self): + person = PersonFactory() + self.view.setup(self.request, username=person.username) + obj = self.view.get_object() + self.view.object = obj + context_object_name = self.view.get_context_object_name(obj) + context_data = self.view.get_context_data() + expected_context_data_keys = ["object", context_object_name, "view"] + self.assertEqual(list(context_data.keys()), expected_context_data_keys) + # SingleObjectTemplateResponseMixin def test_template_name(self): self.view.setup(self.request) @@ -314,6 +340,22 @@ def test_context_object_name(self): context_object_name = self.view.get_context_object_name(queryset) self.assertEqual(context_object_name, "relationships") + def test_context_data(self): + self.view.setup(self.request) + queryset = self.view.get_queryset() + self.view.object_list = queryset + context_object_name = self.view.get_context_object_name(queryset) + context_data = self.view.get_context_data() + expected_context_data_keys = [ + "paginator", + "page_obj", + "is_paginated", + "object_list", + context_object_name, + "view", + ] + self.assertEqual(list(context_data.keys()), expected_context_data_keys) + # MultipleObjectTemplateResponseMixin def test_template_name(self): self.view.setup(self.request) diff --git a/records/tests/test_views_.py b/records/tests/test_views_.py index 513250cb..486d273c 100644 --- a/records/tests/test_views_.py +++ b/records/tests/test_views_.py @@ -106,6 +106,22 @@ def test_context_object_name(self): context_object_name = self.view.get_context_object_name(queryset) self.assertEqual(context_object_name, "temperature_records") + def test_context_data(self): + self.view.setup(self.request) + queryset = self.view.get_queryset() + self.view.object_list = queryset + context_object_name = self.view.get_context_object_name(queryset) + context_data = self.view.get_context_data() + expected_context_data_keys = [ + "paginator", + "page_obj", + "is_paginated", + "object_list", + context_object_name, + "view", + ] + self.assertEqual(list(context_data.keys()), expected_context_data_keys) + # MultipleObjectTemplateResponseMixin def test_template_name(self): self.view.setup(self.request) From 9636e11bd7fac9b67e26c01524a95f16b24685d1 Mon Sep 17 00:00:00 2001 From: Harison Gachuru Date: Thu, 18 Nov 2021 19:31:12 +0300 Subject: [PATCH 09/29] Fix bugs in PersonDetailView unit tests and refactor --- people/tests/test_views_.py | 24 ++++++++++++++---------- 1 file changed, 14 insertions(+), 10 deletions(-) diff --git a/people/tests/test_views_.py b/people/tests/test_views_.py index 20485949..45b05aa3 100644 --- a/people/tests/test_views_.py +++ b/people/tests/test_views_.py @@ -179,6 +179,12 @@ def test_response_with_no_search_results(self): class PersonDetailViewTestCase(TestCase): + @classmethod + def setUpClass(cls): + super().setUpClass() + + cls.person = PersonFactory() + def setUp(self): self.factory = RequestFactory() self.request = self.factory.get("dummy_path") @@ -190,7 +196,7 @@ def setUp(self): def test_queryset(self): self.view.setup(self.request) queryset = self.view.get_queryset() - self.assertEqual(list(queryset), []) + self.assertEqual(list(queryset), [self.person]) def test_slug_field(self): self.view.setup(self.request) @@ -198,10 +204,9 @@ def test_slug_field(self): self.assertEqual(slug_field, "username") def test_object_with_existing_person(self): - person = PersonFactory() - self.view.setup(self.request, username=person.username) + self.view.setup(self.request, username=self.person.username) obj = self.view.get_object() - self.assertEqual(obj, person) + self.assertEqual(obj, self.person) def test_object_with_non_existent_person(self): self.view.setup(self.request, username="non-existent-person") @@ -209,14 +214,13 @@ def test_object_with_non_existent_person(self): self.view.get_object() def test_context_object_name(self): - self.view.setup(self.request) - queryset = self.view.get_queryset() - context_object_name = self.view.get_context_object_name(queryset) - self.assertIsNone(context_object_name) + self.view.setup(self.request, username=self.person.username) + obj = self.view.get_object() + context_object_name = self.view.get_context_object_name(obj) + self.assertEqual(context_object_name, "person") def test_context_data(self): - person = PersonFactory() - self.view.setup(self.request, username=person.username) + self.view.setup(self.request, username=self.person.username) obj = self.view.get_object() self.view.object = obj context_object_name = self.view.get_context_object_name(obj) From 4bd51945b24008877930002290b5c7c3f125189a Mon Sep 17 00:00:00 2001 From: Harison Gachuru Date: Thu, 18 Nov 2021 19:59:41 +0300 Subject: [PATCH 10/29] Fix bug in TemperatureRecordCreateViewTestCase.test_success_url --- records/tests/test_views_.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/records/tests/test_views_.py b/records/tests/test_views_.py index 486d273c..3301deab 100644 --- a/records/tests/test_views_.py +++ b/records/tests/test_views_.py @@ -237,7 +237,7 @@ def test_form_kwargs(self): def test_success_url(self): self.view.setup(self.request) - self.view.object = TemperatureRecordFactory.build() + self.view.object = self.temp_record success_url = self.view.get_success_url() self.assertEqual(success_url, reverse("people:people_list")) From 8c0000285626cc8593e3c2cf1d201416af02e162 Mon Sep 17 00:00:00 2001 From: Harison Gachuru Date: Fri, 19 Nov 2021 16:18:52 +0300 Subject: [PATCH 11/29] Fix bug in TemperatureRecordCreateViewTestCase and refactor --- records/tests/test_views_.py | 17 ++++++++++++----- 1 file changed, 12 insertions(+), 5 deletions(-) diff --git a/records/tests/test_views_.py b/records/tests/test_views_.py index 3301deab..38d4a86e 100644 --- a/records/tests/test_views_.py +++ b/records/tests/test_views_.py @@ -209,6 +209,15 @@ def setUp(self): self.view_func = self.view_class.as_view() self.view = self.view_class() + def get_form(self): + # monkey patch the form kwargs to get a form with data + # initial data doesn't work since the form's instance will + # have null values + self.view.get_form_kwargs = lambda: {"data": self.form_data} + form = self.view.get_form() + form.save(commit=False) + return form + # FormMixin def test_initial(self): self.view.setup(self.request) @@ -264,8 +273,7 @@ def test_success_message(self): def test_form_valid_without_duplicate(self, mock_success): self.request.user = self.user self.view.setup(self.request, username=self.person.username) - form_class = self.view.get_form_class() - form = form_class(self.form_data) + form = self.get_form() response = self.view.form_valid(form) self.assertTrue(mock_success.called) self.assertEqual(response.status_code, 302) @@ -274,10 +282,9 @@ def test_form_valid_without_duplicate(self, mock_success): def test_form_valid_with_duplicate(self): TemperatureRecordFactory(**self.form_data) self.request.user = self.user - self.view.object = None self.view.setup(self.request, username=self.person.username) - form_class = self.view.get_form_class() - form = form_class(self.form_data) + self.view.object = None + form = self.get_form() response = self.view.form_valid(form) self.assertEqual(response.status_code, 200) response.render() From 8e05cdb8f981d97be29ecce7735b6fe503851658 Mon Sep 17 00:00:00 2001 From: Harison Gachuru Date: Fri, 19 Nov 2021 16:26:04 +0300 Subject: [PATCH 12/29] Add unit tests for PersonCreateView --- people/tests/test_views_.py | 171 ++++++++++++++++++++++++++++++++++++ 1 file changed, 171 insertions(+) diff --git a/people/tests/test_views_.py b/people/tests/test_views_.py index 45b05aa3..71e5537d 100644 --- a/people/tests/test_views_.py +++ b/people/tests/test_views_.py @@ -1,7 +1,11 @@ +from unittest.mock import patch + from django.contrib.auth.models import AnonymousUser, Permission +from django.core.exceptions import ImproperlyConfigured from django.http.response import Http404 from django.test import RequestFactory, TestCase from django.urls import reverse +from django.utils.module_loading import import_string from accounts.factories import UserFactory from people import views @@ -250,6 +254,173 @@ def test_permission_required(self): self.assertEqual(permission_required, ("people.view_person",)) +class PersonCreateViewTestCase(TestCase): + @classmethod + def setUpClass(cls): + super().setUpClass() + + cls.user = UserFactory() + cls.person = PersonFactory.build() + cls.form_data = { + "username": cls.person.username, + "full_name": cls.person.full_name, + "gender": cls.person.gender, + "dob": cls.person.dob, + } + + def setUp(self): + self.factory = RequestFactory() + self.request = self.factory.get("dummy_path") + self.view_class = views.PersonCreateView + self.view_func = self.view_class.as_view() + self.view = self.view_class() + + def create_duplicate(self): + data = self.form_data.copy() + data["username"] = PersonFactory.build().username + data["created_by"] = self.user + PersonFactory(**data) + + def get_form(self): + # monkey patch the form kwargs to get a form with data + # initial data doesn't work since the form's instance will + # have null values + self.view.get_form_kwargs = lambda: {"data": self.form_data} + form = self.view.get_form() + form.save(commit=False) + return form + + # FormMixin + def test_initial(self): + self.view.setup(self.request) + initial = self.view.get_initial() + self.assertEqual(initial, {}) + + def test_prefix(self): + self.view.setup(self.request) + prefix = self.view.get_prefix() + self.assertIsNone(prefix) + + def test_form_class(self): + self.view.setup(self.request) + form_class = self.view.get_form_class() + self.assertEqual(form_class, import_string("people.forms.PersonCreationForm")) + + def test_form_kwargs(self): + self.view.setup(self.request) + form_kwargs = { + "initial": self.view.get_initial(), + "prefix": self.view.get_prefix(), + } + self.assertEqual(self.view.get_form_kwargs(), form_kwargs) + + def test_success_url(self): + self.view.setup(self.request) + self.view.object = self.person + success_url = self.view.get_success_url() + self.assertEqual( + success_url, + reverse( + "people:person_detail", kwargs={"username": self.form_data["username"]} + ), + ) + + def test_form_invalid(self): + self.request.user = self.user + self.view.object = None + self.view.setup(self.request) + form = self.view.get_form() + response = self.view.form_invalid(form) + self.assertEqual(response.status_code, 200) + + # SuccessMessageMixin + def test_success_message(self): + self.request.user = self.user + self.view.setup(self.request) + self.view.object = self.person + success_message = self.view.get_success_message(self.form_data) + self.assertEqual( + success_message, f"{self.person}'s information has been added successfully." + ) + + @patch("django.contrib.messages.success") + def test_form_valid_without_duplicate(self, mock_success): + self.request.user = self.user + self.view.setup(self.request) + form = self.get_form() + response = self.view.form_valid(form) + self.assertTrue(mock_success.called) + self.assertEqual(response.status_code, 302) + + # ModelFormMixin + def test_form_valid_with_duplicate(self): + # setup + self.create_duplicate() + self.request.user = self.user + self.view.setup(self.request) + self.view.object = None + form = self.get_form() + response = self.view.form_valid(form) + + # test + self.assertEqual(response.status_code, 200) + response.render() + error_message = "This person already exists" + self.assertInHTML(error_message, str(response.content)) + + # SingleObjectMixin + def test_queryset(self): + self.view.setup(self.request) + with self.assertRaises(ImproperlyConfigured): + queryset = self.view.get_queryset() + self.assertEqual(list(queryset), []) + + def test_slug_field(self): + self.view.setup(self.request) + slug_field = self.view.get_slug_field() + self.assertEqual(slug_field, "slug") + + def test_object(self): + self.view.setup(self.request) + with self.assertRaises(ImproperlyConfigured): + obj = self.view.get_object() + self.assertIsNone(obj) + + def test_context_object_name(self): + self.view.setup(self.request) + with self.assertRaises(ImproperlyConfigured): + queryset = self.view.get_queryset() + context_object_name = self.view.get_context_object_name(queryset) + self.assertIsNone(context_object_name) + + def test_context_data(self): + self.view.setup(self.request) + self.view.object = None + context_data = self.view.get_context_data() + self.assertEqual(list(context_data.keys()), ["form", "view", "action"]) + + # SingleObjectTemplateResponseMixin + def test_template_name(self): + self.view.setup(self.request) + template_names = self.view.get_template_names() + self.assertIn("people/person_form.html", template_names) + + # LoginRequiredMixin + def test_login_required(self): + self.request.user = AnonymousUser() + self.view.setup(self.request) + response = self.view.dispatch(self.request) + self.assertEqual(response.status_code, 302) + self.assertIn(reverse("account_login"), response.url) + + # PermissionRequiredMixin + def test_permission_required(self): + self.request.user = UserFactory() + self.view.setup(self.request) + permission_required = self.view.get_permission_required() + self.assertEqual(permission_required, ("people.add_person",)) + + class InterpersonalRelationshipsListViewTestCase(TestCase): @classmethod def setUpClass(cls): From 67c694e36148e8064514bf6fae4bede293bfdebf Mon Sep 17 00:00:00 2001 From: Harison Gachuru Date: Fri, 19 Nov 2021 17:03:32 +0300 Subject: [PATCH 13/29] Add unit tests for RelationshipCreateView --- people/tests/test_views_.py | 167 ++++++++++++++++++++++++++++++++++++ 1 file changed, 167 insertions(+) diff --git a/people/tests/test_views_.py b/people/tests/test_views_.py index 71e5537d..60dfa387 100644 --- a/people/tests/test_views_.py +++ b/people/tests/test_views_.py @@ -599,3 +599,170 @@ def test_response_with_no_search_results(self): self.assertInHTML( "Your search didn't yield any results", response.content.decode() ) + + +class InterpersonalRelationshipCreateViewTestCase(TestCase): + @classmethod + def setUpClass(cls): + super().setUpClass() + + cls.user = UserFactory() + cls.person = PersonFactory() + cls.relative = PersonFactory() + cls.relationship = InterpersonalRelationshipFactory.build( + person=cls.person, relative=cls.relative + ) + cls.form_data = { + "person": cls.person.username, + "relative": cls.relative.username, + "relation": cls.relationship.relation, + } + + def setUp(self): + self.factory = RequestFactory() + self.request = self.factory.get("dummy_path") + self.view_class = views.RelationshipCreateView + self.view_func = self.view_class.as_view() + self.view = self.view_class() + + def get_data(self): + data = self.form_data.copy() + data["person"] = self.person + data["relative"] = self.relative + return data + + def get_form(self): + # monkey patch the form kwargs to get a form with data + # initial data doesn't work since the form's instance will + # have null values + self.view.get_form_kwargs = lambda: {"data": self.form_data} + form = self.view.get_form() + form.save(commit=False) + return form + + # FormMixin + def test_initial(self): + self.view.setup(self.request) + initial = self.view.get_initial() + self.assertEqual(initial, {}) + + def test_prefix(self): + self.view.setup(self.request) + prefix = self.view.get_prefix() + self.assertIsNone(prefix) + + def test_form_class(self): + self.view.setup(self.request) + form_class = self.view.get_form_class() + self.assertEqual( + form_class, + import_string("people.forms.InterpersonalRelationshipCreationForm"), + ) + + def test_form_kwargs(self): + self.view.setup(self.request) + form_kwargs = { + "initial": self.view.get_initial(), + "prefix": self.view.get_prefix(), + } + self.assertEqual(self.view.get_form_kwargs(), form_kwargs) + + def test_success_url(self): + self.view.setup(self.request) + self.view.object = self.relationship + success_url = self.view.get_success_url() + self.assertEqual(success_url, reverse("people:relationships_list")) + + def test_form_invalid(self): + self.request.user = self.user + self.view.object = None + self.view.setup(self.request) + form = self.view.get_form() + response = self.view.form_invalid(form) + self.assertEqual(response.status_code, 200) + + # SuccessMessageMixin + def test_success_message(self): + self.request.user = self.user + self.view.setup(self.request) + self.view.object = self.relationship + data = self.get_data() + success_message = self.view.get_success_message(data) + people = f"{self.person} and {self.relative}" + self.assertEqual( + success_message, + f"The relationship between {people} has been added successfully.", + ) + + @patch("django.contrib.messages.success") + def test_form_valid_without_duplicate(self, mock_success): + self.request.user = self.user + self.view.setup(self.request) + form = self.get_form() + response = self.view.form_valid(form) + self.assertTrue(mock_success.called) + self.assertEqual(response.status_code, 302) + + # ModelFormMixin + def test_form_valid_with_duplicate(self): + data = self.get_data() + InterpersonalRelationshipFactory(**data) + self.request.user = self.user + self.view.setup(self.request) + self.view.object = None + error_message = "The InterpersonalRelationship could not be created " + error_message += "because the data didn't validate." + with self.assertRaisesRegex(ValueError, error_message): + self.get_form() + + # SingleObjectMixin + def test_queryset(self): + self.view.setup(self.request) + with self.assertRaises(ImproperlyConfigured): + queryset = self.view.get_queryset() + self.assertEqual(list(queryset), []) + + def test_slug_field(self): + self.view.setup(self.request) + slug_field = self.view.get_slug_field() + self.assertEqual(slug_field, "slug") + + def test_object(self): + self.view.setup(self.request) + with self.assertRaises(ImproperlyConfigured): + obj = self.view.get_object() + self.assertIsNone(obj) + + def test_context_object_name(self): + self.view.setup(self.request) + with self.assertRaises(ImproperlyConfigured): + queryset = self.view.get_queryset() + context_object_name = self.view.get_context_object_name(queryset) + self.assertIsNone(context_object_name) + + def test_context_data(self): + self.view.setup(self.request) + self.view.object = None + context_data = self.view.get_context_data() + self.assertEqual(list(context_data.keys()), ["form", "view"]) + + # SingleObjectTemplateResponseMixin + def test_template_name(self): + self.view.setup(self.request) + template_names = self.view.get_template_names() + self.assertIn("people/relationship_form.html", template_names) + + # LoginRequiredMixin + def test_login_required(self): + self.request.user = AnonymousUser() + self.view.setup(self.request) + response = self.view.dispatch(self.request) + self.assertEqual(response.status_code, 302) + self.assertIn(reverse("account_login"), response.url) + + # PermissionRequiredMixin + def test_permission_required(self): + self.request.user = UserFactory() + self.view.setup(self.request) + permission_required = self.view.get_permission_required() + self.assertEqual(permission_required, ("people.add_interpersonalrelationship",)) From 81ea1e03c5cf9b7e86a9a05a7f08493f6d34973f Mon Sep 17 00:00:00 2001 From: Harison Gachuru Date: Fri, 19 Nov 2021 17:21:07 +0300 Subject: [PATCH 14/29] Test attributes added in overridden create view form_valid method --- people/tests/test_views_.py | 4 ++++ records/tests/test_views_.py | 2 ++ 2 files changed, 6 insertions(+) diff --git a/people/tests/test_views_.py b/people/tests/test_views_.py index 60dfa387..e70c5f6c 100644 --- a/people/tests/test_views_.py +++ b/people/tests/test_views_.py @@ -351,6 +351,8 @@ def test_form_valid_without_duplicate(self, mock_success): response = self.view.form_valid(form) self.assertTrue(mock_success.called) self.assertEqual(response.status_code, 302) + person = Person.objects.get(username=self.form_data["username"]) + self.assertEqual(person.created_by, self.user) # ModelFormMixin def test_form_valid_with_duplicate(self): @@ -702,6 +704,8 @@ def test_form_valid_without_duplicate(self, mock_success): response = self.view.form_valid(form) self.assertTrue(mock_success.called) self.assertEqual(response.status_code, 302) + relationship = InterpersonalRelationship.objects.get(person=self.person) + self.assertEqual(relationship.created_by, self.user) # ModelFormMixin def test_form_valid_with_duplicate(self): diff --git a/records/tests/test_views_.py b/records/tests/test_views_.py index 38d4a86e..78770e6a 100644 --- a/records/tests/test_views_.py +++ b/records/tests/test_views_.py @@ -277,6 +277,8 @@ def test_form_valid_without_duplicate(self, mock_success): response = self.view.form_valid(form) self.assertTrue(mock_success.called) self.assertEqual(response.status_code, 302) + temp_record = TemperatureRecord.objects.get(person=self.person) + self.assertEqual(temp_record.created_by, self.user) # ModelFormMixin def test_form_valid_with_duplicate(self): From 354964282c425f7cffc84ec36134037cf2404804 Mon Sep 17 00:00:00 2001 From: Harison Gachuru Date: Fri, 19 Nov 2021 17:27:06 +0300 Subject: [PATCH 15/29] Test attribute added in overridden get_context_data method --- people/tests/test_views_.py | 1 + 1 file changed, 1 insertion(+) diff --git a/people/tests/test_views_.py b/people/tests/test_views_.py index e70c5f6c..c92dbdda 100644 --- a/people/tests/test_views_.py +++ b/people/tests/test_views_.py @@ -400,6 +400,7 @@ def test_context_data(self): self.view.object = None context_data = self.view.get_context_data() self.assertEqual(list(context_data.keys()), ["form", "view", "action"]) + self.assertEqual(context_data.get("action"), "add") # SingleObjectTemplateResponseMixin def test_template_name(self): From 84b97e3aa8416418c604589e46a142486d7e8531 Mon Sep 17 00:00:00 2001 From: Harison Gachuru Date: Fri, 19 Nov 2021 21:18:19 +0300 Subject: [PATCH 16/29] Use POST requests to test views with forms --- people/tests/test_views_.py | 48 ++++++++++++++---------------------- records/tests/test_views_.py | 18 +++++--------- 2 files changed, 25 insertions(+), 41 deletions(-) diff --git a/people/tests/test_views_.py b/people/tests/test_views_.py index c92dbdda..83a3dc5c 100644 --- a/people/tests/test_views_.py +++ b/people/tests/test_views_.py @@ -270,7 +270,7 @@ def setUpClass(cls): def setUp(self): self.factory = RequestFactory() - self.request = self.factory.get("dummy_path") + self.request = self.factory.post("dummy_path", data=self.form_data) self.view_class = views.PersonCreateView self.view_func = self.view_class.as_view() self.view = self.view_class() @@ -281,15 +281,6 @@ def create_duplicate(self): data["created_by"] = self.user PersonFactory(**data) - def get_form(self): - # monkey patch the form kwargs to get a form with data - # initial data doesn't work since the form's instance will - # have null values - self.view.get_form_kwargs = lambda: {"data": self.form_data} - form = self.view.get_form() - form.save(commit=False) - return form - # FormMixin def test_initial(self): self.view.setup(self.request) @@ -311,6 +302,8 @@ def test_form_kwargs(self): form_kwargs = { "initial": self.view.get_initial(), "prefix": self.view.get_prefix(), + "data": self.request.POST, + "files": self.request.FILES, } self.assertEqual(self.view.get_form_kwargs(), form_kwargs) @@ -327,8 +320,8 @@ def test_success_url(self): def test_form_invalid(self): self.request.user = self.user - self.view.object = None self.view.setup(self.request) + self.view.object = None form = self.view.get_form() response = self.view.form_invalid(form) self.assertEqual(response.status_code, 200) @@ -347,7 +340,8 @@ def test_success_message(self): def test_form_valid_without_duplicate(self, mock_success): self.request.user = self.user self.view.setup(self.request) - form = self.get_form() + form = self.view.get_form() + self.assertTrue(form.is_valid()) response = self.view.form_valid(form) self.assertTrue(mock_success.called) self.assertEqual(response.status_code, 302) @@ -361,7 +355,8 @@ def test_form_valid_with_duplicate(self): self.request.user = self.user self.view.setup(self.request) self.view.object = None - form = self.get_form() + form = self.view.get_form() + self.assertTrue(form.is_valid()) response = self.view.form_valid(form) # test @@ -623,7 +618,7 @@ def setUpClass(cls): def setUp(self): self.factory = RequestFactory() - self.request = self.factory.get("dummy_path") + self.request = self.factory.post("dummy_path", data=self.form_data) self.view_class = views.RelationshipCreateView self.view_func = self.view_class.as_view() self.view = self.view_class() @@ -634,15 +629,6 @@ def get_data(self): data["relative"] = self.relative return data - def get_form(self): - # monkey patch the form kwargs to get a form with data - # initial data doesn't work since the form's instance will - # have null values - self.view.get_form_kwargs = lambda: {"data": self.form_data} - form = self.view.get_form() - form.save(commit=False) - return form - # FormMixin def test_initial(self): self.view.setup(self.request) @@ -667,6 +653,8 @@ def test_form_kwargs(self): form_kwargs = { "initial": self.view.get_initial(), "prefix": self.view.get_prefix(), + "data": self.request.POST, + "files": self.request.FILES, } self.assertEqual(self.view.get_form_kwargs(), form_kwargs) @@ -678,8 +666,8 @@ def test_success_url(self): def test_form_invalid(self): self.request.user = self.user - self.view.object = None self.view.setup(self.request) + self.view.object = None form = self.view.get_form() response = self.view.form_invalid(form) self.assertEqual(response.status_code, 200) @@ -701,7 +689,8 @@ def test_success_message(self): def test_form_valid_without_duplicate(self, mock_success): self.request.user = self.user self.view.setup(self.request) - form = self.get_form() + form = self.view.get_form() + self.assertTrue(form.is_valid()) response = self.view.form_valid(form) self.assertTrue(mock_success.called) self.assertEqual(response.status_code, 302) @@ -715,10 +704,11 @@ def test_form_valid_with_duplicate(self): self.request.user = self.user self.view.setup(self.request) self.view.object = None - error_message = "The InterpersonalRelationship could not be created " - error_message += "because the data didn't validate." - with self.assertRaisesRegex(ValueError, error_message): - self.get_form() + form = self.view.get_form() + self.assertFalse(form.is_valid()) + self.assertEqual( + form.errors, {"__all__": ["This interpersonal relationship already exists"]} + ) # SingleObjectMixin def test_queryset(self): diff --git a/records/tests/test_views_.py b/records/tests/test_views_.py index 78770e6a..3a70ede0 100644 --- a/records/tests/test_views_.py +++ b/records/tests/test_views_.py @@ -204,20 +204,11 @@ def setUpClass(cls): def setUp(self): self.factory = RequestFactory() - self.request = self.factory.get("dummy_path") + self.request = self.factory.post("dummy_path", data=self.form_data) self.view_class = views.TemperatureRecordCreateView self.view_func = self.view_class.as_view() self.view = self.view_class() - def get_form(self): - # monkey patch the form kwargs to get a form with data - # initial data doesn't work since the form's instance will - # have null values - self.view.get_form_kwargs = lambda: {"data": self.form_data} - form = self.view.get_form() - form.save(commit=False) - return form - # FormMixin def test_initial(self): self.view.setup(self.request) @@ -241,6 +232,8 @@ def test_form_kwargs(self): form_kwargs = { "initial": self.view.get_initial(), "prefix": self.view.get_prefix(), + "data": self.request.POST, + "files": self.request.FILES, } self.assertEqual(self.view.get_form_kwargs(), form_kwargs) @@ -252,8 +245,8 @@ def test_success_url(self): def test_form_invalid(self): self.request.user = self.user - self.view.object = None self.view.setup(self.request, username=self.person.username) + self.view.object = None form = self.view.get_form() response = self.view.form_invalid(form) self.assertEqual(response.status_code, 200) @@ -273,7 +266,8 @@ def test_success_message(self): def test_form_valid_without_duplicate(self, mock_success): self.request.user = self.user self.view.setup(self.request, username=self.person.username) - form = self.get_form() + form = self.view.get_form() + self.assertTrue(form.is_valid()) response = self.view.form_valid(form) self.assertTrue(mock_success.called) self.assertEqual(response.status_code, 302) From a3fffde7242485b03daca88fa9e58ca7c32d29a4 Mon Sep 17 00:00:00 2001 From: Harison Gachuru Date: Fri, 19 Nov 2021 21:19:20 +0300 Subject: [PATCH 17/29] Add unit tests for PersonUpdateView --- people/tests/test_views_.py | 139 ++++++++++++++++++++++++++++++++++++ 1 file changed, 139 insertions(+) diff --git a/people/tests/test_views_.py b/people/tests/test_views_.py index 83a3dc5c..0c095086 100644 --- a/people/tests/test_views_.py +++ b/people/tests/test_views_.py @@ -419,6 +419,145 @@ def test_permission_required(self): self.assertEqual(permission_required, ("people.add_person",)) +class PersonUpdateViewTestCase(TestCase): + @classmethod + def setUpClass(cls): + super().setUpClass() + + cls.user = UserFactory() + cls.person = PersonFactory() + cls.form_data = { + "username": cls.person.username, + "full_name": cls.person.full_name, + "gender": cls.person.gender, + "dob": cls.person.dob, + } + + def setUp(self): + self.factory = RequestFactory() + self.request = self.factory.post("dummy_path", data=self.form_data) + self.view_class = views.PersonUpdateView + self.view_func = self.view_class.as_view() + self.view = self.view_class() + + # FormMixin + def test_initial(self): + self.view.setup(self.request) + initial = self.view.get_initial() + self.assertEqual(initial, {}) + + def test_prefix(self): + self.view.setup(self.request) + prefix = self.view.get_prefix() + self.assertIsNone(prefix) + + def test_form_class(self): + self.view.setup(self.request) + form_class = self.view.get_form_class() + self.assertEqual(form_class, import_string("people.forms.PersonUpdateForm")) + + def test_form_kwargs(self): + self.view.setup(self.request) + form_kwargs = { + "initial": self.view.get_initial(), + "prefix": self.view.get_prefix(), + "data": self.request.POST, + "files": self.request.FILES, + } + self.assertEqual(self.view.get_form_kwargs(), form_kwargs) + + def test_success_url(self): + self.view.setup(self.request) + self.view.object = self.person + success_url = self.view.get_success_url() + self.assertEqual( + success_url, + reverse( + "people:person_detail", kwargs={"username": self.form_data["username"]} + ), + ) + + def test_form_invalid(self): + self.request.user = self.user + self.view.setup(self.request) + self.view.object = None + form = self.view.get_form() + response = self.view.form_invalid(form) + self.assertEqual(response.status_code, 200) + + # SuccessMessageMixin + def test_success_message(self): + self.request.user = self.user + self.view.setup(self.request) + self.view.object = self.person + success_message = self.view.get_success_message(self.form_data) + self.assertEqual( + success_message, + f"{self.person}'s information has been updated successfully.", + ) + + @patch("django.contrib.messages.success") + def test_form_valid(self, mock_success): + self.request.user = self.user + self.view.setup(self.request, username=self.person.username) + self.view.object = self.view.get_object() + form = self.view.get_form() + self.assertTrue(form.is_valid()) + response = self.view.form_valid(form) + self.assertTrue(mock_success.called) + self.assertEqual(response.status_code, 302) + + # SingleObjectMixin + def test_queryset(self): + self.view.setup(self.request) + queryset = self.view.get_queryset() + self.assertEqual(list(queryset), [self.person]) + + def test_slug_field(self): + self.view.setup(self.request) + slug_field = self.view.get_slug_field() + self.assertEqual(slug_field, "username") + + def test_object(self): + self.view.setup(self.request, username=self.person.username) + obj = self.view.get_object() + self.assertEqual(obj, self.person) + + def test_context_object_name(self): + self.view.setup(self.request, username=self.person.username) + obj = self.view.get_object() + context_object_name = self.view.get_context_object_name(obj) + self.assertEqual(context_object_name, "person") + + def test_context_data(self): + self.view.setup(self.request) + self.view.object = None + context_data = self.view.get_context_data() + self.assertEqual(list(context_data.keys()), ["form", "view", "action"]) + self.assertEqual(context_data.get("action"), "update") + + # SingleObjectTemplateResponseMixin + def test_template_name(self): + self.view.setup(self.request) + template_names = self.view.get_template_names() + self.assertIn("people/person_form.html", template_names) + + # LoginRequiredMixin + def test_login_required(self): + self.request.user = AnonymousUser() + self.view.setup(self.request) + response = self.view.dispatch(self.request) + self.assertEqual(response.status_code, 302) + self.assertIn(reverse("account_login"), response.url) + + # PermissionRequiredMixin + def test_permission_required(self): + self.request.user = UserFactory() + self.view.setup(self.request) + permission_required = self.view.get_permission_required() + self.assertEqual(permission_required, ("people.change_person",)) + + class InterpersonalRelationshipsListViewTestCase(TestCase): @classmethod def setUpClass(cls): From f4e2a740878c4dcf55f2d3bb650b014955d5983c Mon Sep 17 00:00:00 2001 From: Harison Gachuru Date: Fri, 19 Nov 2021 21:22:02 +0300 Subject: [PATCH 18/29] Fix bug in TemperatureRecordCreateViewTestCase --- records/tests/test_views_.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/records/tests/test_views_.py b/records/tests/test_views_.py index 3a70ede0..23201eea 100644 --- a/records/tests/test_views_.py +++ b/records/tests/test_views_.py @@ -280,7 +280,7 @@ def test_form_valid_with_duplicate(self): self.request.user = self.user self.view.setup(self.request, username=self.person.username) self.view.object = None - form = self.get_form() + form = self.view.get_form() response = self.view.form_valid(form) self.assertEqual(response.status_code, 200) response.render() From 305d3c1e9a0f30ed115d24e408a581286306e7db Mon Sep 17 00:00:00 2001 From: Harison Gachuru Date: Sat, 4 Dec 2021 22:18:16 +0300 Subject: [PATCH 19/29] Add unit tests for AdultCreateView --- people/tests/test_views_.py | 174 +++++++++++++++++++++++++++++++++++- 1 file changed, 173 insertions(+), 1 deletion(-) diff --git a/people/tests/test_views_.py b/people/tests/test_views_.py index 0c095086..eb35a48c 100644 --- a/people/tests/test_views_.py +++ b/people/tests/test_views_.py @@ -9,7 +9,11 @@ from accounts.factories import UserFactory from people import views -from people.factories import InterpersonalRelationshipFactory, PersonFactory +from people.factories import ( + AdultFactory, + InterpersonalRelationshipFactory, + PersonFactory, +) from people.models import InterpersonalRelationship, Person from .helpers import search_interpersonal_relationships, search_people @@ -419,6 +423,174 @@ def test_permission_required(self): self.assertEqual(permission_required, ("people.add_person",)) +class AdultCreateViewTestCase(TestCase): + @classmethod + def setUpClass(cls): + super().setUpClass() + + cls.user = UserFactory() + cls.person = AdultFactory.build() + cls.form_data = { + "username": cls.person.username, + "full_name": cls.person.full_name, + "gender": cls.person.gender, + "dob": cls.person.dob, + "phone_number": cls.person.phone_number, + } + + def setUp(self): + self.factory = RequestFactory() + self.request = self.factory.post("dummy_path", data=self.form_data) + self.view_class = views.AdultCreateView + self.view_func = self.view_class.as_view() + self.view = self.view_class() + + def create_duplicate(self): + data = self.form_data.copy() + data["username"] = AdultFactory.build().username + data["created_by"] = self.user + AdultFactory(**data) + + # FormMixin + def test_initial(self): + self.view.setup(self.request) + initial = self.view.get_initial() + self.assertEqual(initial, {}) + + def test_prefix(self): + self.view.setup(self.request) + prefix = self.view.get_prefix() + self.assertIsNone(prefix) + + def test_form_class(self): + self.view.setup(self.request) + form_class = self.view.get_form_class() + self.assertEqual(form_class, import_string("people.forms.AdultCreationForm")) + + def test_form_kwargs(self): + self.view.setup(self.request) + form_kwargs = { + "initial": self.view.get_initial(), + "prefix": self.view.get_prefix(), + "data": self.request.POST, + "files": self.request.FILES, + } + self.assertEqual(self.view.get_form_kwargs(), form_kwargs) + + def test_success_url(self): + self.view.setup(self.request) + self.view.object = self.person + success_url = self.view.get_success_url() + self.assertEqual( + success_url, + reverse( + "people:person_detail", kwargs={"username": self.form_data["username"]} + ), + ) + + def test_form_invalid(self): + self.request.user = self.user + self.view.setup(self.request) + self.view.object = None + form = self.view.get_form() + response = self.view.form_invalid(form) + self.assertEqual(response.status_code, 200) + + # SuccessMessageMixin + def test_success_message(self): + self.request.user = self.user + self.view.setup(self.request) + self.view.object = self.person + success_message = self.view.get_success_message(self.form_data) + self.assertEqual( + success_message, f"{self.person}'s information has been added successfully." + ) + + @patch("django.contrib.messages.success") + def test_form_valid_without_duplicate(self, mock_success): + self.request.user = self.user + self.view.setup(self.request) + form = self.view.get_form() + self.assertTrue(form.is_valid()) + response = self.view.form_valid(form) + self.assertTrue(mock_success.called) + self.assertEqual(response.status_code, 302) + person = Person.objects.get(username=self.form_data["username"]) + self.assertEqual(person.created_by, self.user) + + # ModelFormMixin + def test_form_valid_with_duplicate(self): + # setup + self.create_duplicate() + self.request.user = self.user + self.view.setup(self.request) + self.view.object = None + form = self.view.get_form() + self.assertTrue(form.is_valid()) + response = self.view.form_valid(form) + + # test + self.assertEqual(response.status_code, 200) + response.render() + error_message = "This person already exists" + self.assertInHTML(error_message, str(response.content)) + + # SingleObjectMixin + def test_queryset(self): + self.view.setup(self.request) + with self.assertRaises(ImproperlyConfigured): + queryset = self.view.get_queryset() + self.assertEqual(list(queryset), []) + + def test_slug_field(self): + self.view.setup(self.request) + slug_field = self.view.get_slug_field() + self.assertEqual(slug_field, "slug") + + def test_object(self): + self.view.setup(self.request) + with self.assertRaises(ImproperlyConfigured): + obj = self.view.get_object() + self.assertIsNone(obj) + + def test_context_object_name(self): + self.view.setup(self.request) + with self.assertRaises(ImproperlyConfigured): + queryset = self.view.get_queryset() + context_object_name = self.view.get_context_object_name(queryset) + self.assertIsNone(context_object_name) + + def test_context_data(self): + self.view.setup(self.request) + self.view.object = None + context_data = self.view.get_context_data() + self.assertEqual( + list(context_data.keys()), ["form", "view", "action", "age_category"] + ) + self.assertEqual(context_data.get("action"), "add") + + # SingleObjectTemplateResponseMixin + def test_template_name(self): + self.view.setup(self.request) + template_names = self.view.get_template_names() + self.assertIn("people/person_form.html", template_names) + + # LoginRequiredMixin + def test_login_required(self): + self.request.user = AnonymousUser() + self.view.setup(self.request) + response = self.view.dispatch(self.request) + self.assertEqual(response.status_code, 302) + self.assertIn(reverse("account_login"), response.url) + + # PermissionRequiredMixin + def test_permission_required(self): + self.request.user = UserFactory() + self.view.setup(self.request) + permission_required = self.view.get_permission_required() + self.assertEqual(permission_required, ("people.add_person",)) + + class PersonUpdateViewTestCase(TestCase): @classmethod def setUpClass(cls): From 772d5a447ed53aaec9766408bb66e0d48d16ddf5 Mon Sep 17 00:00:00 2001 From: Harison Gachuru Date: Sat, 4 Dec 2021 22:25:22 +0300 Subject: [PATCH 20/29] Add unit tests for AdultSelfRegisterView --- people/tests/test_views_.py | 164 ++++++++++++++++++++++++++++++++++++ 1 file changed, 164 insertions(+) diff --git a/people/tests/test_views_.py b/people/tests/test_views_.py index eb35a48c..5be93cc7 100644 --- a/people/tests/test_views_.py +++ b/people/tests/test_views_.py @@ -591,6 +591,170 @@ def test_permission_required(self): self.assertEqual(permission_required, ("people.add_person",)) +class AdultSelfRegisterViewTestCase(TestCase): + @classmethod + def setUpClass(cls): + super().setUpClass() + + cls.user = UserFactory() + cls.person = AdultFactory.build() + cls.form_data = { + "username": cls.person.username, + "full_name": cls.person.full_name, + "gender": cls.person.gender, + "dob": cls.person.dob, + "phone_number": cls.person.phone_number, + } + + def setUp(self): + self.factory = RequestFactory() + self.request = self.factory.post("dummy_path", data=self.form_data) + self.view_class = views.AdultSelfRegisterView + self.view_func = self.view_class.as_view() + self.view = self.view_class() + + def create_duplicate(self): + data = self.form_data.copy() + data["username"] = AdultFactory.build().username + data["created_by"] = self.user + AdultFactory(**data) + + # FormMixin + def test_initial(self): + self.view.setup(self.request) + initial = self.view.get_initial() + self.assertEqual(initial, {}) + + def test_prefix(self): + self.view.setup(self.request) + prefix = self.view.get_prefix() + self.assertIsNone(prefix) + + def test_form_class(self): + self.view.setup(self.request) + form_class = self.view.get_form_class() + self.assertEqual(form_class, import_string("people.forms.AdultCreationForm")) + + def test_form_kwargs(self): + self.view.setup(self.request) + form_kwargs = { + "initial": self.view.get_initial(), + "prefix": self.view.get_prefix(), + "data": self.request.POST, + "files": self.request.FILES, + } + self.assertEqual(self.view.get_form_kwargs(), form_kwargs) + + def test_success_url(self): + self.view.setup(self.request) + self.view.object = self.person + success_url = self.view.get_success_url() + self.assertEqual(success_url, reverse("core:dashboard")) + + def test_form_invalid(self): + self.request.user = self.user + self.view.setup(self.request) + self.view.object = None + form = self.view.get_form() + response = self.view.form_invalid(form) + self.assertEqual(response.status_code, 200) + + # SuccessMessageMixin + def test_success_message(self): + self.request.user = self.user + self.view.setup(self.request) + self.view.object = self.person + success_message = self.view.get_success_message(self.form_data) + self.assertEqual( + success_message, f"{self.person}'s information has been added successfully." + ) + + @patch("django.contrib.messages.success") + def test_form_valid_without_duplicate(self, mock_success): + self.request.user = self.user + self.view.setup(self.request) + form = self.view.get_form() + self.assertTrue(form.is_valid()) + response = self.view.form_valid(form) + self.assertTrue(mock_success.called) + self.assertEqual(response.status_code, 302) + person = Person.objects.get(username=self.form_data["username"]) + self.assertEqual(person.created_by, self.user) + self.assertEqual(person.user, self.user) + + # ModelFormMixin + def test_form_valid_with_duplicate(self): + # setup + self.create_duplicate() + self.request.user = self.user + self.view.setup(self.request) + self.view.object = None + form = self.view.get_form() + self.assertTrue(form.is_valid()) + response = self.view.form_valid(form) + + # test + self.assertEqual(response.status_code, 200) + response.render() + error_message = "This person already exists" + self.assertInHTML(error_message, str(response.content)) + + # SingleObjectMixin + def test_queryset(self): + self.view.setup(self.request) + with self.assertRaises(ImproperlyConfigured): + queryset = self.view.get_queryset() + self.assertEqual(list(queryset), []) + + def test_slug_field(self): + self.view.setup(self.request) + slug_field = self.view.get_slug_field() + self.assertEqual(slug_field, "slug") + + def test_object(self): + self.view.setup(self.request) + with self.assertRaises(ImproperlyConfigured): + obj = self.view.get_object() + self.assertIsNone(obj) + + def test_context_object_name(self): + self.view.setup(self.request) + with self.assertRaises(ImproperlyConfigured): + queryset = self.view.get_queryset() + context_object_name = self.view.get_context_object_name(queryset) + self.assertIsNone(context_object_name) + + def test_context_data(self): + self.view.setup(self.request) + self.view.object = None + context_data = self.view.get_context_data() + self.assertEqual( + list(context_data.keys()), ["form", "view", "action", "age_category"] + ) + self.assertEqual(context_data.get("action"), "add") + + # SingleObjectTemplateResponseMixin + def test_template_name(self): + self.view.setup(self.request) + template_names = self.view.get_template_names() + self.assertIn("people/self_register_form.html", template_names) + + # LoginRequiredMixin + def test_login_required(self): + self.request.user = AnonymousUser() + self.view.setup(self.request) + response = self.view.dispatch(self.request) + self.assertEqual(response.status_code, 302) + self.assertIn(reverse("account_login"), response.url) + + # PermissionRequiredMixin + def test_permission_required(self): + self.request.user = UserFactory() + self.view.setup(self.request) + permission_required = self.view.get_permission_required() + self.assertEqual(permission_required, tuple()) + + class PersonUpdateViewTestCase(TestCase): @classmethod def setUpClass(cls): From be335a94cac6746689e15c640de13371b20cd8fd Mon Sep 17 00:00:00 2001 From: Harison Gachuru Date: Sat, 4 Dec 2021 23:48:08 +0300 Subject: [PATCH 21/29] Add unit tests for ChildCreateView --- people/tests/test_views_.py | 238 +++++++++++++++++++++++++++++++++++- 1 file changed, 237 insertions(+), 1 deletion(-) diff --git a/people/tests/test_views_.py b/people/tests/test_views_.py index 5be93cc7..b1e713ce 100644 --- a/people/tests/test_views_.py +++ b/people/tests/test_views_.py @@ -1,4 +1,4 @@ -from unittest.mock import patch +from unittest.mock import call, patch from django.contrib.auth.models import AnonymousUser, Permission from django.core.exceptions import ImproperlyConfigured @@ -11,6 +11,7 @@ from people import views from people.factories import ( AdultFactory, + ChildFactory, InterpersonalRelationshipFactory, PersonFactory, ) @@ -568,6 +569,7 @@ def test_context_data(self): list(context_data.keys()), ["form", "view", "action", "age_category"] ) self.assertEqual(context_data.get("action"), "add") + self.assertEqual(context_data.get("age_category"), "an adult") # SingleObjectTemplateResponseMixin def test_template_name(self): @@ -732,6 +734,7 @@ def test_context_data(self): list(context_data.keys()), ["form", "view", "action", "age_category"] ) self.assertEqual(context_data.get("action"), "add") + self.assertEqual(context_data.get("age_category"), "an adult") # SingleObjectTemplateResponseMixin def test_template_name(self): @@ -755,6 +758,239 @@ def test_permission_required(self): self.assertEqual(permission_required, tuple()) +class ChildCreateViewTestCase(TestCase): + @classmethod + def setUpClass(cls): + super().setUpClass() + + cls.user = UserFactory() + cls.parent = AdultFactory(user=cls.user) + cls.person = ChildFactory.build() + cls.form_data = { + "username": cls.person.username, + "full_name": cls.person.full_name, + "gender": cls.person.gender, + "dob": cls.person.dob, + } + + def setUp(self): + self.factory = RequestFactory() + self.request = self.build_post_request(self.form_data) + self.view_class = views.ChildCreateView + self.view_func = self.view_class.as_view() + self.view = self.view_class() + + def build_post_request(self, data=None): + return self.factory.post("dummy_path", data=data) + + def create_duplicate(self): + data = self.form_data.copy() + data["username"] = ChildFactory.build().username + data["created_by"] = self.user + ChildFactory(**data) + + # FormMixin + def test_initial(self): + self.view.setup(self.request) + initial = self.view.get_initial() + self.assertEqual(initial, {}) + + def test_prefix(self): + self.view.setup(self.request) + prefix = self.view.get_prefix() + self.assertIsNone(prefix) + + def test_form_class(self): + self.view.setup(self.request) + form_class = self.view.get_form_class() + self.assertEqual(form_class, import_string("people.forms.ChildCreationForm")) + + def test_form_kwargs(self): + self.view.setup(self.request) + form_kwargs = { + "initial": self.view.get_initial(), + "prefix": self.view.get_prefix(), + "data": self.request.POST, + "files": self.request.FILES, + } + self.assertEqual(self.view.get_form_kwargs(), form_kwargs) + + def test_success_url_when_creator_is_the_parent(self): + self.view.setup(self.request) + self.view.object = self.person + success_url = self.view.get_success_url(is_parent=True) + self.assertEqual(success_url, reverse("core:dashboard")) + + def test_success_url_when_creator_is_not_the_parent(self): + self.view.setup(self.request) + self.view.object = self.person + success_url = self.view.get_success_url() + self.assertEqual( + success_url, + reverse( + "people:parent_child_relationship_create", + kwargs={"username": self.person.username}, + ), + ) + + def test_form_invalid(self): + self.request.user = self.user + self.view.setup(self.request) + self.view.object = None + form = self.view.get_form() + response = self.view.form_invalid(form) + self.assertEqual(response.status_code, 200) + + # SuccessMessageMixin + def test_success_message(self): + self.request.user = self.user + self.view.setup(self.request) + self.view.object = self.person + success_message = self.view.get_success_message(self.form_data) + self.assertEqual( + success_message, f"{self.person}'s information has been added successfully." + ) + + @patch("django.contrib.messages.success") + def test_form_valid_when_creator_is_not_the_parent(self, mock_success): + self.request.user = self.user + self.view.setup(self.request) + form = self.view.get_form() + self.assertTrue(form.is_valid()) + response = self.view.form_valid(form) + self.assertTrue(mock_success.called) + self.assertEqual(response.status_code, 302) + person = Person.objects.get(username=self.form_data["username"]) + self.assertEqual(person.created_by, self.user) + self.assertEqual(person.user, None) + + @patch("django.contrib.messages.info") + def test_create_relationship(self, mock_info): + # setup + child = ChildFactory(**self.form_data) + self.request.user = self.user + self.view.setup(self.request) + self.view.object = child + self.view.create_relationship() + + # test + relationship = InterpersonalRelationship.objects.get(relative=child) + self.assertEqual(relationship.relation, "PC") + self.assertEqual(relationship.person, self.parent) + self.assertEqual(relationship.created_by, self.user) + self.assertTrue(mock_info.called) + message = f"A parent-child relationship between {self.parent} and {child}" + message += " has been added." + self.assertEqual(mock_info.call_args, call(self.request, message)) + + @patch("django.contrib.messages.success") + @patch("django.contrib.messages.info") + def test_form_valid_when_creator_is_the_parent(self, mock_success, mock_info): + # setup + data = self.form_data.copy() + data["is_parent"] = True + self.request = self.build_post_request(data) + self.request.user = self.user + self.view.setup(self.request) + form = self.view.get_form() + + # test + self.assertTrue(form.is_valid()) + response = self.view.form_valid(form) + self.assertTrue(mock_success.called) + self.assertEqual(response.status_code, 302) + person = Person.objects.get(username=self.form_data["username"]) + self.assertEqual(person.created_by, self.user) + self.assertEqual(person.user, None) + self.assertTrue(mock_info.called) + + # ModelFormMixin + def test_form_valid_with_duplicate(self): + # setup + self.create_duplicate() + self.request.user = self.user + self.view.setup(self.request) + self.view.object = None + form = self.view.get_form() + self.assertTrue(form.is_valid()) + response = self.view.form_valid(form) + + # test + self.assertEqual(response.status_code, 200) + response.render() + error_message = "This person already exists" + self.assertInHTML(error_message, str(response.content)) + + # SingleObjectMixin + def test_queryset(self): + self.view.setup(self.request) + with self.assertRaises(ImproperlyConfigured): + queryset = self.view.get_queryset() + self.assertEqual(list(queryset), []) + + def test_slug_field(self): + self.view.setup(self.request) + slug_field = self.view.get_slug_field() + self.assertEqual(slug_field, "slug") + + def test_object(self): + self.view.setup(self.request) + with self.assertRaises(ImproperlyConfigured): + obj = self.view.get_object() + self.assertIsNone(obj) + + def test_context_object_name(self): + self.view.setup(self.request) + with self.assertRaises(ImproperlyConfigured): + queryset = self.view.get_queryset() + context_object_name = self.view.get_context_object_name(queryset) + self.assertIsNone(context_object_name) + + def test_context_data(self): + self.view.setup(self.request) + self.view.object = None + context_data = self.view.get_context_data() + self.assertEqual( + list(context_data.keys()), ["form", "view", "action", "age_category"] + ) + self.assertEqual(context_data.get("action"), "add") + self.assertEqual(context_data.get("age_category"), "a child") + + # SingleObjectTemplateResponseMixin + def test_template_name(self): + self.view.setup(self.request) + template_names = self.view.get_template_names() + self.assertIn("people/person_form.html", template_names) + + # LoginRequiredMixin + def test_login_required(self): + self.request.user = AnonymousUser() + self.view.setup(self.request) + response = self.view.dispatch(self.request) + self.assertEqual(response.status_code, 302) + self.assertIn(reverse("account_login"), response.url) + + # PermissionRequiredMixin + def test_permission_required(self): + self.request.user = UserFactory() + self.view.setup(self.request) + permission_required = self.view.get_permission_required() + self.assertEqual(permission_required, tuple()) + + # UserPassesTestMixin + def test_test_func_false(self): + self.request.user = UserFactory() + self.view.setup(self.request) + self.assertFalse(self.view.test_func()) + + def test_test_func_true(self): + user = UserFactory() + AdultFactory(user=user) + self.request.user = user + self.view.setup(self.request) + self.assertTrue(self.view.test_func()) + + class PersonUpdateViewTestCase(TestCase): @classmethod def setUpClass(cls): From 71e716128f51c1f9c9667a4c2def41ae0cb8fa2d Mon Sep 17 00:00:00 2001 From: Harison Gachuru Date: Fri, 4 Feb 2022 11:45:12 +0300 Subject: [PATCH 22/29] Don't create objects when testing for zero search results --- people/tests/test_views_.py | 2 -- records/tests/test_views_.py | 1 - 2 files changed, 3 deletions(-) diff --git a/people/tests/test_views_.py b/people/tests/test_views_.py index b1e713ce..042b23ed 100644 --- a/people/tests/test_views_.py +++ b/people/tests/test_views_.py @@ -172,7 +172,6 @@ def test_response_with_people(self): def test_response_with_no_search_results(self): # setup - PersonFactory.create_batch(10) search_term = "does not exist" self.request = self.build_get_request({"q": search_term}) self.request.user = self.authorized_user @@ -1295,7 +1294,6 @@ def test_response_with_relationships(self): def test_response_with_no_search_results(self): # setup - InterpersonalRelationshipFactory.create_batch(10) search_term = "does not exist" self.request = self.build_get_request({"q": search_term}) self.request.user = self.authorized_user diff --git a/records/tests/test_views_.py b/records/tests/test_views_.py index 23201eea..967909d7 100644 --- a/records/tests/test_views_.py +++ b/records/tests/test_views_.py @@ -174,7 +174,6 @@ def test_response_with_temperature_records(self): def test_response_with_no_search_results(self): # setup - TemperatureRecordFactory.create_batch(10) search_term = "does not exist" self.request = self.build_get_request({"q": search_term}) self.request.user = self.authorized_user From 28c22bc5c76b4a99fe69467b4667e72edb4e5e0a Mon Sep 17 00:00:00 2001 From: Harison Gachuru Date: Fri, 4 Feb 2022 14:56:19 +0300 Subject: [PATCH 23/29] Create empty tuples using literals --- people/tests/test_views_.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/people/tests/test_views_.py b/people/tests/test_views_.py index 042b23ed..adda4033 100644 --- a/people/tests/test_views_.py +++ b/people/tests/test_views_.py @@ -754,7 +754,7 @@ def test_permission_required(self): self.request.user = UserFactory() self.view.setup(self.request) permission_required = self.view.get_permission_required() - self.assertEqual(permission_required, tuple()) + self.assertEqual(permission_required, ()) class ChildCreateViewTestCase(TestCase): @@ -974,7 +974,7 @@ def test_permission_required(self): self.request.user = UserFactory() self.view.setup(self.request) permission_required = self.view.get_permission_required() - self.assertEqual(permission_required, tuple()) + self.assertEqual(permission_required, ()) # UserPassesTestMixin def test_test_func_false(self): From 21f3444d8d8e7ddbc623c819860e4075147508ce Mon Sep 17 00:00:00 2001 From: Harison Gachuru Date: Fri, 4 Feb 2022 14:58:52 +0300 Subject: [PATCH 24/29] Remove extra data from form_data --- records/tests/test_views_.py | 7 ++----- 1 file changed, 2 insertions(+), 5 deletions(-) diff --git a/records/tests/test_views_.py b/records/tests/test_views_.py index 967909d7..536505fc 100644 --- a/records/tests/test_views_.py +++ b/records/tests/test_views_.py @@ -196,10 +196,7 @@ def setUpClass(cls): cls.person = PersonFactory() cls.user = UserFactory() cls.temp_record = TemperatureRecordFactory.build(person=cls.person) - cls.form_data = { - "person": cls.person, - "body_temperature": cls.temp_record.body_temperature, - } + cls.form_data = {"body_temperature": cls.temp_record.body_temperature} def setUp(self): self.factory = RequestFactory() @@ -275,7 +272,7 @@ def test_form_valid_without_duplicate(self, mock_success): # ModelFormMixin def test_form_valid_with_duplicate(self): - TemperatureRecordFactory(**self.form_data) + TemperatureRecordFactory(person=self.person, **self.form_data) self.request.user = self.user self.view.setup(self.request, username=self.person.username) self.view.object = None From 2ae881ac2b32a023681d4aed6534f5bb505a885f Mon Sep 17 00:00:00 2001 From: Harison Gachuru Date: Fri, 4 Feb 2022 15:00:17 +0300 Subject: [PATCH 25/29] Test the value of person in context_data --- records/tests/test_views_.py | 1 + 1 file changed, 1 insertion(+) diff --git a/records/tests/test_views_.py b/records/tests/test_views_.py index 536505fc..217aa41d 100644 --- a/records/tests/test_views_.py +++ b/records/tests/test_views_.py @@ -323,6 +323,7 @@ def test_context_data(self): self.view.object = None context_data = self.view.get_context_data() self.assertEqual(list(context_data.keys()), ["form", "view", "person"]) + self.assertEqual(context_data.get("person"), self.person) # SingleObjectTemplateResponseMixin def test_template_name(self): From d17a2e0259f960dac87d62090003f3192235a937 Mon Sep 17 00:00:00 2001 From: Harison Gachuru Date: Fri, 4 Feb 2022 15:00:41 +0300 Subject: [PATCH 26/29] Add unit tests for ParentChildRelationshipCreateView --- people/tests/test_views_.py | 187 ++++++++++++++++++++++++++++++++++++ 1 file changed, 187 insertions(+) diff --git a/people/tests/test_views_.py b/people/tests/test_views_.py index adda4033..6a1dd11c 100644 --- a/people/tests/test_views_.py +++ b/people/tests/test_views_.py @@ -1470,3 +1470,190 @@ def test_permission_required(self): self.view.setup(self.request) permission_required = self.view.get_permission_required() self.assertEqual(permission_required, ("people.add_interpersonalrelationship",)) + + +class ParentChildRelationshipCreateViewTestCase(TestCase): + @classmethod + def setUpClass(cls): + super().setUpClass() + + cls.user = UserFactory() + cls.person = AdultFactory(user=cls.user) + cls.parent = AdultFactory() + cls.child = ChildFactory() + cls.form_data = {"person": cls.parent.username} + cls.relationship_data = { + "person": cls.parent, + "relative": cls.child, + "relation": "PC", + } + cls.relationship = InterpersonalRelationshipFactory.build( + **cls.relationship_data + ) + + def setUp(self): + self.factory = RequestFactory() + self.request = self.factory.post("dummy_path", data=self.form_data) + self.view_class = views.ParentChildRelationshipCreateView + self.view_func = self.view_class.as_view() + self.view = self.view_class() + + # FormMixin + def test_initial(self): + self.view.setup(self.request) + initial = self.view.get_initial() + self.assertEqual(initial, {}) + + def test_prefix(self): + self.view.setup(self.request) + prefix = self.view.get_prefix() + self.assertIsNone(prefix) + + def test_form_class(self): + self.view.setup(self.request) + form_class = self.view.get_form_class() + self.assertEqual( + form_class, + import_string("people.forms.ParentChildRelationshipCreationForm"), + ) + + def test_form_kwargs(self): + self.view.setup(self.request) + form_kwargs = { + "initial": self.view.get_initial(), + "prefix": self.view.get_prefix(), + "data": self.request.POST, + "files": self.request.FILES, + } + self.assertEqual(self.view.get_form_kwargs(), form_kwargs) + + def test_success_url(self): + self.view.setup(self.request) + self.view.object = self.relationship + success_url = self.view.get_success_url() + self.assertEqual(success_url, reverse("core:dashboard")) + + def test_form_invalid(self): + self.request.user = self.user + self.view.setup(self.request, username=self.child.username) + self.view.object = None + form = self.view.get_form() + response = self.view.form_invalid(form) + self.assertEqual(response.status_code, 200) + + # SuccessMessageMixin + def test_success_message(self): + self.request.user = self.user + self.view.setup(self.request) + self.view.object = self.relationship + data = self.form_data.copy() + success_message = self.view.get_success_message(data) + people = f"{self.parent} and {self.child}" + self.assertEqual( + success_message, + f"A parent-child relationship between {people} has been added.", + ) + + @patch("django.contrib.messages.success") + def test_form_valid_without_duplicate(self, mock_success): + self.request.user = self.user + self.view.setup(self.request, username=self.child.username) + form = self.view.get_form() + self.assertTrue(form.is_valid()) + response = self.view.form_valid(form) + self.assertTrue(mock_success.called) + self.assertEqual(response.status_code, 302) + relationship = InterpersonalRelationship.objects.get(person=self.parent) + self.assertEqual(relationship.created_by, self.user) + self.assertEqual(relationship.relation, "PC") + + # ModelFormMixin + def test_form_valid_with_duplicate(self): + # setup + InterpersonalRelationshipFactory(**self.relationship_data) + self.request.user = self.user + self.view.setup(self.request, username=self.child.username) + self.view.object = None + form = self.view.get_form() + self.assertTrue(form.is_valid()) + response = self.view.form_valid(form) + + # test + self.assertEqual(response.status_code, 200) + response.render() + error_message = "This interpersonal relationship already exists" + self.assertInHTML(error_message, str(response.content)) + + # SingleObjectMixin + def test_queryset(self): + self.view.setup(self.request) + with self.assertRaises(ImproperlyConfigured): + queryset = self.view.get_queryset() + self.assertEqual(list(queryset), []) + + def test_slug_field(self): + self.view.setup(self.request) + slug_field = self.view.get_slug_field() + self.assertEqual(slug_field, "slug") + + def test_object(self): + self.view.setup(self.request) + with self.assertRaises(ImproperlyConfigured): + obj = self.view.get_object() + self.assertIsNone(obj) + + def test_child_with_existing_person(self): + self.view.setup(self.request, username=self.child.username) + obj = self.view.get_child() + self.assertEqual(obj, self.child) + + def test_child_with_non_existent_person(self): + self.view.setup(self.request, username="non-existent-person") + with self.assertRaises(Http404): + self.view.get_child() + + def test_context_object_name(self): + self.view.setup(self.request) + with self.assertRaises(ImproperlyConfigured): + queryset = self.view.get_queryset() + context_object_name = self.view.get_context_object_name(queryset) + self.assertIsNone(context_object_name) + + def test_context_data(self): + self.view.setup(self.request, username=self.child.username) + self.view.object = None + context_data = self.view.get_context_data() + self.assertEqual(list(context_data.keys()), ["form", "view", "child"]) + self.assertEqual(context_data.get("child"), self.child) + + # SingleObjectTemplateResponseMixin + def test_template_name(self): + self.view.setup(self.request) + template_names = self.view.get_template_names() + self.assertIn("people/relationship_form.html", template_names) + + # LoginRequiredMixin + def test_login_required(self): + self.request.user = AnonymousUser() + self.view.setup(self.request) + response = self.view.dispatch(self.request) + self.assertEqual(response.status_code, 302) + self.assertIn(reverse("account_login"), response.url) + + # PermissionRequiredMixin + def test_permission_required(self): + self.request.user = UserFactory() + self.view.setup(self.request) + permission_required = self.view.get_permission_required() + self.assertEqual(permission_required, ()) + + # UserPassesTestMixin + def test_test_func_false(self): + self.request.user = UserFactory() + self.view.setup(self.request) + self.assertFalse(self.view.test_func()) + + def test_test_func_true(self): + self.request.user = self.user + self.view.setup(self.request) + self.assertTrue(self.view.test_func()) From 06832a949453e102d9323f5fefd3b8f81473938a Mon Sep 17 00:00:00 2001 From: Harison Gachuru Date: Fri, 4 Feb 2022 15:14:30 +0300 Subject: [PATCH 27/29] Add comments in core view tests --- core/tests/test_views_.py | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/core/tests/test_views_.py b/core/tests/test_views_.py index 589a7c7b..8664bfb1 100644 --- a/core/tests/test_views_.py +++ b/core/tests/test_views_.py @@ -16,11 +16,13 @@ def setUp(self): self.view_func = self.view_class.as_view() self.view = self.view_class() + # TemplateResponseMixin def test_template_name(self): self.view.setup(self.request) template_names = self.view.get_template_names() self.assertIn("core/index.html", template_names) + # View def test_response(self): response = self.view_func(self.request) self.assertEqual(response.status_code, 200) @@ -34,12 +36,14 @@ def setUp(self): self.view_func = self.view_class.as_view() self.view = self.view_class() + # LoginRequiredMixin def test_login_required(self): self.request.user = AnonymousUser() response = self.view_func(self.request) self.assertEqual(response.status_code, 302) self.assertIn(reverse("account_login"), response.url) + # RedirectView def test_redirect_url_for_user_with_person(self): # setup user = UserFactory() @@ -66,17 +70,20 @@ def setUp(self): self.view_func = self.view_class.as_view() self.view = self.view_class() + # TemplateResponseMixin def test_template_name(self): self.view.setup(self.request) template_names = self.view.get_template_names() self.assertIn("core/dashboard.html", template_names) + # LoginRequiredMixin def test_login_required(self): self.request.user = AnonymousUser() response = self.view_func(self.request) self.assertEqual(response.status_code, 302) self.assertIn(reverse("account_login"), response.url) + # View def test_response_for_user_with_person(self): # setup user = UserFactory() From 4ac1dd5ad81ae9d83df51a3527370bd5de4841ab Mon Sep 17 00:00:00 2001 From: Harison Gachuru Date: Fri, 4 Feb 2022 15:26:31 +0300 Subject: [PATCH 28/29] Replace older view tests with unit tests --- core/tests/test_views.py | 130 ++- core/tests/test_views_.py | 100 -- people/tests/test_views.py | 2051 +++++++++++++++++++++++----------- people/tests/test_views_.py | 1659 --------------------------- records/tests/test_views.py | 439 +++++--- records/tests/test_views_.py | 347 ------ 6 files changed, 1777 insertions(+), 2949 deletions(-) delete mode 100644 core/tests/test_views_.py delete mode 100644 people/tests/test_views_.py delete mode 100644 records/tests/test_views_.py diff --git a/core/tests/test_views.py b/core/tests/test_views.py index 73217def..8664bfb1 100644 --- a/core/tests/test_views.py +++ b/core/tests/test_views.py @@ -1,4 +1,6 @@ -from django.test import RequestFactory, SimpleTestCase, TestCase +from django.contrib.auth.models import AnonymousUser +from django.core.exceptions import PermissionDenied +from django.test import RequestFactory, TestCase from django.urls import reverse from accounts.factories import UserFactory @@ -6,73 +8,93 @@ from people.factories import AdultFactory -class IndexViewTestCase(SimpleTestCase): +class IndexViewTestCase(TestCase): def setUp(self): self.factory = RequestFactory() self.request = self.factory.get("dummy_path/") - self.view = views.IndexView - - def test_response_status_code(self): - response = self.view.as_view()(self.request) + self.view_class = views.IndexView + self.view_func = self.view_class.as_view() + self.view = self.view_class() + + # TemplateResponseMixin + def test_template_name(self): + self.view.setup(self.request) + template_names = self.view.get_template_names() + self.assertIn("core/index.html", template_names) + + # View + def test_response(self): + response = self.view_func(self.request) self.assertEqual(response.status_code, 200) - def test_template_used(self): - response = self.view.as_view()(self.request) - with self.assertTemplateUsed("core/index.html"): - response.render() - class LoginRedirectViewTestCase(TestCase): - @classmethod - def setUpClass(cls): - super().setUpClass() - - cls.url = "/login/redirect/" - cls.fully_registered_user = UserFactory() - cls.partially_registered_user = UserFactory() - - # personal details - AdultFactory(user=cls.fully_registered_user) - - def test_anonymous_user_response(self): - response = self.client.get(self.url) - self.assertRedirects(response, f"/accounts/login/?next={self.url}") - - def test_fully_registered_user_response(self): - self.client.force_login(self.fully_registered_user) - response = self.client.get(self.url) + def setUp(self): + self.factory = RequestFactory() + self.request = self.factory.get("dummy_path/") + self.view_class = views.LoginRedirectView + self.view_func = self.view_class.as_view() + self.view = self.view_class() + + # LoginRequiredMixin + def test_login_required(self): + self.request.user = AnonymousUser() + response = self.view_func(self.request) self.assertEqual(response.status_code, 302) - self.assertRedirects(response, reverse("core:dashboard")) + self.assertIn(reverse("account_login"), response.url) - def test_partially_registered_user_response(self): - self.client.force_login(self.partially_registered_user) - response = self.client.get(self.url) - self.assertEqual(response.status_code, 302) - self.assertRedirects(response, reverse("people:adult_self_register")) + # RedirectView + def test_redirect_url_for_user_with_person(self): + # setup + user = UserFactory() + AdultFactory(user=user) + self.request.user = user + self.view.setup(self.request) + # test + url = self.view.get_redirect_url() + self.assertEqual(url, reverse("core:dashboard")) -class DashboardViewTestCase(TestCase): - @classmethod - def setUpClass(cls): - super().setUpClass() + def test_redirect_url_for_user_without_person(self): + self.request.user = UserFactory() + self.view.setup(self.request) + url = self.view.get_redirect_url() + self.assertEqual(url, reverse("people:adult_self_register")) - cls.url = "/dashboard/" - cls.fully_registered_user = UserFactory() - cls.partially_registered_user = UserFactory() - # personal details - AdultFactory(user=cls.fully_registered_user) +class DashboardViewTestCase(TestCase): + def setUp(self): + self.factory = RequestFactory() + self.request = self.factory.get("dummy_path/") + self.view_class = views.DashboardView + self.view_func = self.view_class.as_view() + self.view = self.view_class() + + # TemplateResponseMixin + def test_template_name(self): + self.view.setup(self.request) + template_names = self.view.get_template_names() + self.assertIn("core/dashboard.html", template_names) + + # LoginRequiredMixin + def test_login_required(self): + self.request.user = AnonymousUser() + response = self.view_func(self.request) + self.assertEqual(response.status_code, 302) + self.assertIn(reverse("account_login"), response.url) - def test_anonymous_user_response(self): - response = self.client.get(self.url) - self.assertRedirects(response, f"/accounts/login/?next={self.url}") + # View + def test_response_for_user_with_person(self): + # setup + user = UserFactory() + AdultFactory(user=user) + self.request.user = user - def test_fully_registered_user_response(self): - self.client.force_login(self.fully_registered_user) - response = self.client.get(self.url) + # test + response = self.view_func(self.request) self.assertEqual(response.status_code, 200) - def test_partially_registered_user_response(self): - self.client.force_login(self.partially_registered_user) - response = self.client.get(self.url) - self.assertEqual(response.status_code, 403) + def test_response_for_user_without_person(self): + self.request.user = UserFactory() + with self.assertRaises(PermissionDenied): + self.view_func(self.request) diff --git a/core/tests/test_views_.py b/core/tests/test_views_.py deleted file mode 100644 index 8664bfb1..00000000 --- a/core/tests/test_views_.py +++ /dev/null @@ -1,100 +0,0 @@ -from django.contrib.auth.models import AnonymousUser -from django.core.exceptions import PermissionDenied -from django.test import RequestFactory, TestCase -from django.urls import reverse - -from accounts.factories import UserFactory -from core import views -from people.factories import AdultFactory - - -class IndexViewTestCase(TestCase): - def setUp(self): - self.factory = RequestFactory() - self.request = self.factory.get("dummy_path/") - self.view_class = views.IndexView - self.view_func = self.view_class.as_view() - self.view = self.view_class() - - # TemplateResponseMixin - def test_template_name(self): - self.view.setup(self.request) - template_names = self.view.get_template_names() - self.assertIn("core/index.html", template_names) - - # View - def test_response(self): - response = self.view_func(self.request) - self.assertEqual(response.status_code, 200) - - -class LoginRedirectViewTestCase(TestCase): - def setUp(self): - self.factory = RequestFactory() - self.request = self.factory.get("dummy_path/") - self.view_class = views.LoginRedirectView - self.view_func = self.view_class.as_view() - self.view = self.view_class() - - # LoginRequiredMixin - def test_login_required(self): - self.request.user = AnonymousUser() - response = self.view_func(self.request) - self.assertEqual(response.status_code, 302) - self.assertIn(reverse("account_login"), response.url) - - # RedirectView - def test_redirect_url_for_user_with_person(self): - # setup - user = UserFactory() - AdultFactory(user=user) - self.request.user = user - self.view.setup(self.request) - - # test - url = self.view.get_redirect_url() - self.assertEqual(url, reverse("core:dashboard")) - - def test_redirect_url_for_user_without_person(self): - self.request.user = UserFactory() - self.view.setup(self.request) - url = self.view.get_redirect_url() - self.assertEqual(url, reverse("people:adult_self_register")) - - -class DashboardViewTestCase(TestCase): - def setUp(self): - self.factory = RequestFactory() - self.request = self.factory.get("dummy_path/") - self.view_class = views.DashboardView - self.view_func = self.view_class.as_view() - self.view = self.view_class() - - # TemplateResponseMixin - def test_template_name(self): - self.view.setup(self.request) - template_names = self.view.get_template_names() - self.assertIn("core/dashboard.html", template_names) - - # LoginRequiredMixin - def test_login_required(self): - self.request.user = AnonymousUser() - response = self.view_func(self.request) - self.assertEqual(response.status_code, 302) - self.assertIn(reverse("account_login"), response.url) - - # View - def test_response_for_user_with_person(self): - # setup - user = UserFactory() - AdultFactory(user=user) - self.request.user = user - - # test - response = self.view_func(self.request) - self.assertEqual(response.status_code, 200) - - def test_response_for_user_without_person(self): - self.request.user = UserFactory() - with self.assertRaises(PermissionDenied): - self.view_func(self.request) diff --git a/people/tests/test_views.py b/people/tests/test_views.py index f2540b74..6a1dd11c 100644 --- a/people/tests/test_views.py +++ b/people/tests/test_views.py @@ -1,9 +1,14 @@ -from django.contrib.auth.models import Permission -from django.test import TestCase +from unittest.mock import call, patch + +from django.contrib.auth.models import AnonymousUser, Permission +from django.core.exceptions import ImproperlyConfigured +from django.http.response import Http404 +from django.test import RequestFactory, TestCase from django.urls import reverse from django.utils.module_loading import import_string from accounts.factories import UserFactory +from people import views from people.factories import ( AdultFactory, ChildFactory, @@ -20,8 +25,26 @@ class PeopleListViewTestCase(TestCase): def setUpClass(cls): super().setUpClass() - cls.url = "/people/" - cls.table_head = """ + cls.authorized_user = cls.get_authorized_user() + + def setUp(self): + self.factory = RequestFactory() + self.request = self.build_get_request() + self.view_class = views.PeopleListView + self.view_func = self.view_class.as_view() + self.view = self.view_class() + + def build_get_request(self, data=None): + return self.factory.get("dummy_path", data=data) + + @staticmethod + def get_authorized_user(): + view_person = Permission.objects.filter(name="Can view person") + return UserFactory(user_permissions=tuple(view_person)) + + @property + def table_head(self): + thead = """ # @@ -32,87 +55,130 @@ def setUpClass(cls): """ - # users - view_person = Permission.objects.filter(name="Can view person") - cls.user = UserFactory() - cls.authorized_user = UserFactory(user_permissions=tuple(view_person)) - cls.staff_user = UserFactory(is_staff=True) - - def test_anonymous_user_response(self): - response = self.client.get(self.url) - self.assertRedirects(response, f"/accounts/login/?next={self.url}") - - def test_authenticated_user_response(self): - self.client.force_login(self.user) - response = self.client.get(self.url) - self.assertEqual(response.status_code, 403) - - def test_authorized_user_response(self): - self.client.force_login(self.authorized_user) - response = self.client.get(self.url) - self.assertEqual(response.status_code, 200) - - def test_staff_user_response(self): - self.client.force_login(self.staff_user) - response = self.client.get(self.url) - self.assertEqual(response.status_code, 403) - - def test_template_used(self): - self.client.force_login(self.authorized_user) - response = self.client.get(self.url) - self.assertTemplateUsed(response, "people/people_list.html") - - def test_context_data_contains_people(self): - self.client.force_login(self.authorized_user) - response = self.client.get(self.url) - self.assertIn("people", response.context) - - def test_is_paginated(self): - PersonFactory.create_batch(11) - self.client.force_login(self.authorized_user) - response = self.client.get(self.url) - self.assertTrue(response.context.get("is_paginated")) - self.assertEqual(len(response.context.get("people")), 10) - - def test_pagination_lists_all_items(self): - PersonFactory.create_batch(12) - self.client.force_login(self.authorized_user) - response = self.client.get(self.url + "?page=2") - expected_people = list(Person.objects.all())[-2:] - people = list(response.context.get("people")) - self.assertEqual(people, expected_people) - + return thead + + # MultipleObjectMixin + def test_allow_empty(self): + self.view.setup(self.request) + allow_empty = self.view.get_allow_empty() + self.assertTrue(allow_empty) + + def test_ordering(self): + self.view.setup(self.request) + ordering = self.view.get_ordering() + self.assertIsNone(ordering) + + # SearchableListMixin + def test_search_fields(self): + self.view.setup(self.request) + search_fields = self.view.get_search_fields_with_filters() + expected_search_fields = [("username", "icontains"), ("full_name", "icontains")] + self.assertEqual(search_fields, expected_search_fields) + + def test_search_query(self): + search_term = "search query" + self.request = self.build_get_request({"q": search_term}) + self.view.setup(self.request) + search_query = self.view.get_search_query() + self.assertEqual(search_query, search_term) + + def test_queryset_without_search_query(self): + self.view.setup(self.request) + queryset = self.view.get_queryset() + self.assertQuerysetEqual(queryset, Person.objects.all()) + + def test_queryset_with_search_query(self): + people = PersonFactory.create_batch(10) + search_term = people[0].full_name.split()[0] + self.request = self.build_get_request({"q": search_term}) + self.view.setup(self.request) + queryset = self.view.get_queryset() + self.assertQuerysetEqual(queryset, search_people(search_term)) + + # MultipleObjectMixin + def test_paginate_by(self): + self.view.setup(self.request) + queryset = self.view.get_queryset() + paginate_by = self.view.get_paginate_by(queryset) + self.assertEqual(paginate_by, 10) + + def test_context_object_name(self): + self.view.setup(self.request) + queryset = self.view.get_queryset() + context_object_name = self.view.get_context_object_name(queryset) + self.assertEqual(context_object_name, "people") + + def test_context_data(self): + self.view.setup(self.request) + queryset = self.view.get_queryset() + self.view.object_list = queryset + context_object_name = self.view.get_context_object_name(queryset) + context_data = self.view.get_context_data() + expected_context_data_keys = [ + "paginator", + "page_obj", + "is_paginated", + "object_list", + context_object_name, + "view", + ] + self.assertEqual(list(context_data.keys()), expected_context_data_keys) + + # MultipleObjectTemplateResponseMixin + def test_template_name(self): + self.view.setup(self.request) + self.view.object_list = self.view.get_queryset() + template_names = self.view.get_template_names() + self.assertIn("people/people_list.html", template_names) + + # LoginRequiredMixin + def test_login_required(self): + self.request.user = AnonymousUser() + self.view.setup(self.request) + response = self.view.dispatch(self.request) + self.assertEqual(response.status_code, 302) + self.assertIn(reverse("account_login"), response.url) + + # PermissionRequiredMixin + def test_permission_required(self): + self.request.user = UserFactory() + self.view.setup(self.request) + permission_required = self.view.get_permission_required() + self.assertEqual(permission_required, ("people.view_person",)) + + # template logic def test_response_with_no_people(self): - self.client.force_login(self.authorized_user) - response = self.client.get(self.url) + # setup + self.request.user = self.authorized_user + response = self.view_func(self.request) + response.render() + + # test with self.assertRaises(AssertionError): self.assertInHTML(self.table_head, response.content.decode()) self.assertInHTML("There are no people yet!", response.content.decode()) def test_response_with_people(self): - PersonFactory.create_batch(3) - self.client.force_login(self.authorized_user) - response = self.client.get(self.url) + # setup + PersonFactory() + self.request.user = self.authorized_user + response = self.view_func(self.request) + response.render() + + # test with self.assertRaises(AssertionError): self.assertInHTML("There are no people yet!", response.content.decode()) self.assertInHTML(self.table_head, response.content.decode()) - def test_search_results(self): + def test_response_with_no_search_results(self): # setup - people = PersonFactory.create_batch(10) - search_term = people[0].full_name.split()[0] - self.client.force_login(self.authorized_user) + search_term = "does not exist" + self.request = self.build_get_request({"q": search_term}) + self.request.user = self.authorized_user + response = self.view_func(self.request) + response.render() # test - response = self.client.get(f"{self.url}?q={search_term}") - search_results = response.context.get("people") - self.assertQuerysetEqual(search_results, search_people(search_term)) - - def test_response_with_no_search_results(self): - PersonFactory.create_batch(10) - self.client.force_login(self.authorized_user) - response = self.client.get(self.url + "?q=Does not exist") - self.assertEqual(list(response.context.get("people")), []) with self.assertRaises(AssertionError): self.assertInHTML(self.table_head, response.content.decode()) self.assertInHTML( @@ -120,95 +186,241 @@ def test_response_with_no_search_results(self): ) -class PersonCreateViewTestCase(TestCase): +class PersonDetailViewTestCase(TestCase): @classmethod def setUpClass(cls): super().setUpClass() - cls.url = "/people/add/" + cls.person = PersonFactory() + + def setUp(self): + self.factory = RequestFactory() + self.request = self.factory.get("dummy_path") + self.view_class = views.PersonDetailView + self.view_func = self.view_class.as_view() + self.view = self.view_class() + + # SingleObjectMixin + def test_queryset(self): + self.view.setup(self.request) + queryset = self.view.get_queryset() + self.assertEqual(list(queryset), [self.person]) + + def test_slug_field(self): + self.view.setup(self.request) + slug_field = self.view.get_slug_field() + self.assertEqual(slug_field, "username") + + def test_object_with_existing_person(self): + self.view.setup(self.request, username=self.person.username) + obj = self.view.get_object() + self.assertEqual(obj, self.person) + + def test_object_with_non_existent_person(self): + self.view.setup(self.request, username="non-existent-person") + with self.assertRaises(Http404): + self.view.get_object() + + def test_context_object_name(self): + self.view.setup(self.request, username=self.person.username) + obj = self.view.get_object() + context_object_name = self.view.get_context_object_name(obj) + self.assertEqual(context_object_name, "person") + + def test_context_data(self): + self.view.setup(self.request, username=self.person.username) + obj = self.view.get_object() + self.view.object = obj + context_object_name = self.view.get_context_object_name(obj) + context_data = self.view.get_context_data() + expected_context_data_keys = ["object", context_object_name, "view"] + self.assertEqual(list(context_data.keys()), expected_context_data_keys) + + # SingleObjectTemplateResponseMixin + def test_template_name(self): + self.view.setup(self.request) + template_names = self.view.get_template_names() + self.assertIn("people/person_detail.html", template_names) + + # LoginRequiredMixin + def test_login_required(self): + self.request.user = AnonymousUser() + self.view.setup(self.request) + response = self.view.dispatch(self.request) + self.assertEqual(response.status_code, 302) + self.assertIn(reverse("account_login"), response.url) + + # PermissionRequiredMixin + def test_permission_required(self): + self.request.user = UserFactory() + self.view.setup(self.request) + permission_required = self.view.get_permission_required() + self.assertEqual(permission_required, ("people.view_person",)) - # users - create_person = Permission.objects.filter(name="Can add person") - view_person = Permission.objects.filter(name="Can view person") - permissions = create_person | view_person - cls.user = UserFactory() - cls.authorized_user = UserFactory(user_permissions=tuple(permissions)) - cls.staff_user = UserFactory(is_staff=True) - - # POST data - person = PersonFactory.build() - cls.data = { - "username": person.username, - "full_name": person.full_name, - "gender": person.gender, - "dob": person.dob, - } - def test_anonymous_user_response(self): - response = self.client.get(self.url) - self.assertRedirects(response, f"/accounts/login/?next={self.url}") +class PersonCreateViewTestCase(TestCase): + @classmethod + def setUpClass(cls): + super().setUpClass() - def test_authenticated_user_response(self): - self.client.force_login(self.user) - response = self.client.get(self.url) - self.assertEqual(response.status_code, 403) + cls.user = UserFactory() + cls.person = PersonFactory.build() + cls.form_data = { + "username": cls.person.username, + "full_name": cls.person.full_name, + "gender": cls.person.gender, + "dob": cls.person.dob, + } - def test_authorized_user_response(self): - self.client.force_login(self.authorized_user) - response = self.client.get(self.url) - self.assertEqual(response.status_code, 200) + def setUp(self): + self.factory = RequestFactory() + self.request = self.factory.post("dummy_path", data=self.form_data) + self.view_class = views.PersonCreateView + self.view_func = self.view_class.as_view() + self.view = self.view_class() - def test_staff_user_response(self): - self.client.force_login(self.staff_user) - response = self.client.get(self.url) - self.assertEqual(response.status_code, 403) + def create_duplicate(self): + data = self.form_data.copy() + data["username"] = PersonFactory.build().username + data["created_by"] = self.user + PersonFactory(**data) - def test_template_used(self): - self.client.force_login(self.authorized_user) - response = self.client.get(self.url) - self.assertTemplateUsed(response, "people/person_form.html") + # FormMixin + def test_initial(self): + self.view.setup(self.request) + initial = self.view.get_initial() + self.assertEqual(initial, {}) - def test_context_data_contains_action(self): - self.client.force_login(self.authorized_user) - response = self.client.get(self.url) - self.assertEqual(response.context.get("action"), "add") + def test_prefix(self): + self.view.setup(self.request) + prefix = self.view.get_prefix() + self.assertIsNone(prefix) def test_form_class(self): - self.client.force_login(self.authorized_user) - response = self.client.get(self.url) - form = response.context.get("form") - self.assertEqual(form.__class__.__name__, "PersonCreationForm") - self.assertIsInstance(form, import_string("django.forms.ModelForm")) - self.assertIsInstance(form, import_string("people.forms.PersonCreationForm")) + self.view.setup(self.request) + form_class = self.view.get_form_class() + self.assertEqual(form_class, import_string("people.forms.PersonCreationForm")) + + def test_form_kwargs(self): + self.view.setup(self.request) + form_kwargs = { + "initial": self.view.get_initial(), + "prefix": self.view.get_prefix(), + "data": self.request.POST, + "files": self.request.FILES, + } + self.assertEqual(self.view.get_form_kwargs(), form_kwargs) + + def test_success_url(self): + self.view.setup(self.request) + self.view.object = self.person + success_url = self.view.get_success_url() + self.assertEqual( + success_url, + reverse( + "people:person_detail", kwargs={"username": self.form_data["username"]} + ), + ) def test_form_invalid(self): - # setup - data = self.data.copy() - data["created_by"] = self.authorized_user - PersonFactory(**data) - data["full_name"] = data["full_name"] + " " + data["username"].title() - data["username"] = PersonFactory.build().username - self.client.force_login(self.authorized_user) + self.request.user = self.user + self.view.setup(self.request) + self.view.object = None + form = self.view.get_form() + response = self.view.form_invalid(form) + self.assertEqual(response.status_code, 200) - # test - response = self.client.post(self.url, data) - form = response.context.get("form") - self.assertFalse(form.is_valid()) - self.assertEqual(form.errors, {"__all__": ["This person already exists"]}) + # SuccessMessageMixin + def test_success_message(self): + self.request.user = self.user + self.view.setup(self.request) + self.view.object = self.person + success_message = self.view.get_success_message(self.form_data) + self.assertEqual( + success_message, f"{self.person}'s information has been added successfully." + ) - def test_form_valid(self): - self.client.force_login(self.authorized_user) - self.client.post(self.url, self.data) - person = Person.objects.get(username=self.data["username"]) - self.assertEqual(person.created_by, self.authorized_user) + @patch("django.contrib.messages.success") + def test_form_valid_without_duplicate(self, mock_success): + self.request.user = self.user + self.view.setup(self.request) + form = self.view.get_form() + self.assertTrue(form.is_valid()) + response = self.view.form_valid(form) + self.assertTrue(mock_success.called) + self.assertEqual(response.status_code, 302) + person = Person.objects.get(username=self.form_data["username"]) + self.assertEqual(person.created_by, self.user) - def test_success_url(self): - self.client.force_login(self.authorized_user) - response = self.client.post(self.url, self.data) - self.assertRedirects( - response, - reverse("people:person_detail", kwargs={"username": self.data["username"]}), - ) + # ModelFormMixin + def test_form_valid_with_duplicate(self): + # setup + self.create_duplicate() + self.request.user = self.user + self.view.setup(self.request) + self.view.object = None + form = self.view.get_form() + self.assertTrue(form.is_valid()) + response = self.view.form_valid(form) + + # test + self.assertEqual(response.status_code, 200) + response.render() + error_message = "This person already exists" + self.assertInHTML(error_message, str(response.content)) + + # SingleObjectMixin + def test_queryset(self): + self.view.setup(self.request) + with self.assertRaises(ImproperlyConfigured): + queryset = self.view.get_queryset() + self.assertEqual(list(queryset), []) + + def test_slug_field(self): + self.view.setup(self.request) + slug_field = self.view.get_slug_field() + self.assertEqual(slug_field, "slug") + + def test_object(self): + self.view.setup(self.request) + with self.assertRaises(ImproperlyConfigured): + obj = self.view.get_object() + self.assertIsNone(obj) + + def test_context_object_name(self): + self.view.setup(self.request) + with self.assertRaises(ImproperlyConfigured): + queryset = self.view.get_queryset() + context_object_name = self.view.get_context_object_name(queryset) + self.assertIsNone(context_object_name) + + def test_context_data(self): + self.view.setup(self.request) + self.view.object = None + context_data = self.view.get_context_data() + self.assertEqual(list(context_data.keys()), ["form", "view", "action"]) + self.assertEqual(context_data.get("action"), "add") + + # SingleObjectTemplateResponseMixin + def test_template_name(self): + self.view.setup(self.request) + template_names = self.view.get_template_names() + self.assertIn("people/person_form.html", template_names) + + # LoginRequiredMixin + def test_login_required(self): + self.request.user = AnonymousUser() + self.view.setup(self.request) + response = self.view.dispatch(self.request) + self.assertEqual(response.status_code, 302) + self.assertIn(reverse("account_login"), response.url) + + # PermissionRequiredMixin + def test_permission_required(self): + self.request.user = UserFactory() + self.view.setup(self.request) + permission_required = self.view.get_permission_required() + self.assertEqual(permission_required, ("people.add_person",)) class AdultCreateViewTestCase(TestCase): @@ -216,96 +428,168 @@ class AdultCreateViewTestCase(TestCase): def setUpClass(cls): super().setUpClass() - cls.url = "/people/add/adult/" - - # users - create_person = Permission.objects.filter(name="Can add person") - view_person = Permission.objects.filter(name="Can view person") - permissions = create_person | view_person cls.user = UserFactory() - cls.authorized_user = UserFactory(user_permissions=tuple(permissions)) - cls.staff_user = UserFactory(is_staff=True) - - # POST data - person = AdultFactory.build() - cls.data = { - "username": person.username, - "full_name": person.full_name, - "gender": person.gender, - "dob": person.dob, - "phone_number": person.phone_number, + cls.person = AdultFactory.build() + cls.form_data = { + "username": cls.person.username, + "full_name": cls.person.full_name, + "gender": cls.person.gender, + "dob": cls.person.dob, + "phone_number": cls.person.phone_number, } - def test_anonymous_user_response(self): - response = self.client.get(self.url) - self.assertRedirects(response, f"/accounts/login/?next={self.url}") + def setUp(self): + self.factory = RequestFactory() + self.request = self.factory.post("dummy_path", data=self.form_data) + self.view_class = views.AdultCreateView + self.view_func = self.view_class.as_view() + self.view = self.view_class() - def test_authenticated_user_response(self): - self.client.force_login(self.user) - response = self.client.get(self.url) - self.assertEqual(response.status_code, 403) + def create_duplicate(self): + data = self.form_data.copy() + data["username"] = AdultFactory.build().username + data["created_by"] = self.user + AdultFactory(**data) - def test_authorized_user_response(self): - self.client.force_login(self.authorized_user) - response = self.client.get(self.url) - self.assertEqual(response.status_code, 200) + # FormMixin + def test_initial(self): + self.view.setup(self.request) + initial = self.view.get_initial() + self.assertEqual(initial, {}) - def test_staff_user_response(self): - self.client.force_login(self.staff_user) - response = self.client.get(self.url) - self.assertEqual(response.status_code, 403) + def test_prefix(self): + self.view.setup(self.request) + prefix = self.view.get_prefix() + self.assertIsNone(prefix) - def test_template_used(self): - self.client.force_login(self.authorized_user) - response = self.client.get(self.url) - self.assertTemplateUsed(response, "people/person_form.html") + def test_form_class(self): + self.view.setup(self.request) + form_class = self.view.get_form_class() + self.assertEqual(form_class, import_string("people.forms.AdultCreationForm")) + + def test_form_kwargs(self): + self.view.setup(self.request) + form_kwargs = { + "initial": self.view.get_initial(), + "prefix": self.view.get_prefix(), + "data": self.request.POST, + "files": self.request.FILES, + } + self.assertEqual(self.view.get_form_kwargs(), form_kwargs) + + def test_success_url(self): + self.view.setup(self.request) + self.view.object = self.person + success_url = self.view.get_success_url() + self.assertEqual( + success_url, + reverse( + "people:person_detail", kwargs={"username": self.form_data["username"]} + ), + ) - def test_context_data_contains_action(self): - self.client.force_login(self.authorized_user) - response = self.client.get(self.url) - self.assertEqual(response.context.get("action"), "add") + def test_form_invalid(self): + self.request.user = self.user + self.view.setup(self.request) + self.view.object = None + form = self.view.get_form() + response = self.view.form_invalid(form) + self.assertEqual(response.status_code, 200) - def test_context_data_contains_age_category(self): - self.client.force_login(self.authorized_user) - response = self.client.get(self.url) - self.assertEqual(response.context.get("age_category"), "an adult") + # SuccessMessageMixin + def test_success_message(self): + self.request.user = self.user + self.view.setup(self.request) + self.view.object = self.person + success_message = self.view.get_success_message(self.form_data) + self.assertEqual( + success_message, f"{self.person}'s information has been added successfully." + ) - def test_form_class(self): - self.client.force_login(self.authorized_user) - response = self.client.get(self.url) - form = response.context.get("form") - self.assertEqual(form.__class__.__name__, "AdultCreationForm") - self.assertIsInstance(form, import_string("django.forms.ModelForm")) - self.assertIsInstance(form, import_string("people.forms.AdultCreationForm")) + @patch("django.contrib.messages.success") + def test_form_valid_without_duplicate(self, mock_success): + self.request.user = self.user + self.view.setup(self.request) + form = self.view.get_form() + self.assertTrue(form.is_valid()) + response = self.view.form_valid(form) + self.assertTrue(mock_success.called) + self.assertEqual(response.status_code, 302) + person = Person.objects.get(username=self.form_data["username"]) + self.assertEqual(person.created_by, self.user) - def test_form_invalid(self): + # ModelFormMixin + def test_form_valid_with_duplicate(self): # setup - data = self.data.copy() - data["created_by"] = self.authorized_user - AdultFactory(**data) - data["full_name"] = data["full_name"] + " " + data["username"].title() - data["username"] = AdultFactory.build().username - self.client.force_login(self.authorized_user) + self.create_duplicate() + self.request.user = self.user + self.view.setup(self.request) + self.view.object = None + form = self.view.get_form() + self.assertTrue(form.is_valid()) + response = self.view.form_valid(form) # test - response = self.client.post(self.url, data) - form = response.context.get("form") - self.assertFalse(form.is_valid()) - self.assertEqual(form.errors, {"__all__": ["This person already exists"]}) - - def test_form_valid(self): - self.client.force_login(self.authorized_user) - self.client.post(self.url, self.data) - person = Person.objects.get(username=self.data["username"]) - self.assertEqual(person.created_by, self.authorized_user) - - def test_success_url(self): - self.client.force_login(self.authorized_user) - response = self.client.post(self.url, self.data) - self.assertRedirects( - response, - reverse("people:person_detail", kwargs={"username": self.data["username"]}), + self.assertEqual(response.status_code, 200) + response.render() + error_message = "This person already exists" + self.assertInHTML(error_message, str(response.content)) + + # SingleObjectMixin + def test_queryset(self): + self.view.setup(self.request) + with self.assertRaises(ImproperlyConfigured): + queryset = self.view.get_queryset() + self.assertEqual(list(queryset), []) + + def test_slug_field(self): + self.view.setup(self.request) + slug_field = self.view.get_slug_field() + self.assertEqual(slug_field, "slug") + + def test_object(self): + self.view.setup(self.request) + with self.assertRaises(ImproperlyConfigured): + obj = self.view.get_object() + self.assertIsNone(obj) + + def test_context_object_name(self): + self.view.setup(self.request) + with self.assertRaises(ImproperlyConfigured): + queryset = self.view.get_queryset() + context_object_name = self.view.get_context_object_name(queryset) + self.assertIsNone(context_object_name) + + def test_context_data(self): + self.view.setup(self.request) + self.view.object = None + context_data = self.view.get_context_data() + self.assertEqual( + list(context_data.keys()), ["form", "view", "action", "age_category"] ) + self.assertEqual(context_data.get("action"), "add") + self.assertEqual(context_data.get("age_category"), "an adult") + + # SingleObjectTemplateResponseMixin + def test_template_name(self): + self.view.setup(self.request) + template_names = self.view.get_template_names() + self.assertIn("people/person_form.html", template_names) + + # LoginRequiredMixin + def test_login_required(self): + self.request.user = AnonymousUser() + self.view.setup(self.request) + response = self.view.dispatch(self.request) + self.assertEqual(response.status_code, 302) + self.assertIn(reverse("account_login"), response.url) + + # PermissionRequiredMixin + def test_permission_required(self): + self.request.user = UserFactory() + self.view.setup(self.request) + permission_required = self.view.get_permission_required() + self.assertEqual(permission_required, ("people.add_person",)) class AdultSelfRegisterViewTestCase(TestCase): @@ -313,64 +597,164 @@ class AdultSelfRegisterViewTestCase(TestCase): def setUpClass(cls): super().setUpClass() - cls.url = "/people/register/self/" - - # users cls.user = UserFactory() - - # POST data - person = AdultFactory.build() - cls.data = { - "username": person.username, - "full_name": person.full_name, - "gender": person.gender, - "dob": person.dob, - "phone_number": person.phone_number, + cls.person = AdultFactory.build() + cls.form_data = { + "username": cls.person.username, + "full_name": cls.person.full_name, + "gender": cls.person.gender, + "dob": cls.person.dob, + "phone_number": cls.person.phone_number, } - def test_anonymous_user_response(self): - response = self.client.get(self.url) - self.assertRedirects(response, f"/accounts/login/?next={self.url}") + def setUp(self): + self.factory = RequestFactory() + self.request = self.factory.post("dummy_path", data=self.form_data) + self.view_class = views.AdultSelfRegisterView + self.view_func = self.view_class.as_view() + self.view = self.view_class() - def test_authenticated_user_response(self): - self.client.force_login(self.user) - response = self.client.get(self.url) - self.assertEqual(response.status_code, 200) - - def test_template_used(self): - self.client.force_login(self.user) - response = self.client.get(self.url) - self.assertTemplateUsed(response, "people/self_register_form.html") + def create_duplicate(self): + data = self.form_data.copy() + data["username"] = AdultFactory.build().username + data["created_by"] = self.user + AdultFactory(**data) - def test_context_data_contains_action(self): - self.client.force_login(self.user) - response = self.client.get(self.url) - self.assertEqual(response.context.get("action"), "add") + # FormMixin + def test_initial(self): + self.view.setup(self.request) + initial = self.view.get_initial() + self.assertEqual(initial, {}) - def test_context_data_contains_age_category(self): - self.client.force_login(self.user) - response = self.client.get(self.url) - self.assertEqual(response.context.get("age_category"), "an adult") + def test_prefix(self): + self.view.setup(self.request) + prefix = self.view.get_prefix() + self.assertIsNone(prefix) def test_form_class(self): - self.client.force_login(self.user) - response = self.client.get(self.url) - form = response.context.get("form") - self.assertEqual(form.__class__.__name__, "AdultCreationForm") - self.assertIsInstance(form, import_string("django.forms.ModelForm")) - self.assertIsInstance(form, import_string("people.forms.AdultCreationForm")) - - def test_form_valid(self): - self.client.force_login(self.user) - self.client.post(self.url, self.data) - person = Person.objects.get(username=self.data["username"]) - self.assertEqual(person.user, self.user) - self.assertEqual(person.created_by, self.user) + self.view.setup(self.request) + form_class = self.view.get_form_class() + self.assertEqual(form_class, import_string("people.forms.AdultCreationForm")) + + def test_form_kwargs(self): + self.view.setup(self.request) + form_kwargs = { + "initial": self.view.get_initial(), + "prefix": self.view.get_prefix(), + "data": self.request.POST, + "files": self.request.FILES, + } + self.assertEqual(self.view.get_form_kwargs(), form_kwargs) def test_success_url(self): - self.client.force_login(self.user) - response = self.client.post(self.url, self.data) - self.assertRedirects(response, reverse("core:dashboard")) + self.view.setup(self.request) + self.view.object = self.person + success_url = self.view.get_success_url() + self.assertEqual(success_url, reverse("core:dashboard")) + + def test_form_invalid(self): + self.request.user = self.user + self.view.setup(self.request) + self.view.object = None + form = self.view.get_form() + response = self.view.form_invalid(form) + self.assertEqual(response.status_code, 200) + + # SuccessMessageMixin + def test_success_message(self): + self.request.user = self.user + self.view.setup(self.request) + self.view.object = self.person + success_message = self.view.get_success_message(self.form_data) + self.assertEqual( + success_message, f"{self.person}'s information has been added successfully." + ) + + @patch("django.contrib.messages.success") + def test_form_valid_without_duplicate(self, mock_success): + self.request.user = self.user + self.view.setup(self.request) + form = self.view.get_form() + self.assertTrue(form.is_valid()) + response = self.view.form_valid(form) + self.assertTrue(mock_success.called) + self.assertEqual(response.status_code, 302) + person = Person.objects.get(username=self.form_data["username"]) + self.assertEqual(person.created_by, self.user) + self.assertEqual(person.user, self.user) + + # ModelFormMixin + def test_form_valid_with_duplicate(self): + # setup + self.create_duplicate() + self.request.user = self.user + self.view.setup(self.request) + self.view.object = None + form = self.view.get_form() + self.assertTrue(form.is_valid()) + response = self.view.form_valid(form) + + # test + self.assertEqual(response.status_code, 200) + response.render() + error_message = "This person already exists" + self.assertInHTML(error_message, str(response.content)) + + # SingleObjectMixin + def test_queryset(self): + self.view.setup(self.request) + with self.assertRaises(ImproperlyConfigured): + queryset = self.view.get_queryset() + self.assertEqual(list(queryset), []) + + def test_slug_field(self): + self.view.setup(self.request) + slug_field = self.view.get_slug_field() + self.assertEqual(slug_field, "slug") + + def test_object(self): + self.view.setup(self.request) + with self.assertRaises(ImproperlyConfigured): + obj = self.view.get_object() + self.assertIsNone(obj) + + def test_context_object_name(self): + self.view.setup(self.request) + with self.assertRaises(ImproperlyConfigured): + queryset = self.view.get_queryset() + context_object_name = self.view.get_context_object_name(queryset) + self.assertIsNone(context_object_name) + + def test_context_data(self): + self.view.setup(self.request) + self.view.object = None + context_data = self.view.get_context_data() + self.assertEqual( + list(context_data.keys()), ["form", "view", "action", "age_category"] + ) + self.assertEqual(context_data.get("action"), "add") + self.assertEqual(context_data.get("age_category"), "an adult") + + # SingleObjectTemplateResponseMixin + def test_template_name(self): + self.view.setup(self.request) + template_names = self.view.get_template_names() + self.assertIn("people/self_register_form.html", template_names) + + # LoginRequiredMixin + def test_login_required(self): + self.request.user = AnonymousUser() + self.view.setup(self.request) + response = self.view.dispatch(self.request) + self.assertEqual(response.status_code, 302) + self.assertIn(reverse("account_login"), response.url) + + # PermissionRequiredMixin + def test_permission_required(self): + self.request.user = UserFactory() + self.view.setup(self.request) + permission_required = self.view.get_permission_required() + self.assertEqual(permission_required, ()) class ChildCreateViewTestCase(TestCase): @@ -378,155 +762,232 @@ class ChildCreateViewTestCase(TestCase): def setUpClass(cls): super().setUpClass() - cls.url = "/people/add/child/" - - # users cls.user = UserFactory() - cls.authorized_user = UserFactory() - - # POST data - cls.parent = AdultFactory(user=cls.authorized_user) - child = ChildFactory.build() - cls.data = { - "username": child.username, - "full_name": child.full_name, - "gender": child.gender, - "dob": child.dob, + cls.parent = AdultFactory(user=cls.user) + cls.person = ChildFactory.build() + cls.form_data = { + "username": cls.person.username, + "full_name": cls.person.full_name, + "gender": cls.person.gender, + "dob": cls.person.dob, } - def test_anonymous_user_response(self): - response = self.client.get(self.url) - self.assertRedirects(response, f"/accounts/login/?next={self.url}") - - def test_authenticated_user_response(self): - self.client.force_login(self.user) - response = self.client.get(self.url) - self.assertEqual(response.status_code, 403) + def setUp(self): + self.factory = RequestFactory() + self.request = self.build_post_request(self.form_data) + self.view_class = views.ChildCreateView + self.view_func = self.view_class.as_view() + self.view = self.view_class() - def test_authorized_user_response(self): - self.client.force_login(self.authorized_user) - response = self.client.get(self.url) - self.assertEqual(response.status_code, 200) + def build_post_request(self, data=None): + return self.factory.post("dummy_path", data=data) - def test_template_used(self): - self.client.force_login(self.authorized_user) - response = self.client.get(self.url) - self.assertTemplateUsed(response, "people/person_form.html") + def create_duplicate(self): + data = self.form_data.copy() + data["username"] = ChildFactory.build().username + data["created_by"] = self.user + ChildFactory(**data) - def test_context_data_contains_action(self): - self.client.force_login(self.authorized_user) - response = self.client.get(self.url) - self.assertEqual(response.context.get("action"), "add") + # FormMixin + def test_initial(self): + self.view.setup(self.request) + initial = self.view.get_initial() + self.assertEqual(initial, {}) - def test_context_data_contains_age_category(self): - self.client.force_login(self.authorized_user) - response = self.client.get(self.url) - self.assertEqual(response.context.get("age_category"), "a child") + def test_prefix(self): + self.view.setup(self.request) + prefix = self.view.get_prefix() + self.assertIsNone(prefix) def test_form_class(self): - self.client.force_login(self.authorized_user) - response = self.client.get(self.url) - form = response.context.get("form") - self.assertEqual(form.__class__.__name__, "ChildCreationForm") - self.assertIsInstance(form, import_string("django.forms.ModelForm")) - self.assertIsInstance(form, import_string("people.forms.ChildCreationForm")) + self.view.setup(self.request) + form_class = self.view.get_form_class() + self.assertEqual(form_class, import_string("people.forms.ChildCreationForm")) + + def test_form_kwargs(self): + self.view.setup(self.request) + form_kwargs = { + "initial": self.view.get_initial(), + "prefix": self.view.get_prefix(), + "data": self.request.POST, + "files": self.request.FILES, + } + self.assertEqual(self.view.get_form_kwargs(), form_kwargs) + + def test_success_url_when_creator_is_the_parent(self): + self.view.setup(self.request) + self.view.object = self.person + success_url = self.view.get_success_url(is_parent=True) + self.assertEqual(success_url, reverse("core:dashboard")) + + def test_success_url_when_creator_is_not_the_parent(self): + self.view.setup(self.request) + self.view.object = self.person + success_url = self.view.get_success_url() + self.assertEqual( + success_url, + reverse( + "people:parent_child_relationship_create", + kwargs={"username": self.person.username}, + ), + ) def test_form_invalid(self): - # setup - data = self.data.copy() - data["created_by"] = self.authorized_user - ChildFactory(**data) - data["full_name"] = data["full_name"] + " " + data["username"].title() - data["username"] = ChildFactory.build().username - self.client.force_login(self.authorized_user) + self.request.user = self.user + self.view.setup(self.request) + self.view.object = None + form = self.view.get_form() + response = self.view.form_invalid(form) + self.assertEqual(response.status_code, 200) - # test - response = self.client.post(self.url, data) - form = response.context.get("form") - self.assertFalse(form.is_valid()) - self.assertEqual(form.errors, {"__all__": ["This person already exists"]}) + # SuccessMessageMixin + def test_success_message(self): + self.request.user = self.user + self.view.setup(self.request) + self.view.object = self.person + success_message = self.view.get_success_message(self.form_data) + self.assertEqual( + success_message, f"{self.person}'s information has been added successfully." + ) - def test_is_parent_form_valid(self): + @patch("django.contrib.messages.success") + def test_form_valid_when_creator_is_not_the_parent(self, mock_success): + self.request.user = self.user + self.view.setup(self.request) + form = self.view.get_form() + self.assertTrue(form.is_valid()) + response = self.view.form_valid(form) + self.assertTrue(mock_success.called) + self.assertEqual(response.status_code, 302) + person = Person.objects.get(username=self.form_data["username"]) + self.assertEqual(person.created_by, self.user) + self.assertEqual(person.user, None) + + @patch("django.contrib.messages.info") + def test_create_relationship(self, mock_info): # setup - data = self.data.copy() - data["is_parent"] = True - self.client.force_login(self.authorized_user) + child = ChildFactory(**self.form_data) + self.request.user = self.user + self.view.setup(self.request) + self.view.object = child + self.view.create_relationship() # test - self.client.post(self.url, self.data) - child = Person.objects.get(username=self.data["username"]) - self.assertEqual(child.created_by, self.authorized_user) - - def test_not_parent_form_valid(self): - self.client.force_login(self.authorized_user) - self.client.post(self.url, self.data) - child = Person.objects.get(username=self.data["username"]) - self.assertEqual(child.created_by, self.authorized_user) - - def test_is_parent_success_url(self): + relationship = InterpersonalRelationship.objects.get(relative=child) + self.assertEqual(relationship.relation, "PC") + self.assertEqual(relationship.person, self.parent) + self.assertEqual(relationship.created_by, self.user) + self.assertTrue(mock_info.called) + message = f"A parent-child relationship between {self.parent} and {child}" + message += " has been added." + self.assertEqual(mock_info.call_args, call(self.request, message)) + + @patch("django.contrib.messages.success") + @patch("django.contrib.messages.info") + def test_form_valid_when_creator_is_the_parent(self, mock_success, mock_info): # setup - data = self.data.copy() + data = self.form_data.copy() data["is_parent"] = True - self.client.force_login(self.authorized_user) + self.request = self.build_post_request(data) + self.request.user = self.user + self.view.setup(self.request) + form = self.view.get_form() # test - response = self.client.post(self.url, data) - self.assertRedirects(response, reverse("core:dashboard")) - - def test_not_parent_success_url(self): - self.client.force_login(self.authorized_user) - response = self.client.post(self.url, self.data) - self.assertRedirects( - response, - reverse( - "people:parent_child_relationship_create", - kwargs={"username": self.data["username"]}, - ), - ) - - -class PersonDetailViewTestCase(TestCase): - @classmethod - def setUpClass(cls): - super().setUpClass() - - cls.person = PersonFactory() - cls.url = cls.person.get_absolute_url() - - # users - view_person = Permission.objects.filter(name="Can view person") - cls.user = UserFactory() - cls.authorized_user = UserFactory(user_permissions=tuple(view_person)) - cls.staff_user = UserFactory(is_staff=True) - - def test_anonymous_user_response(self): - response = self.client.get(self.url) - self.assertRedirects(response, f"/accounts/login/?next={self.url}") + self.assertTrue(form.is_valid()) + response = self.view.form_valid(form) + self.assertTrue(mock_success.called) + self.assertEqual(response.status_code, 302) + person = Person.objects.get(username=self.form_data["username"]) + self.assertEqual(person.created_by, self.user) + self.assertEqual(person.user, None) + self.assertTrue(mock_info.called) - def test_authenticated_user_response(self): - self.client.force_login(self.user) - response = self.client.get(self.url) - self.assertEqual(response.status_code, 403) + # ModelFormMixin + def test_form_valid_with_duplicate(self): + # setup + self.create_duplicate() + self.request.user = self.user + self.view.setup(self.request) + self.view.object = None + form = self.view.get_form() + self.assertTrue(form.is_valid()) + response = self.view.form_valid(form) - def test_authorized_user_response(self): - self.client.force_login(self.authorized_user) - response = self.client.get(self.url) + # test self.assertEqual(response.status_code, 200) - - def test_staff_user_response(self): - self.client.force_login(self.staff_user) - response = self.client.get(self.url) - self.assertEqual(response.status_code, 403) - - def test_template_used(self): - self.client.force_login(self.authorized_user) - response = self.client.get(self.url) - self.assertTemplateUsed(response, "people/person_detail.html") - - def test_context_data_contains_person(self): - self.client.force_login(self.authorized_user) - response = self.client.get(self.url) - self.assertEqual(response.context.get("person"), self.person) + response.render() + error_message = "This person already exists" + self.assertInHTML(error_message, str(response.content)) + + # SingleObjectMixin + def test_queryset(self): + self.view.setup(self.request) + with self.assertRaises(ImproperlyConfigured): + queryset = self.view.get_queryset() + self.assertEqual(list(queryset), []) + + def test_slug_field(self): + self.view.setup(self.request) + slug_field = self.view.get_slug_field() + self.assertEqual(slug_field, "slug") + + def test_object(self): + self.view.setup(self.request) + with self.assertRaises(ImproperlyConfigured): + obj = self.view.get_object() + self.assertIsNone(obj) + + def test_context_object_name(self): + self.view.setup(self.request) + with self.assertRaises(ImproperlyConfigured): + queryset = self.view.get_queryset() + context_object_name = self.view.get_context_object_name(queryset) + self.assertIsNone(context_object_name) + + def test_context_data(self): + self.view.setup(self.request) + self.view.object = None + context_data = self.view.get_context_data() + self.assertEqual( + list(context_data.keys()), ["form", "view", "action", "age_category"] + ) + self.assertEqual(context_data.get("action"), "add") + self.assertEqual(context_data.get("age_category"), "a child") + + # SingleObjectTemplateResponseMixin + def test_template_name(self): + self.view.setup(self.request) + template_names = self.view.get_template_names() + self.assertIn("people/person_form.html", template_names) + + # LoginRequiredMixin + def test_login_required(self): + self.request.user = AnonymousUser() + self.view.setup(self.request) + response = self.view.dispatch(self.request) + self.assertEqual(response.status_code, 302) + self.assertIn(reverse("account_login"), response.url) + + # PermissionRequiredMixin + def test_permission_required(self): + self.request.user = UserFactory() + self.view.setup(self.request) + permission_required = self.view.get_permission_required() + self.assertEqual(permission_required, ()) + + # UserPassesTestMixin + def test_test_func_false(self): + self.request.user = UserFactory() + self.view.setup(self.request) + self.assertFalse(self.view.test_func()) + + def test_test_func_true(self): + user = UserFactory() + AdultFactory(user=user) + self.request.user = user + self.view.setup(self.request) + self.assertTrue(self.view.test_func()) class PersonUpdateViewTestCase(TestCase): @@ -534,80 +995,167 @@ class PersonUpdateViewTestCase(TestCase): def setUpClass(cls): super().setUpClass() - cls.person = PersonFactory() - cls.url = cls.person.get_absolute_url() + "update/" - - # users - update_person = Permission.objects.filter(name="Can change person") - view_person = Permission.objects.filter(name="Can view person") - permissions = update_person | view_person cls.user = UserFactory() - cls.authorized_user = UserFactory(user_permissions=tuple(permissions)) - cls.staff_user = UserFactory(is_staff=True) - - # POST data - cls.data = { + cls.person = PersonFactory() + cls.form_data = { "username": cls.person.username, - "full_name": cls.person.full_name + " " + cls.person.username.title(), + "full_name": cls.person.full_name, "gender": cls.person.gender, "dob": cls.person.dob, } - def test_anonymous_user_response(self): - response = self.client.get(self.url) - self.assertRedirects(response, f"/accounts/login/?next={self.url}") - - def test_authenticated_user_response(self): - self.client.force_login(self.user) - response = self.client.get(self.url) - self.assertEqual(response.status_code, 403) - - def test_authorized_user_response(self): - self.client.force_login(self.authorized_user) - response = self.client.get(self.url) - self.assertEqual(response.status_code, 200) - - def test_staff_user_response(self): - self.client.force_login(self.staff_user) - response = self.client.get(self.url) - self.assertEqual(response.status_code, 403) + def setUp(self): + self.factory = RequestFactory() + self.request = self.factory.post("dummy_path", data=self.form_data) + self.view_class = views.PersonUpdateView + self.view_func = self.view_class.as_view() + self.view = self.view_class() - def test_template_used(self): - self.client.force_login(self.authorized_user) - response = self.client.get(self.url) - self.assertTemplateUsed(response, "people/person_form.html") + # FormMixin + def test_initial(self): + self.view.setup(self.request) + initial = self.view.get_initial() + self.assertEqual(initial, {}) - def test_context_data_contains_person(self): - self.client.force_login(self.authorized_user) - response = self.client.get(self.url) - self.assertEqual(response.context.get("person"), self.person) - - def test_context_data_contains_action(self): - self.client.force_login(self.authorized_user) - response = self.client.get(self.url) - self.assertEqual(response.context.get("action"), "update") + def test_prefix(self): + self.view.setup(self.request) + prefix = self.view.get_prefix() + self.assertIsNone(prefix) def test_form_class(self): - self.client.force_login(self.authorized_user) - response = self.client.get(self.url) - form = response.context.get("form") - self.assertEqual(form.__class__.__name__, "PersonUpdateForm") - self.assertIsInstance(form, import_string("django.forms.ModelForm")) - self.assertIsInstance(form, import_string("people.forms.PersonUpdateForm")) + self.view.setup(self.request) + form_class = self.view.get_form_class() + self.assertEqual(form_class, import_string("people.forms.PersonUpdateForm")) + + def test_form_kwargs(self): + self.view.setup(self.request) + form_kwargs = { + "initial": self.view.get_initial(), + "prefix": self.view.get_prefix(), + "data": self.request.POST, + "files": self.request.FILES, + } + self.assertEqual(self.view.get_form_kwargs(), form_kwargs) def test_success_url(self): - self.client.force_login(self.authorized_user) - response = self.client.post(self.url, self.data) - self.assertRedirects(response, self.person.get_absolute_url()) + self.view.setup(self.request) + self.view.object = self.person + success_url = self.view.get_success_url() + self.assertEqual( + success_url, + reverse( + "people:person_detail", kwargs={"username": self.form_data["username"]} + ), + ) + def test_form_invalid(self): + self.request.user = self.user + self.view.setup(self.request) + self.view.object = None + form = self.view.get_form() + response = self.view.form_invalid(form) + self.assertEqual(response.status_code, 200) -class RelationshipsListViewTestCase(TestCase): + # SuccessMessageMixin + def test_success_message(self): + self.request.user = self.user + self.view.setup(self.request) + self.view.object = self.person + success_message = self.view.get_success_message(self.form_data) + self.assertEqual( + success_message, + f"{self.person}'s information has been updated successfully.", + ) + + @patch("django.contrib.messages.success") + def test_form_valid(self, mock_success): + self.request.user = self.user + self.view.setup(self.request, username=self.person.username) + self.view.object = self.view.get_object() + form = self.view.get_form() + self.assertTrue(form.is_valid()) + response = self.view.form_valid(form) + self.assertTrue(mock_success.called) + self.assertEqual(response.status_code, 302) + + # SingleObjectMixin + def test_queryset(self): + self.view.setup(self.request) + queryset = self.view.get_queryset() + self.assertEqual(list(queryset), [self.person]) + + def test_slug_field(self): + self.view.setup(self.request) + slug_field = self.view.get_slug_field() + self.assertEqual(slug_field, "username") + + def test_object(self): + self.view.setup(self.request, username=self.person.username) + obj = self.view.get_object() + self.assertEqual(obj, self.person) + + def test_context_object_name(self): + self.view.setup(self.request, username=self.person.username) + obj = self.view.get_object() + context_object_name = self.view.get_context_object_name(obj) + self.assertEqual(context_object_name, "person") + + def test_context_data(self): + self.view.setup(self.request) + self.view.object = None + context_data = self.view.get_context_data() + self.assertEqual(list(context_data.keys()), ["form", "view", "action"]) + self.assertEqual(context_data.get("action"), "update") + + # SingleObjectTemplateResponseMixin + def test_template_name(self): + self.view.setup(self.request) + template_names = self.view.get_template_names() + self.assertIn("people/person_form.html", template_names) + + # LoginRequiredMixin + def test_login_required(self): + self.request.user = AnonymousUser() + self.view.setup(self.request) + response = self.view.dispatch(self.request) + self.assertEqual(response.status_code, 302) + self.assertIn(reverse("account_login"), response.url) + + # PermissionRequiredMixin + def test_permission_required(self): + self.request.user = UserFactory() + self.view.setup(self.request) + permission_required = self.view.get_permission_required() + self.assertEqual(permission_required, ("people.change_person",)) + + +class InterpersonalRelationshipsListViewTestCase(TestCase): @classmethod def setUpClass(cls): super().setUpClass() - cls.url = "/people/relationships/" - cls.table_head = """ + cls.authorized_user = cls.get_authorized_user() + + def setUp(self): + self.factory = RequestFactory() + self.request = self.build_get_request() + self.view_class = views.RelationshipsListView + self.view_func = self.view_class.as_view() + self.view = self.view_class() + + def build_get_request(self, data=None): + return self.factory.get("dummy_path", data=data) + + @staticmethod + def get_authorized_user(): + view_relationship = Permission.objects.filter( + name="Can view interpersonal relationship" + ) + return UserFactory(user_permissions=tuple(view_relationship)) + + @property + def table_head(self): + thead = """ # @@ -617,61 +1165,112 @@ def setUpClass(cls): """ - # users - view_relationships = Permission.objects.filter( - name="Can view interpersonal relationship" + return thead + + # MultipleObjectMixin + def test_allow_empty(self): + self.view.setup(self.request) + allow_empty = self.view.get_allow_empty() + self.assertTrue(allow_empty) + + def test_ordering(self): + self.view.setup(self.request) + ordering = self.view.get_ordering() + self.assertIsNone(ordering) + + # SearchableListMixin + def test_search_fields(self): + self.view.setup(self.request) + search_fields = self.view.get_search_fields_with_filters() + expected_search_fields = [ + ("person__username", "icontains"), + ("relative__username", "icontains"), + ] + self.assertEqual(search_fields, expected_search_fields) + + def test_search_query(self): + search_term = "search query" + self.request = self.build_get_request({"q": search_term}) + self.view.setup(self.request) + search_query = self.view.get_search_query() + self.assertEqual(search_query, search_term) + + def test_queryset_without_search_query(self): + self.view.setup(self.request) + queryset = self.view.get_queryset() + self.assertQuerysetEqual(queryset, InterpersonalRelationship.objects.all()) + + def test_queryset_with_search_query(self): + relationships = InterpersonalRelationshipFactory.create_batch(10) + search_term = relationships[0].person.full_name.split()[0] + self.request = self.build_get_request({"q": search_term}) + self.view.setup(self.request) + queryset = self.view.get_queryset() + self.assertQuerysetEqual( + queryset, search_interpersonal_relationships(search_term) ) - cls.user = UserFactory() - cls.authorized_user = UserFactory(user_permissions=tuple(view_relationships)) - cls.staff_user = UserFactory(is_staff=True) - - def test_anonymous_user_response(self): - response = self.client.get(self.url) - self.assertRedirects(response, f"/accounts/login/?next={self.url}") - - def test_authenticated_user_response(self): - self.client.force_login(self.user) - response = self.client.get(self.url) - self.assertEqual(response.status_code, 403) - - def test_authorized_user_response(self): - self.client.force_login(self.authorized_user) - response = self.client.get(self.url) - self.assertEqual(response.status_code, 200) - def test_staff_user_response(self): - self.client.force_login(self.staff_user) - response = self.client.get(self.url) - self.assertEqual(response.status_code, 403) - - def test_template_used(self): - self.client.force_login(self.authorized_user) - response = self.client.get(self.url) - self.assertTemplateUsed(response, "people/relationships_list.html") - - def test_context_data_contains_relationships(self): - self.client.force_login(self.authorized_user) - response = self.client.get(self.url) - self.assertIn("relationships", response.context) - - def test_is_paginated(self): - InterpersonalRelationshipFactory.create_batch(11) - self.client.force_login(self.authorized_user) - response = self.client.get(self.url) - self.assertTrue(response.context.get("is_paginated")) - self.assertEqual(len(response.context.get("relationships")), 10) - - def test_pagination_lists_all_items(self): - InterpersonalRelationshipFactory.create_batch(12) - self.client.force_login(self.authorized_user) - response = self.client.get(self.url + "?page=2") - expected_relationships = list(InterpersonalRelationship.objects.all())[-2:] - people = list(response.context.get("relationships")) - self.assertEqual(people, expected_relationships) + # MultipleObjectMixin + def test_paginate_by(self): + self.view.setup(self.request) + queryset = self.view.get_queryset() + paginate_by = self.view.get_paginate_by(queryset) + self.assertEqual(paginate_by, 10) + + def test_context_object_name(self): + self.view.setup(self.request) + queryset = self.view.get_queryset() + context_object_name = self.view.get_context_object_name(queryset) + self.assertEqual(context_object_name, "relationships") + + def test_context_data(self): + self.view.setup(self.request) + queryset = self.view.get_queryset() + self.view.object_list = queryset + context_object_name = self.view.get_context_object_name(queryset) + context_data = self.view.get_context_data() + expected_context_data_keys = [ + "paginator", + "page_obj", + "is_paginated", + "object_list", + context_object_name, + "view", + ] + self.assertEqual(list(context_data.keys()), expected_context_data_keys) + + # MultipleObjectTemplateResponseMixin + def test_template_name(self): + self.view.setup(self.request) + self.view.object_list = self.view.get_queryset() + template_names = self.view.get_template_names() + self.assertIn("people/relationships_list.html", template_names) + + # LoginRequiredMixin + def test_login_required(self): + self.request.user = AnonymousUser() + self.view.setup(self.request) + response = self.view.dispatch(self.request) + self.assertEqual(response.status_code, 302) + self.assertIn(reverse("account_login"), response.url) + + # PermissionRequiredMixin + def test_permission_required(self): + self.request.user = UserFactory() + self.view.setup(self.request) + permission_required = self.view.get_permission_required() + self.assertEqual( + permission_required, ("people.view_interpersonalrelationship",) + ) + # template logic def test_response_with_no_relationships(self): - self.client.force_login(self.authorized_user) - response = self.client.get(self.url) + # setup + self.request.user = self.authorized_user + response = self.view_func(self.request) + response.render() + + # test with self.assertRaises(AssertionError): self.assertInHTML(self.table_head, response.content.decode()) self.assertInHTML( @@ -679,9 +1278,13 @@ def test_response_with_no_relationships(self): ) def test_response_with_relationships(self): - InterpersonalRelationshipFactory.create_batch(3) - self.client.force_login(self.authorized_user) - response = self.client.get(self.url) + # setup + InterpersonalRelationshipFactory() + self.request.user = self.authorized_user + response = self.view_func(self.request) + response.render() + + # test with self.assertRaises(AssertionError): self.assertInHTML( "There are no interpersonal relationships yet!", @@ -689,24 +1292,15 @@ def test_response_with_relationships(self): ) self.assertInHTML(self.table_head, response.content.decode()) - def test_search_results(self): + def test_response_with_no_search_results(self): # setup - relationships = InterpersonalRelationshipFactory.create_batch(10) - search_term = relationships[0].person.username - self.client.force_login(self.authorized_user) + search_term = "does not exist" + self.request = self.build_get_request({"q": search_term}) + self.request.user = self.authorized_user + response = self.view_func(self.request) + response.render() # test - response = self.client.get(f"{self.url}?q={search_term}") - search_results = response.context.get("relationships") - self.assertQuerysetEqual( - search_results, search_interpersonal_relationships(search_term) - ) - - def test_response_with_no_search_results(self): - InterpersonalRelationshipFactory.create_batch(10) - self.client.force_login(self.authorized_user) - response = self.client.get(self.url + "?q=Does not exist") - self.assertEqual(list(response.context.get("relationships")), []) with self.assertRaises(AssertionError): self.assertInHTML(self.table_head, response.content.decode()) self.assertInHTML( @@ -714,83 +1308,168 @@ def test_response_with_no_search_results(self): ) -class RelationshipCreateViewTestCase(TestCase): +class InterpersonalRelationshipCreateViewTestCase(TestCase): @classmethod def setUpClass(cls): super().setUpClass() - cls.url = "/people/relationships/add/" - - # users - create_relationship = Permission.objects.filter( - name="Can add interpersonal relationship" - ) - view_relationship = Permission.objects.filter( - name="Can view interpersonal relationship" - ) - permissions = create_relationship | view_relationship cls.user = UserFactory() - cls.authorized_user = UserFactory(user_permissions=tuple(permissions)) - cls.staff_user = UserFactory(is_staff=True) - - # POST data cls.person = PersonFactory() cls.relative = PersonFactory() - cls.relation = InterpersonalRelationshipFactory.build().relation - cls.data = { + cls.relationship = InterpersonalRelationshipFactory.build( + person=cls.person, relative=cls.relative + ) + cls.form_data = { "person": cls.person.username, "relative": cls.relative.username, - "relation": cls.relation, + "relation": cls.relationship.relation, } - def test_anonymous_user_response(self): - response = self.client.get(self.url) - self.assertRedirects(response, f"/accounts/login/?next={self.url}") + def setUp(self): + self.factory = RequestFactory() + self.request = self.factory.post("dummy_path", data=self.form_data) + self.view_class = views.RelationshipCreateView + self.view_func = self.view_class.as_view() + self.view = self.view_class() + + def get_data(self): + data = self.form_data.copy() + data["person"] = self.person + data["relative"] = self.relative + return data + + # FormMixin + def test_initial(self): + self.view.setup(self.request) + initial = self.view.get_initial() + self.assertEqual(initial, {}) + + def test_prefix(self): + self.view.setup(self.request) + prefix = self.view.get_prefix() + self.assertIsNone(prefix) - def test_authenticated_user_response(self): - self.client.force_login(self.user) - response = self.client.get(self.url) - self.assertEqual(response.status_code, 403) + def test_form_class(self): + self.view.setup(self.request) + form_class = self.view.get_form_class() + self.assertEqual( + form_class, + import_string("people.forms.InterpersonalRelationshipCreationForm"), + ) - def test_authorized_user_response(self): - self.client.force_login(self.authorized_user) - response = self.client.get(self.url) - self.assertEqual(response.status_code, 200) + def test_form_kwargs(self): + self.view.setup(self.request) + form_kwargs = { + "initial": self.view.get_initial(), + "prefix": self.view.get_prefix(), + "data": self.request.POST, + "files": self.request.FILES, + } + self.assertEqual(self.view.get_form_kwargs(), form_kwargs) - def test_staff_user_response(self): - self.client.force_login(self.staff_user) - response = self.client.get(self.url) - self.assertEqual(response.status_code, 403) + def test_success_url(self): + self.view.setup(self.request) + self.view.object = self.relationship + success_url = self.view.get_success_url() + self.assertEqual(success_url, reverse("people:relationships_list")) - def test_template_used(self): - self.client.force_login(self.authorized_user) - response = self.client.get(self.url) - self.assertTemplateUsed(response, "people/relationship_form.html") + def test_form_invalid(self): + self.request.user = self.user + self.view.setup(self.request) + self.view.object = None + form = self.view.get_form() + response = self.view.form_invalid(form) + self.assertEqual(response.status_code, 200) - def test_form_class(self): - self.client.force_login(self.authorized_user) - response = self.client.get(self.url) - form = response.context.get("form") + # SuccessMessageMixin + def test_success_message(self): + self.request.user = self.user + self.view.setup(self.request) + self.view.object = self.relationship + data = self.get_data() + success_message = self.view.get_success_message(data) + people = f"{self.person} and {self.relative}" self.assertEqual( - form.__class__.__name__, "InterpersonalRelationshipCreationForm" - ) - self.assertIsInstance(form, import_string("django.forms.ModelForm")) - self.assertIsInstance( - form, import_string("people.forms.InterpersonalRelationshipCreationForm") + success_message, + f"The relationship between {people} has been added successfully.", ) - def test_form_valid(self): - self.client.force_login(self.authorized_user) - self.client.post(self.url, self.data) - relationship = InterpersonalRelationship.objects.get( - person__username=self.data["person"] + @patch("django.contrib.messages.success") + def test_form_valid_without_duplicate(self, mock_success): + self.request.user = self.user + self.view.setup(self.request) + form = self.view.get_form() + self.assertTrue(form.is_valid()) + response = self.view.form_valid(form) + self.assertTrue(mock_success.called) + self.assertEqual(response.status_code, 302) + relationship = InterpersonalRelationship.objects.get(person=self.person) + self.assertEqual(relationship.created_by, self.user) + + # ModelFormMixin + def test_form_valid_with_duplicate(self): + data = self.get_data() + InterpersonalRelationshipFactory(**data) + self.request.user = self.user + self.view.setup(self.request) + self.view.object = None + form = self.view.get_form() + self.assertFalse(form.is_valid()) + self.assertEqual( + form.errors, {"__all__": ["This interpersonal relationship already exists"]} ) - self.assertEqual(relationship.created_by, self.authorized_user) - def test_success_url(self): - self.client.force_login(self.authorized_user) - response = self.client.post(self.url, self.data) - self.assertRedirects(response, reverse("people:relationships_list")) + # SingleObjectMixin + def test_queryset(self): + self.view.setup(self.request) + with self.assertRaises(ImproperlyConfigured): + queryset = self.view.get_queryset() + self.assertEqual(list(queryset), []) + + def test_slug_field(self): + self.view.setup(self.request) + slug_field = self.view.get_slug_field() + self.assertEqual(slug_field, "slug") + + def test_object(self): + self.view.setup(self.request) + with self.assertRaises(ImproperlyConfigured): + obj = self.view.get_object() + self.assertIsNone(obj) + + def test_context_object_name(self): + self.view.setup(self.request) + with self.assertRaises(ImproperlyConfigured): + queryset = self.view.get_queryset() + context_object_name = self.view.get_context_object_name(queryset) + self.assertIsNone(context_object_name) + + def test_context_data(self): + self.view.setup(self.request) + self.view.object = None + context_data = self.view.get_context_data() + self.assertEqual(list(context_data.keys()), ["form", "view"]) + + # SingleObjectTemplateResponseMixin + def test_template_name(self): + self.view.setup(self.request) + template_names = self.view.get_template_names() + self.assertIn("people/relationship_form.html", template_names) + + # LoginRequiredMixin + def test_login_required(self): + self.request.user = AnonymousUser() + self.view.setup(self.request) + response = self.view.dispatch(self.request) + self.assertEqual(response.status_code, 302) + self.assertIn(reverse("account_login"), response.url) + + # PermissionRequiredMixin + def test_permission_required(self): + self.request.user = UserFactory() + self.view.setup(self.request) + permission_required = self.view.get_permission_required() + self.assertEqual(permission_required, ("people.add_interpersonalrelationship",)) class ParentChildRelationshipCreateViewTestCase(TestCase): @@ -798,81 +1477,183 @@ class ParentChildRelationshipCreateViewTestCase(TestCase): def setUpClass(cls): super().setUpClass() - # users cls.user = UserFactory() - cls.authorized_user = UserFactory() - cls.staff_user = UserFactory(is_staff=True) - - # people - cls.person = AdultFactory(user=cls.authorized_user) + cls.person = AdultFactory(user=cls.user) cls.parent = AdultFactory() cls.child = ChildFactory() - cls.url = f"/people/relationships/add/{cls.child.username}/parent/" - - # POST data - cls.data = {"person": cls.parent.username} - - def test_anonymous_user_response(self): - response = self.client.get(self.url) - self.assertRedirects(response, f"/accounts/login/?next={self.url}") - - def test_authenticated_user_response(self): - self.client.force_login(self.user) - response = self.client.get(self.url) - self.assertEqual(response.status_code, 403) - - def test_authorized_user_response(self): - self.client.force_login(self.authorized_user) - response = self.client.get(self.url) - self.assertEqual(response.status_code, 200) + cls.form_data = {"person": cls.parent.username} + cls.relationship_data = { + "person": cls.parent, + "relative": cls.child, + "relation": "PC", + } + cls.relationship = InterpersonalRelationshipFactory.build( + **cls.relationship_data + ) - def test_template_used(self): - self.client.force_login(self.authorized_user) - response = self.client.get(self.url) - self.assertTemplateUsed(response, "people/relationship_form.html") + def setUp(self): + self.factory = RequestFactory() + self.request = self.factory.post("dummy_path", data=self.form_data) + self.view_class = views.ParentChildRelationshipCreateView + self.view_func = self.view_class.as_view() + self.view = self.view_class() - def test_response_with_nonexistent_child(self): - self.client.force_login(self.authorized_user) - url = self.url.replace(self.child.username, "nonexistent-child") - response = self.client.get(url) - self.assertEqual(response.status_code, 404) + # FormMixin + def test_initial(self): + self.view.setup(self.request) + initial = self.view.get_initial() + self.assertEqual(initial, {}) - def test_context_data_contains_child(self): - self.client.force_login(self.authorized_user) - response = self.client.get(self.url) - self.assertEqual(response.context.get("child"), self.child) + def test_prefix(self): + self.view.setup(self.request) + prefix = self.view.get_prefix() + self.assertIsNone(prefix) def test_form_class(self): - self.client.force_login(self.authorized_user) - response = self.client.get(self.url) - form = response.context.get("form") - self.assertEqual(form.__class__.__name__, "ParentChildRelationshipCreationForm") - self.assertIsInstance(form, import_string("django.forms.ModelForm")) - self.assertIsInstance( - form, import_string("people.forms.ParentChildRelationshipCreationForm") + self.view.setup(self.request) + form_class = self.view.get_form_class() + self.assertEqual( + form_class, + import_string("people.forms.ParentChildRelationshipCreationForm"), ) + def test_form_kwargs(self): + self.view.setup(self.request) + form_kwargs = { + "initial": self.view.get_initial(), + "prefix": self.view.get_prefix(), + "data": self.request.POST, + "files": self.request.FILES, + } + self.assertEqual(self.view.get_form_kwargs(), form_kwargs) + + def test_success_url(self): + self.view.setup(self.request) + self.view.object = self.relationship + success_url = self.view.get_success_url() + self.assertEqual(success_url, reverse("core:dashboard")) + def test_form_invalid(self): - # setup - data = {"person": self.parent, "relative": self.child, "relation": "PC"} - InterpersonalRelationshipFactory(**data) - self.client.force_login(self.authorized_user) + self.request.user = self.user + self.view.setup(self.request, username=self.child.username) + self.view.object = None + form = self.view.get_form() + response = self.view.form_invalid(form) + self.assertEqual(response.status_code, 200) - # test - response = self.client.post(self.url, self.data) - form = response.context.get("form") - self.assertFalse(form.is_valid()) + # SuccessMessageMixin + def test_success_message(self): + self.request.user = self.user + self.view.setup(self.request) + self.view.object = self.relationship + data = self.form_data.copy() + success_message = self.view.get_success_message(data) + people = f"{self.parent} and {self.child}" self.assertEqual( - form.errors, {"__all__": ["This interpersonal relationship already exists"]} + success_message, + f"A parent-child relationship between {people} has been added.", ) - def test_form_valid(self): - self.client.force_login(self.authorized_user) - self.client.post(self.url, self.data) - relationship = InterpersonalRelationship.objects.get(relative=self.child) - self.assertEqual(relationship.created_by, self.authorized_user) + @patch("django.contrib.messages.success") + def test_form_valid_without_duplicate(self, mock_success): + self.request.user = self.user + self.view.setup(self.request, username=self.child.username) + form = self.view.get_form() + self.assertTrue(form.is_valid()) + response = self.view.form_valid(form) + self.assertTrue(mock_success.called) + self.assertEqual(response.status_code, 302) + relationship = InterpersonalRelationship.objects.get(person=self.parent) + self.assertEqual(relationship.created_by, self.user) + self.assertEqual(relationship.relation, "PC") + + # ModelFormMixin + def test_form_valid_with_duplicate(self): + # setup + InterpersonalRelationshipFactory(**self.relationship_data) + self.request.user = self.user + self.view.setup(self.request, username=self.child.username) + self.view.object = None + form = self.view.get_form() + self.assertTrue(form.is_valid()) + response = self.view.form_valid(form) - def test_success_url(self): - self.client.force_login(self.authorized_user) - response = self.client.post(self.url, self.data) - self.assertRedirects(response, reverse("core:dashboard")) + # test + self.assertEqual(response.status_code, 200) + response.render() + error_message = "This interpersonal relationship already exists" + self.assertInHTML(error_message, str(response.content)) + + # SingleObjectMixin + def test_queryset(self): + self.view.setup(self.request) + with self.assertRaises(ImproperlyConfigured): + queryset = self.view.get_queryset() + self.assertEqual(list(queryset), []) + + def test_slug_field(self): + self.view.setup(self.request) + slug_field = self.view.get_slug_field() + self.assertEqual(slug_field, "slug") + + def test_object(self): + self.view.setup(self.request) + with self.assertRaises(ImproperlyConfigured): + obj = self.view.get_object() + self.assertIsNone(obj) + + def test_child_with_existing_person(self): + self.view.setup(self.request, username=self.child.username) + obj = self.view.get_child() + self.assertEqual(obj, self.child) + + def test_child_with_non_existent_person(self): + self.view.setup(self.request, username="non-existent-person") + with self.assertRaises(Http404): + self.view.get_child() + + def test_context_object_name(self): + self.view.setup(self.request) + with self.assertRaises(ImproperlyConfigured): + queryset = self.view.get_queryset() + context_object_name = self.view.get_context_object_name(queryset) + self.assertIsNone(context_object_name) + + def test_context_data(self): + self.view.setup(self.request, username=self.child.username) + self.view.object = None + context_data = self.view.get_context_data() + self.assertEqual(list(context_data.keys()), ["form", "view", "child"]) + self.assertEqual(context_data.get("child"), self.child) + + # SingleObjectTemplateResponseMixin + def test_template_name(self): + self.view.setup(self.request) + template_names = self.view.get_template_names() + self.assertIn("people/relationship_form.html", template_names) + + # LoginRequiredMixin + def test_login_required(self): + self.request.user = AnonymousUser() + self.view.setup(self.request) + response = self.view.dispatch(self.request) + self.assertEqual(response.status_code, 302) + self.assertIn(reverse("account_login"), response.url) + + # PermissionRequiredMixin + def test_permission_required(self): + self.request.user = UserFactory() + self.view.setup(self.request) + permission_required = self.view.get_permission_required() + self.assertEqual(permission_required, ()) + + # UserPassesTestMixin + def test_test_func_false(self): + self.request.user = UserFactory() + self.view.setup(self.request) + self.assertFalse(self.view.test_func()) + + def test_test_func_true(self): + self.request.user = self.user + self.view.setup(self.request) + self.assertTrue(self.view.test_func()) diff --git a/people/tests/test_views_.py b/people/tests/test_views_.py deleted file mode 100644 index 6a1dd11c..00000000 --- a/people/tests/test_views_.py +++ /dev/null @@ -1,1659 +0,0 @@ -from unittest.mock import call, patch - -from django.contrib.auth.models import AnonymousUser, Permission -from django.core.exceptions import ImproperlyConfigured -from django.http.response import Http404 -from django.test import RequestFactory, TestCase -from django.urls import reverse -from django.utils.module_loading import import_string - -from accounts.factories import UserFactory -from people import views -from people.factories import ( - AdultFactory, - ChildFactory, - InterpersonalRelationshipFactory, - PersonFactory, -) -from people.models import InterpersonalRelationship, Person - -from .helpers import search_interpersonal_relationships, search_people - - -class PeopleListViewTestCase(TestCase): - @classmethod - def setUpClass(cls): - super().setUpClass() - - cls.authorized_user = cls.get_authorized_user() - - def setUp(self): - self.factory = RequestFactory() - self.request = self.build_get_request() - self.view_class = views.PeopleListView - self.view_func = self.view_class.as_view() - self.view = self.view_class() - - def build_get_request(self, data=None): - return self.factory.get("dummy_path", data=data) - - @staticmethod - def get_authorized_user(): - view_person = Permission.objects.filter(name="Can view person") - return UserFactory(user_permissions=tuple(view_person)) - - @property - def table_head(self): - thead = """ - - - # - Username - Full name - Age category - Actions - - - """ - return thead - - # MultipleObjectMixin - def test_allow_empty(self): - self.view.setup(self.request) - allow_empty = self.view.get_allow_empty() - self.assertTrue(allow_empty) - - def test_ordering(self): - self.view.setup(self.request) - ordering = self.view.get_ordering() - self.assertIsNone(ordering) - - # SearchableListMixin - def test_search_fields(self): - self.view.setup(self.request) - search_fields = self.view.get_search_fields_with_filters() - expected_search_fields = [("username", "icontains"), ("full_name", "icontains")] - self.assertEqual(search_fields, expected_search_fields) - - def test_search_query(self): - search_term = "search query" - self.request = self.build_get_request({"q": search_term}) - self.view.setup(self.request) - search_query = self.view.get_search_query() - self.assertEqual(search_query, search_term) - - def test_queryset_without_search_query(self): - self.view.setup(self.request) - queryset = self.view.get_queryset() - self.assertQuerysetEqual(queryset, Person.objects.all()) - - def test_queryset_with_search_query(self): - people = PersonFactory.create_batch(10) - search_term = people[0].full_name.split()[0] - self.request = self.build_get_request({"q": search_term}) - self.view.setup(self.request) - queryset = self.view.get_queryset() - self.assertQuerysetEqual(queryset, search_people(search_term)) - - # MultipleObjectMixin - def test_paginate_by(self): - self.view.setup(self.request) - queryset = self.view.get_queryset() - paginate_by = self.view.get_paginate_by(queryset) - self.assertEqual(paginate_by, 10) - - def test_context_object_name(self): - self.view.setup(self.request) - queryset = self.view.get_queryset() - context_object_name = self.view.get_context_object_name(queryset) - self.assertEqual(context_object_name, "people") - - def test_context_data(self): - self.view.setup(self.request) - queryset = self.view.get_queryset() - self.view.object_list = queryset - context_object_name = self.view.get_context_object_name(queryset) - context_data = self.view.get_context_data() - expected_context_data_keys = [ - "paginator", - "page_obj", - "is_paginated", - "object_list", - context_object_name, - "view", - ] - self.assertEqual(list(context_data.keys()), expected_context_data_keys) - - # MultipleObjectTemplateResponseMixin - def test_template_name(self): - self.view.setup(self.request) - self.view.object_list = self.view.get_queryset() - template_names = self.view.get_template_names() - self.assertIn("people/people_list.html", template_names) - - # LoginRequiredMixin - def test_login_required(self): - self.request.user = AnonymousUser() - self.view.setup(self.request) - response = self.view.dispatch(self.request) - self.assertEqual(response.status_code, 302) - self.assertIn(reverse("account_login"), response.url) - - # PermissionRequiredMixin - def test_permission_required(self): - self.request.user = UserFactory() - self.view.setup(self.request) - permission_required = self.view.get_permission_required() - self.assertEqual(permission_required, ("people.view_person",)) - - # template logic - def test_response_with_no_people(self): - # setup - self.request.user = self.authorized_user - response = self.view_func(self.request) - response.render() - - # test - with self.assertRaises(AssertionError): - self.assertInHTML(self.table_head, response.content.decode()) - self.assertInHTML("There are no people yet!", response.content.decode()) - - def test_response_with_people(self): - # setup - PersonFactory() - self.request.user = self.authorized_user - response = self.view_func(self.request) - response.render() - - # test - with self.assertRaises(AssertionError): - self.assertInHTML("There are no people yet!", response.content.decode()) - self.assertInHTML(self.table_head, response.content.decode()) - - def test_response_with_no_search_results(self): - # setup - search_term = "does not exist" - self.request = self.build_get_request({"q": search_term}) - self.request.user = self.authorized_user - response = self.view_func(self.request) - response.render() - - # test - with self.assertRaises(AssertionError): - self.assertInHTML(self.table_head, response.content.decode()) - self.assertInHTML( - "Your search didn't yield any results", response.content.decode() - ) - - -class PersonDetailViewTestCase(TestCase): - @classmethod - def setUpClass(cls): - super().setUpClass() - - cls.person = PersonFactory() - - def setUp(self): - self.factory = RequestFactory() - self.request = self.factory.get("dummy_path") - self.view_class = views.PersonDetailView - self.view_func = self.view_class.as_view() - self.view = self.view_class() - - # SingleObjectMixin - def test_queryset(self): - self.view.setup(self.request) - queryset = self.view.get_queryset() - self.assertEqual(list(queryset), [self.person]) - - def test_slug_field(self): - self.view.setup(self.request) - slug_field = self.view.get_slug_field() - self.assertEqual(slug_field, "username") - - def test_object_with_existing_person(self): - self.view.setup(self.request, username=self.person.username) - obj = self.view.get_object() - self.assertEqual(obj, self.person) - - def test_object_with_non_existent_person(self): - self.view.setup(self.request, username="non-existent-person") - with self.assertRaises(Http404): - self.view.get_object() - - def test_context_object_name(self): - self.view.setup(self.request, username=self.person.username) - obj = self.view.get_object() - context_object_name = self.view.get_context_object_name(obj) - self.assertEqual(context_object_name, "person") - - def test_context_data(self): - self.view.setup(self.request, username=self.person.username) - obj = self.view.get_object() - self.view.object = obj - context_object_name = self.view.get_context_object_name(obj) - context_data = self.view.get_context_data() - expected_context_data_keys = ["object", context_object_name, "view"] - self.assertEqual(list(context_data.keys()), expected_context_data_keys) - - # SingleObjectTemplateResponseMixin - def test_template_name(self): - self.view.setup(self.request) - template_names = self.view.get_template_names() - self.assertIn("people/person_detail.html", template_names) - - # LoginRequiredMixin - def test_login_required(self): - self.request.user = AnonymousUser() - self.view.setup(self.request) - response = self.view.dispatch(self.request) - self.assertEqual(response.status_code, 302) - self.assertIn(reverse("account_login"), response.url) - - # PermissionRequiredMixin - def test_permission_required(self): - self.request.user = UserFactory() - self.view.setup(self.request) - permission_required = self.view.get_permission_required() - self.assertEqual(permission_required, ("people.view_person",)) - - -class PersonCreateViewTestCase(TestCase): - @classmethod - def setUpClass(cls): - super().setUpClass() - - cls.user = UserFactory() - cls.person = PersonFactory.build() - cls.form_data = { - "username": cls.person.username, - "full_name": cls.person.full_name, - "gender": cls.person.gender, - "dob": cls.person.dob, - } - - def setUp(self): - self.factory = RequestFactory() - self.request = self.factory.post("dummy_path", data=self.form_data) - self.view_class = views.PersonCreateView - self.view_func = self.view_class.as_view() - self.view = self.view_class() - - def create_duplicate(self): - data = self.form_data.copy() - data["username"] = PersonFactory.build().username - data["created_by"] = self.user - PersonFactory(**data) - - # FormMixin - def test_initial(self): - self.view.setup(self.request) - initial = self.view.get_initial() - self.assertEqual(initial, {}) - - def test_prefix(self): - self.view.setup(self.request) - prefix = self.view.get_prefix() - self.assertIsNone(prefix) - - def test_form_class(self): - self.view.setup(self.request) - form_class = self.view.get_form_class() - self.assertEqual(form_class, import_string("people.forms.PersonCreationForm")) - - def test_form_kwargs(self): - self.view.setup(self.request) - form_kwargs = { - "initial": self.view.get_initial(), - "prefix": self.view.get_prefix(), - "data": self.request.POST, - "files": self.request.FILES, - } - self.assertEqual(self.view.get_form_kwargs(), form_kwargs) - - def test_success_url(self): - self.view.setup(self.request) - self.view.object = self.person - success_url = self.view.get_success_url() - self.assertEqual( - success_url, - reverse( - "people:person_detail", kwargs={"username": self.form_data["username"]} - ), - ) - - def test_form_invalid(self): - self.request.user = self.user - self.view.setup(self.request) - self.view.object = None - form = self.view.get_form() - response = self.view.form_invalid(form) - self.assertEqual(response.status_code, 200) - - # SuccessMessageMixin - def test_success_message(self): - self.request.user = self.user - self.view.setup(self.request) - self.view.object = self.person - success_message = self.view.get_success_message(self.form_data) - self.assertEqual( - success_message, f"{self.person}'s information has been added successfully." - ) - - @patch("django.contrib.messages.success") - def test_form_valid_without_duplicate(self, mock_success): - self.request.user = self.user - self.view.setup(self.request) - form = self.view.get_form() - self.assertTrue(form.is_valid()) - response = self.view.form_valid(form) - self.assertTrue(mock_success.called) - self.assertEqual(response.status_code, 302) - person = Person.objects.get(username=self.form_data["username"]) - self.assertEqual(person.created_by, self.user) - - # ModelFormMixin - def test_form_valid_with_duplicate(self): - # setup - self.create_duplicate() - self.request.user = self.user - self.view.setup(self.request) - self.view.object = None - form = self.view.get_form() - self.assertTrue(form.is_valid()) - response = self.view.form_valid(form) - - # test - self.assertEqual(response.status_code, 200) - response.render() - error_message = "This person already exists" - self.assertInHTML(error_message, str(response.content)) - - # SingleObjectMixin - def test_queryset(self): - self.view.setup(self.request) - with self.assertRaises(ImproperlyConfigured): - queryset = self.view.get_queryset() - self.assertEqual(list(queryset), []) - - def test_slug_field(self): - self.view.setup(self.request) - slug_field = self.view.get_slug_field() - self.assertEqual(slug_field, "slug") - - def test_object(self): - self.view.setup(self.request) - with self.assertRaises(ImproperlyConfigured): - obj = self.view.get_object() - self.assertIsNone(obj) - - def test_context_object_name(self): - self.view.setup(self.request) - with self.assertRaises(ImproperlyConfigured): - queryset = self.view.get_queryset() - context_object_name = self.view.get_context_object_name(queryset) - self.assertIsNone(context_object_name) - - def test_context_data(self): - self.view.setup(self.request) - self.view.object = None - context_data = self.view.get_context_data() - self.assertEqual(list(context_data.keys()), ["form", "view", "action"]) - self.assertEqual(context_data.get("action"), "add") - - # SingleObjectTemplateResponseMixin - def test_template_name(self): - self.view.setup(self.request) - template_names = self.view.get_template_names() - self.assertIn("people/person_form.html", template_names) - - # LoginRequiredMixin - def test_login_required(self): - self.request.user = AnonymousUser() - self.view.setup(self.request) - response = self.view.dispatch(self.request) - self.assertEqual(response.status_code, 302) - self.assertIn(reverse("account_login"), response.url) - - # PermissionRequiredMixin - def test_permission_required(self): - self.request.user = UserFactory() - self.view.setup(self.request) - permission_required = self.view.get_permission_required() - self.assertEqual(permission_required, ("people.add_person",)) - - -class AdultCreateViewTestCase(TestCase): - @classmethod - def setUpClass(cls): - super().setUpClass() - - cls.user = UserFactory() - cls.person = AdultFactory.build() - cls.form_data = { - "username": cls.person.username, - "full_name": cls.person.full_name, - "gender": cls.person.gender, - "dob": cls.person.dob, - "phone_number": cls.person.phone_number, - } - - def setUp(self): - self.factory = RequestFactory() - self.request = self.factory.post("dummy_path", data=self.form_data) - self.view_class = views.AdultCreateView - self.view_func = self.view_class.as_view() - self.view = self.view_class() - - def create_duplicate(self): - data = self.form_data.copy() - data["username"] = AdultFactory.build().username - data["created_by"] = self.user - AdultFactory(**data) - - # FormMixin - def test_initial(self): - self.view.setup(self.request) - initial = self.view.get_initial() - self.assertEqual(initial, {}) - - def test_prefix(self): - self.view.setup(self.request) - prefix = self.view.get_prefix() - self.assertIsNone(prefix) - - def test_form_class(self): - self.view.setup(self.request) - form_class = self.view.get_form_class() - self.assertEqual(form_class, import_string("people.forms.AdultCreationForm")) - - def test_form_kwargs(self): - self.view.setup(self.request) - form_kwargs = { - "initial": self.view.get_initial(), - "prefix": self.view.get_prefix(), - "data": self.request.POST, - "files": self.request.FILES, - } - self.assertEqual(self.view.get_form_kwargs(), form_kwargs) - - def test_success_url(self): - self.view.setup(self.request) - self.view.object = self.person - success_url = self.view.get_success_url() - self.assertEqual( - success_url, - reverse( - "people:person_detail", kwargs={"username": self.form_data["username"]} - ), - ) - - def test_form_invalid(self): - self.request.user = self.user - self.view.setup(self.request) - self.view.object = None - form = self.view.get_form() - response = self.view.form_invalid(form) - self.assertEqual(response.status_code, 200) - - # SuccessMessageMixin - def test_success_message(self): - self.request.user = self.user - self.view.setup(self.request) - self.view.object = self.person - success_message = self.view.get_success_message(self.form_data) - self.assertEqual( - success_message, f"{self.person}'s information has been added successfully." - ) - - @patch("django.contrib.messages.success") - def test_form_valid_without_duplicate(self, mock_success): - self.request.user = self.user - self.view.setup(self.request) - form = self.view.get_form() - self.assertTrue(form.is_valid()) - response = self.view.form_valid(form) - self.assertTrue(mock_success.called) - self.assertEqual(response.status_code, 302) - person = Person.objects.get(username=self.form_data["username"]) - self.assertEqual(person.created_by, self.user) - - # ModelFormMixin - def test_form_valid_with_duplicate(self): - # setup - self.create_duplicate() - self.request.user = self.user - self.view.setup(self.request) - self.view.object = None - form = self.view.get_form() - self.assertTrue(form.is_valid()) - response = self.view.form_valid(form) - - # test - self.assertEqual(response.status_code, 200) - response.render() - error_message = "This person already exists" - self.assertInHTML(error_message, str(response.content)) - - # SingleObjectMixin - def test_queryset(self): - self.view.setup(self.request) - with self.assertRaises(ImproperlyConfigured): - queryset = self.view.get_queryset() - self.assertEqual(list(queryset), []) - - def test_slug_field(self): - self.view.setup(self.request) - slug_field = self.view.get_slug_field() - self.assertEqual(slug_field, "slug") - - def test_object(self): - self.view.setup(self.request) - with self.assertRaises(ImproperlyConfigured): - obj = self.view.get_object() - self.assertIsNone(obj) - - def test_context_object_name(self): - self.view.setup(self.request) - with self.assertRaises(ImproperlyConfigured): - queryset = self.view.get_queryset() - context_object_name = self.view.get_context_object_name(queryset) - self.assertIsNone(context_object_name) - - def test_context_data(self): - self.view.setup(self.request) - self.view.object = None - context_data = self.view.get_context_data() - self.assertEqual( - list(context_data.keys()), ["form", "view", "action", "age_category"] - ) - self.assertEqual(context_data.get("action"), "add") - self.assertEqual(context_data.get("age_category"), "an adult") - - # SingleObjectTemplateResponseMixin - def test_template_name(self): - self.view.setup(self.request) - template_names = self.view.get_template_names() - self.assertIn("people/person_form.html", template_names) - - # LoginRequiredMixin - def test_login_required(self): - self.request.user = AnonymousUser() - self.view.setup(self.request) - response = self.view.dispatch(self.request) - self.assertEqual(response.status_code, 302) - self.assertIn(reverse("account_login"), response.url) - - # PermissionRequiredMixin - def test_permission_required(self): - self.request.user = UserFactory() - self.view.setup(self.request) - permission_required = self.view.get_permission_required() - self.assertEqual(permission_required, ("people.add_person",)) - - -class AdultSelfRegisterViewTestCase(TestCase): - @classmethod - def setUpClass(cls): - super().setUpClass() - - cls.user = UserFactory() - cls.person = AdultFactory.build() - cls.form_data = { - "username": cls.person.username, - "full_name": cls.person.full_name, - "gender": cls.person.gender, - "dob": cls.person.dob, - "phone_number": cls.person.phone_number, - } - - def setUp(self): - self.factory = RequestFactory() - self.request = self.factory.post("dummy_path", data=self.form_data) - self.view_class = views.AdultSelfRegisterView - self.view_func = self.view_class.as_view() - self.view = self.view_class() - - def create_duplicate(self): - data = self.form_data.copy() - data["username"] = AdultFactory.build().username - data["created_by"] = self.user - AdultFactory(**data) - - # FormMixin - def test_initial(self): - self.view.setup(self.request) - initial = self.view.get_initial() - self.assertEqual(initial, {}) - - def test_prefix(self): - self.view.setup(self.request) - prefix = self.view.get_prefix() - self.assertIsNone(prefix) - - def test_form_class(self): - self.view.setup(self.request) - form_class = self.view.get_form_class() - self.assertEqual(form_class, import_string("people.forms.AdultCreationForm")) - - def test_form_kwargs(self): - self.view.setup(self.request) - form_kwargs = { - "initial": self.view.get_initial(), - "prefix": self.view.get_prefix(), - "data": self.request.POST, - "files": self.request.FILES, - } - self.assertEqual(self.view.get_form_kwargs(), form_kwargs) - - def test_success_url(self): - self.view.setup(self.request) - self.view.object = self.person - success_url = self.view.get_success_url() - self.assertEqual(success_url, reverse("core:dashboard")) - - def test_form_invalid(self): - self.request.user = self.user - self.view.setup(self.request) - self.view.object = None - form = self.view.get_form() - response = self.view.form_invalid(form) - self.assertEqual(response.status_code, 200) - - # SuccessMessageMixin - def test_success_message(self): - self.request.user = self.user - self.view.setup(self.request) - self.view.object = self.person - success_message = self.view.get_success_message(self.form_data) - self.assertEqual( - success_message, f"{self.person}'s information has been added successfully." - ) - - @patch("django.contrib.messages.success") - def test_form_valid_without_duplicate(self, mock_success): - self.request.user = self.user - self.view.setup(self.request) - form = self.view.get_form() - self.assertTrue(form.is_valid()) - response = self.view.form_valid(form) - self.assertTrue(mock_success.called) - self.assertEqual(response.status_code, 302) - person = Person.objects.get(username=self.form_data["username"]) - self.assertEqual(person.created_by, self.user) - self.assertEqual(person.user, self.user) - - # ModelFormMixin - def test_form_valid_with_duplicate(self): - # setup - self.create_duplicate() - self.request.user = self.user - self.view.setup(self.request) - self.view.object = None - form = self.view.get_form() - self.assertTrue(form.is_valid()) - response = self.view.form_valid(form) - - # test - self.assertEqual(response.status_code, 200) - response.render() - error_message = "This person already exists" - self.assertInHTML(error_message, str(response.content)) - - # SingleObjectMixin - def test_queryset(self): - self.view.setup(self.request) - with self.assertRaises(ImproperlyConfigured): - queryset = self.view.get_queryset() - self.assertEqual(list(queryset), []) - - def test_slug_field(self): - self.view.setup(self.request) - slug_field = self.view.get_slug_field() - self.assertEqual(slug_field, "slug") - - def test_object(self): - self.view.setup(self.request) - with self.assertRaises(ImproperlyConfigured): - obj = self.view.get_object() - self.assertIsNone(obj) - - def test_context_object_name(self): - self.view.setup(self.request) - with self.assertRaises(ImproperlyConfigured): - queryset = self.view.get_queryset() - context_object_name = self.view.get_context_object_name(queryset) - self.assertIsNone(context_object_name) - - def test_context_data(self): - self.view.setup(self.request) - self.view.object = None - context_data = self.view.get_context_data() - self.assertEqual( - list(context_data.keys()), ["form", "view", "action", "age_category"] - ) - self.assertEqual(context_data.get("action"), "add") - self.assertEqual(context_data.get("age_category"), "an adult") - - # SingleObjectTemplateResponseMixin - def test_template_name(self): - self.view.setup(self.request) - template_names = self.view.get_template_names() - self.assertIn("people/self_register_form.html", template_names) - - # LoginRequiredMixin - def test_login_required(self): - self.request.user = AnonymousUser() - self.view.setup(self.request) - response = self.view.dispatch(self.request) - self.assertEqual(response.status_code, 302) - self.assertIn(reverse("account_login"), response.url) - - # PermissionRequiredMixin - def test_permission_required(self): - self.request.user = UserFactory() - self.view.setup(self.request) - permission_required = self.view.get_permission_required() - self.assertEqual(permission_required, ()) - - -class ChildCreateViewTestCase(TestCase): - @classmethod - def setUpClass(cls): - super().setUpClass() - - cls.user = UserFactory() - cls.parent = AdultFactory(user=cls.user) - cls.person = ChildFactory.build() - cls.form_data = { - "username": cls.person.username, - "full_name": cls.person.full_name, - "gender": cls.person.gender, - "dob": cls.person.dob, - } - - def setUp(self): - self.factory = RequestFactory() - self.request = self.build_post_request(self.form_data) - self.view_class = views.ChildCreateView - self.view_func = self.view_class.as_view() - self.view = self.view_class() - - def build_post_request(self, data=None): - return self.factory.post("dummy_path", data=data) - - def create_duplicate(self): - data = self.form_data.copy() - data["username"] = ChildFactory.build().username - data["created_by"] = self.user - ChildFactory(**data) - - # FormMixin - def test_initial(self): - self.view.setup(self.request) - initial = self.view.get_initial() - self.assertEqual(initial, {}) - - def test_prefix(self): - self.view.setup(self.request) - prefix = self.view.get_prefix() - self.assertIsNone(prefix) - - def test_form_class(self): - self.view.setup(self.request) - form_class = self.view.get_form_class() - self.assertEqual(form_class, import_string("people.forms.ChildCreationForm")) - - def test_form_kwargs(self): - self.view.setup(self.request) - form_kwargs = { - "initial": self.view.get_initial(), - "prefix": self.view.get_prefix(), - "data": self.request.POST, - "files": self.request.FILES, - } - self.assertEqual(self.view.get_form_kwargs(), form_kwargs) - - def test_success_url_when_creator_is_the_parent(self): - self.view.setup(self.request) - self.view.object = self.person - success_url = self.view.get_success_url(is_parent=True) - self.assertEqual(success_url, reverse("core:dashboard")) - - def test_success_url_when_creator_is_not_the_parent(self): - self.view.setup(self.request) - self.view.object = self.person - success_url = self.view.get_success_url() - self.assertEqual( - success_url, - reverse( - "people:parent_child_relationship_create", - kwargs={"username": self.person.username}, - ), - ) - - def test_form_invalid(self): - self.request.user = self.user - self.view.setup(self.request) - self.view.object = None - form = self.view.get_form() - response = self.view.form_invalid(form) - self.assertEqual(response.status_code, 200) - - # SuccessMessageMixin - def test_success_message(self): - self.request.user = self.user - self.view.setup(self.request) - self.view.object = self.person - success_message = self.view.get_success_message(self.form_data) - self.assertEqual( - success_message, f"{self.person}'s information has been added successfully." - ) - - @patch("django.contrib.messages.success") - def test_form_valid_when_creator_is_not_the_parent(self, mock_success): - self.request.user = self.user - self.view.setup(self.request) - form = self.view.get_form() - self.assertTrue(form.is_valid()) - response = self.view.form_valid(form) - self.assertTrue(mock_success.called) - self.assertEqual(response.status_code, 302) - person = Person.objects.get(username=self.form_data["username"]) - self.assertEqual(person.created_by, self.user) - self.assertEqual(person.user, None) - - @patch("django.contrib.messages.info") - def test_create_relationship(self, mock_info): - # setup - child = ChildFactory(**self.form_data) - self.request.user = self.user - self.view.setup(self.request) - self.view.object = child - self.view.create_relationship() - - # test - relationship = InterpersonalRelationship.objects.get(relative=child) - self.assertEqual(relationship.relation, "PC") - self.assertEqual(relationship.person, self.parent) - self.assertEqual(relationship.created_by, self.user) - self.assertTrue(mock_info.called) - message = f"A parent-child relationship between {self.parent} and {child}" - message += " has been added." - self.assertEqual(mock_info.call_args, call(self.request, message)) - - @patch("django.contrib.messages.success") - @patch("django.contrib.messages.info") - def test_form_valid_when_creator_is_the_parent(self, mock_success, mock_info): - # setup - data = self.form_data.copy() - data["is_parent"] = True - self.request = self.build_post_request(data) - self.request.user = self.user - self.view.setup(self.request) - form = self.view.get_form() - - # test - self.assertTrue(form.is_valid()) - response = self.view.form_valid(form) - self.assertTrue(mock_success.called) - self.assertEqual(response.status_code, 302) - person = Person.objects.get(username=self.form_data["username"]) - self.assertEqual(person.created_by, self.user) - self.assertEqual(person.user, None) - self.assertTrue(mock_info.called) - - # ModelFormMixin - def test_form_valid_with_duplicate(self): - # setup - self.create_duplicate() - self.request.user = self.user - self.view.setup(self.request) - self.view.object = None - form = self.view.get_form() - self.assertTrue(form.is_valid()) - response = self.view.form_valid(form) - - # test - self.assertEqual(response.status_code, 200) - response.render() - error_message = "This person already exists" - self.assertInHTML(error_message, str(response.content)) - - # SingleObjectMixin - def test_queryset(self): - self.view.setup(self.request) - with self.assertRaises(ImproperlyConfigured): - queryset = self.view.get_queryset() - self.assertEqual(list(queryset), []) - - def test_slug_field(self): - self.view.setup(self.request) - slug_field = self.view.get_slug_field() - self.assertEqual(slug_field, "slug") - - def test_object(self): - self.view.setup(self.request) - with self.assertRaises(ImproperlyConfigured): - obj = self.view.get_object() - self.assertIsNone(obj) - - def test_context_object_name(self): - self.view.setup(self.request) - with self.assertRaises(ImproperlyConfigured): - queryset = self.view.get_queryset() - context_object_name = self.view.get_context_object_name(queryset) - self.assertIsNone(context_object_name) - - def test_context_data(self): - self.view.setup(self.request) - self.view.object = None - context_data = self.view.get_context_data() - self.assertEqual( - list(context_data.keys()), ["form", "view", "action", "age_category"] - ) - self.assertEqual(context_data.get("action"), "add") - self.assertEqual(context_data.get("age_category"), "a child") - - # SingleObjectTemplateResponseMixin - def test_template_name(self): - self.view.setup(self.request) - template_names = self.view.get_template_names() - self.assertIn("people/person_form.html", template_names) - - # LoginRequiredMixin - def test_login_required(self): - self.request.user = AnonymousUser() - self.view.setup(self.request) - response = self.view.dispatch(self.request) - self.assertEqual(response.status_code, 302) - self.assertIn(reverse("account_login"), response.url) - - # PermissionRequiredMixin - def test_permission_required(self): - self.request.user = UserFactory() - self.view.setup(self.request) - permission_required = self.view.get_permission_required() - self.assertEqual(permission_required, ()) - - # UserPassesTestMixin - def test_test_func_false(self): - self.request.user = UserFactory() - self.view.setup(self.request) - self.assertFalse(self.view.test_func()) - - def test_test_func_true(self): - user = UserFactory() - AdultFactory(user=user) - self.request.user = user - self.view.setup(self.request) - self.assertTrue(self.view.test_func()) - - -class PersonUpdateViewTestCase(TestCase): - @classmethod - def setUpClass(cls): - super().setUpClass() - - cls.user = UserFactory() - cls.person = PersonFactory() - cls.form_data = { - "username": cls.person.username, - "full_name": cls.person.full_name, - "gender": cls.person.gender, - "dob": cls.person.dob, - } - - def setUp(self): - self.factory = RequestFactory() - self.request = self.factory.post("dummy_path", data=self.form_data) - self.view_class = views.PersonUpdateView - self.view_func = self.view_class.as_view() - self.view = self.view_class() - - # FormMixin - def test_initial(self): - self.view.setup(self.request) - initial = self.view.get_initial() - self.assertEqual(initial, {}) - - def test_prefix(self): - self.view.setup(self.request) - prefix = self.view.get_prefix() - self.assertIsNone(prefix) - - def test_form_class(self): - self.view.setup(self.request) - form_class = self.view.get_form_class() - self.assertEqual(form_class, import_string("people.forms.PersonUpdateForm")) - - def test_form_kwargs(self): - self.view.setup(self.request) - form_kwargs = { - "initial": self.view.get_initial(), - "prefix": self.view.get_prefix(), - "data": self.request.POST, - "files": self.request.FILES, - } - self.assertEqual(self.view.get_form_kwargs(), form_kwargs) - - def test_success_url(self): - self.view.setup(self.request) - self.view.object = self.person - success_url = self.view.get_success_url() - self.assertEqual( - success_url, - reverse( - "people:person_detail", kwargs={"username": self.form_data["username"]} - ), - ) - - def test_form_invalid(self): - self.request.user = self.user - self.view.setup(self.request) - self.view.object = None - form = self.view.get_form() - response = self.view.form_invalid(form) - self.assertEqual(response.status_code, 200) - - # SuccessMessageMixin - def test_success_message(self): - self.request.user = self.user - self.view.setup(self.request) - self.view.object = self.person - success_message = self.view.get_success_message(self.form_data) - self.assertEqual( - success_message, - f"{self.person}'s information has been updated successfully.", - ) - - @patch("django.contrib.messages.success") - def test_form_valid(self, mock_success): - self.request.user = self.user - self.view.setup(self.request, username=self.person.username) - self.view.object = self.view.get_object() - form = self.view.get_form() - self.assertTrue(form.is_valid()) - response = self.view.form_valid(form) - self.assertTrue(mock_success.called) - self.assertEqual(response.status_code, 302) - - # SingleObjectMixin - def test_queryset(self): - self.view.setup(self.request) - queryset = self.view.get_queryset() - self.assertEqual(list(queryset), [self.person]) - - def test_slug_field(self): - self.view.setup(self.request) - slug_field = self.view.get_slug_field() - self.assertEqual(slug_field, "username") - - def test_object(self): - self.view.setup(self.request, username=self.person.username) - obj = self.view.get_object() - self.assertEqual(obj, self.person) - - def test_context_object_name(self): - self.view.setup(self.request, username=self.person.username) - obj = self.view.get_object() - context_object_name = self.view.get_context_object_name(obj) - self.assertEqual(context_object_name, "person") - - def test_context_data(self): - self.view.setup(self.request) - self.view.object = None - context_data = self.view.get_context_data() - self.assertEqual(list(context_data.keys()), ["form", "view", "action"]) - self.assertEqual(context_data.get("action"), "update") - - # SingleObjectTemplateResponseMixin - def test_template_name(self): - self.view.setup(self.request) - template_names = self.view.get_template_names() - self.assertIn("people/person_form.html", template_names) - - # LoginRequiredMixin - def test_login_required(self): - self.request.user = AnonymousUser() - self.view.setup(self.request) - response = self.view.dispatch(self.request) - self.assertEqual(response.status_code, 302) - self.assertIn(reverse("account_login"), response.url) - - # PermissionRequiredMixin - def test_permission_required(self): - self.request.user = UserFactory() - self.view.setup(self.request) - permission_required = self.view.get_permission_required() - self.assertEqual(permission_required, ("people.change_person",)) - - -class InterpersonalRelationshipsListViewTestCase(TestCase): - @classmethod - def setUpClass(cls): - super().setUpClass() - - cls.authorized_user = cls.get_authorized_user() - - def setUp(self): - self.factory = RequestFactory() - self.request = self.build_get_request() - self.view_class = views.RelationshipsListView - self.view_func = self.view_class.as_view() - self.view = self.view_class() - - def build_get_request(self, data=None): - return self.factory.get("dummy_path", data=data) - - @staticmethod - def get_authorized_user(): - view_relationship = Permission.objects.filter( - name="Can view interpersonal relationship" - ) - return UserFactory(user_permissions=tuple(view_relationship)) - - @property - def table_head(self): - thead = """ - - - # - Person - Relative - Relationship type - - - """ - return thead - - # MultipleObjectMixin - def test_allow_empty(self): - self.view.setup(self.request) - allow_empty = self.view.get_allow_empty() - self.assertTrue(allow_empty) - - def test_ordering(self): - self.view.setup(self.request) - ordering = self.view.get_ordering() - self.assertIsNone(ordering) - - # SearchableListMixin - def test_search_fields(self): - self.view.setup(self.request) - search_fields = self.view.get_search_fields_with_filters() - expected_search_fields = [ - ("person__username", "icontains"), - ("relative__username", "icontains"), - ] - self.assertEqual(search_fields, expected_search_fields) - - def test_search_query(self): - search_term = "search query" - self.request = self.build_get_request({"q": search_term}) - self.view.setup(self.request) - search_query = self.view.get_search_query() - self.assertEqual(search_query, search_term) - - def test_queryset_without_search_query(self): - self.view.setup(self.request) - queryset = self.view.get_queryset() - self.assertQuerysetEqual(queryset, InterpersonalRelationship.objects.all()) - - def test_queryset_with_search_query(self): - relationships = InterpersonalRelationshipFactory.create_batch(10) - search_term = relationships[0].person.full_name.split()[0] - self.request = self.build_get_request({"q": search_term}) - self.view.setup(self.request) - queryset = self.view.get_queryset() - self.assertQuerysetEqual( - queryset, search_interpersonal_relationships(search_term) - ) - - # MultipleObjectMixin - def test_paginate_by(self): - self.view.setup(self.request) - queryset = self.view.get_queryset() - paginate_by = self.view.get_paginate_by(queryset) - self.assertEqual(paginate_by, 10) - - def test_context_object_name(self): - self.view.setup(self.request) - queryset = self.view.get_queryset() - context_object_name = self.view.get_context_object_name(queryset) - self.assertEqual(context_object_name, "relationships") - - def test_context_data(self): - self.view.setup(self.request) - queryset = self.view.get_queryset() - self.view.object_list = queryset - context_object_name = self.view.get_context_object_name(queryset) - context_data = self.view.get_context_data() - expected_context_data_keys = [ - "paginator", - "page_obj", - "is_paginated", - "object_list", - context_object_name, - "view", - ] - self.assertEqual(list(context_data.keys()), expected_context_data_keys) - - # MultipleObjectTemplateResponseMixin - def test_template_name(self): - self.view.setup(self.request) - self.view.object_list = self.view.get_queryset() - template_names = self.view.get_template_names() - self.assertIn("people/relationships_list.html", template_names) - - # LoginRequiredMixin - def test_login_required(self): - self.request.user = AnonymousUser() - self.view.setup(self.request) - response = self.view.dispatch(self.request) - self.assertEqual(response.status_code, 302) - self.assertIn(reverse("account_login"), response.url) - - # PermissionRequiredMixin - def test_permission_required(self): - self.request.user = UserFactory() - self.view.setup(self.request) - permission_required = self.view.get_permission_required() - self.assertEqual( - permission_required, ("people.view_interpersonalrelationship",) - ) - - # template logic - def test_response_with_no_relationships(self): - # setup - self.request.user = self.authorized_user - response = self.view_func(self.request) - response.render() - - # test - with self.assertRaises(AssertionError): - self.assertInHTML(self.table_head, response.content.decode()) - self.assertInHTML( - "There are no interpersonal relationships yet!", response.content.decode() - ) - - def test_response_with_relationships(self): - # setup - InterpersonalRelationshipFactory() - self.request.user = self.authorized_user - response = self.view_func(self.request) - response.render() - - # test - with self.assertRaises(AssertionError): - self.assertInHTML( - "There are no interpersonal relationships yet!", - response.content.decode(), - ) - self.assertInHTML(self.table_head, response.content.decode()) - - def test_response_with_no_search_results(self): - # setup - search_term = "does not exist" - self.request = self.build_get_request({"q": search_term}) - self.request.user = self.authorized_user - response = self.view_func(self.request) - response.render() - - # test - with self.assertRaises(AssertionError): - self.assertInHTML(self.table_head, response.content.decode()) - self.assertInHTML( - "Your search didn't yield any results", response.content.decode() - ) - - -class InterpersonalRelationshipCreateViewTestCase(TestCase): - @classmethod - def setUpClass(cls): - super().setUpClass() - - cls.user = UserFactory() - cls.person = PersonFactory() - cls.relative = PersonFactory() - cls.relationship = InterpersonalRelationshipFactory.build( - person=cls.person, relative=cls.relative - ) - cls.form_data = { - "person": cls.person.username, - "relative": cls.relative.username, - "relation": cls.relationship.relation, - } - - def setUp(self): - self.factory = RequestFactory() - self.request = self.factory.post("dummy_path", data=self.form_data) - self.view_class = views.RelationshipCreateView - self.view_func = self.view_class.as_view() - self.view = self.view_class() - - def get_data(self): - data = self.form_data.copy() - data["person"] = self.person - data["relative"] = self.relative - return data - - # FormMixin - def test_initial(self): - self.view.setup(self.request) - initial = self.view.get_initial() - self.assertEqual(initial, {}) - - def test_prefix(self): - self.view.setup(self.request) - prefix = self.view.get_prefix() - self.assertIsNone(prefix) - - def test_form_class(self): - self.view.setup(self.request) - form_class = self.view.get_form_class() - self.assertEqual( - form_class, - import_string("people.forms.InterpersonalRelationshipCreationForm"), - ) - - def test_form_kwargs(self): - self.view.setup(self.request) - form_kwargs = { - "initial": self.view.get_initial(), - "prefix": self.view.get_prefix(), - "data": self.request.POST, - "files": self.request.FILES, - } - self.assertEqual(self.view.get_form_kwargs(), form_kwargs) - - def test_success_url(self): - self.view.setup(self.request) - self.view.object = self.relationship - success_url = self.view.get_success_url() - self.assertEqual(success_url, reverse("people:relationships_list")) - - def test_form_invalid(self): - self.request.user = self.user - self.view.setup(self.request) - self.view.object = None - form = self.view.get_form() - response = self.view.form_invalid(form) - self.assertEqual(response.status_code, 200) - - # SuccessMessageMixin - def test_success_message(self): - self.request.user = self.user - self.view.setup(self.request) - self.view.object = self.relationship - data = self.get_data() - success_message = self.view.get_success_message(data) - people = f"{self.person} and {self.relative}" - self.assertEqual( - success_message, - f"The relationship between {people} has been added successfully.", - ) - - @patch("django.contrib.messages.success") - def test_form_valid_without_duplicate(self, mock_success): - self.request.user = self.user - self.view.setup(self.request) - form = self.view.get_form() - self.assertTrue(form.is_valid()) - response = self.view.form_valid(form) - self.assertTrue(mock_success.called) - self.assertEqual(response.status_code, 302) - relationship = InterpersonalRelationship.objects.get(person=self.person) - self.assertEqual(relationship.created_by, self.user) - - # ModelFormMixin - def test_form_valid_with_duplicate(self): - data = self.get_data() - InterpersonalRelationshipFactory(**data) - self.request.user = self.user - self.view.setup(self.request) - self.view.object = None - form = self.view.get_form() - self.assertFalse(form.is_valid()) - self.assertEqual( - form.errors, {"__all__": ["This interpersonal relationship already exists"]} - ) - - # SingleObjectMixin - def test_queryset(self): - self.view.setup(self.request) - with self.assertRaises(ImproperlyConfigured): - queryset = self.view.get_queryset() - self.assertEqual(list(queryset), []) - - def test_slug_field(self): - self.view.setup(self.request) - slug_field = self.view.get_slug_field() - self.assertEqual(slug_field, "slug") - - def test_object(self): - self.view.setup(self.request) - with self.assertRaises(ImproperlyConfigured): - obj = self.view.get_object() - self.assertIsNone(obj) - - def test_context_object_name(self): - self.view.setup(self.request) - with self.assertRaises(ImproperlyConfigured): - queryset = self.view.get_queryset() - context_object_name = self.view.get_context_object_name(queryset) - self.assertIsNone(context_object_name) - - def test_context_data(self): - self.view.setup(self.request) - self.view.object = None - context_data = self.view.get_context_data() - self.assertEqual(list(context_data.keys()), ["form", "view"]) - - # SingleObjectTemplateResponseMixin - def test_template_name(self): - self.view.setup(self.request) - template_names = self.view.get_template_names() - self.assertIn("people/relationship_form.html", template_names) - - # LoginRequiredMixin - def test_login_required(self): - self.request.user = AnonymousUser() - self.view.setup(self.request) - response = self.view.dispatch(self.request) - self.assertEqual(response.status_code, 302) - self.assertIn(reverse("account_login"), response.url) - - # PermissionRequiredMixin - def test_permission_required(self): - self.request.user = UserFactory() - self.view.setup(self.request) - permission_required = self.view.get_permission_required() - self.assertEqual(permission_required, ("people.add_interpersonalrelationship",)) - - -class ParentChildRelationshipCreateViewTestCase(TestCase): - @classmethod - def setUpClass(cls): - super().setUpClass() - - cls.user = UserFactory() - cls.person = AdultFactory(user=cls.user) - cls.parent = AdultFactory() - cls.child = ChildFactory() - cls.form_data = {"person": cls.parent.username} - cls.relationship_data = { - "person": cls.parent, - "relative": cls.child, - "relation": "PC", - } - cls.relationship = InterpersonalRelationshipFactory.build( - **cls.relationship_data - ) - - def setUp(self): - self.factory = RequestFactory() - self.request = self.factory.post("dummy_path", data=self.form_data) - self.view_class = views.ParentChildRelationshipCreateView - self.view_func = self.view_class.as_view() - self.view = self.view_class() - - # FormMixin - def test_initial(self): - self.view.setup(self.request) - initial = self.view.get_initial() - self.assertEqual(initial, {}) - - def test_prefix(self): - self.view.setup(self.request) - prefix = self.view.get_prefix() - self.assertIsNone(prefix) - - def test_form_class(self): - self.view.setup(self.request) - form_class = self.view.get_form_class() - self.assertEqual( - form_class, - import_string("people.forms.ParentChildRelationshipCreationForm"), - ) - - def test_form_kwargs(self): - self.view.setup(self.request) - form_kwargs = { - "initial": self.view.get_initial(), - "prefix": self.view.get_prefix(), - "data": self.request.POST, - "files": self.request.FILES, - } - self.assertEqual(self.view.get_form_kwargs(), form_kwargs) - - def test_success_url(self): - self.view.setup(self.request) - self.view.object = self.relationship - success_url = self.view.get_success_url() - self.assertEqual(success_url, reverse("core:dashboard")) - - def test_form_invalid(self): - self.request.user = self.user - self.view.setup(self.request, username=self.child.username) - self.view.object = None - form = self.view.get_form() - response = self.view.form_invalid(form) - self.assertEqual(response.status_code, 200) - - # SuccessMessageMixin - def test_success_message(self): - self.request.user = self.user - self.view.setup(self.request) - self.view.object = self.relationship - data = self.form_data.copy() - success_message = self.view.get_success_message(data) - people = f"{self.parent} and {self.child}" - self.assertEqual( - success_message, - f"A parent-child relationship between {people} has been added.", - ) - - @patch("django.contrib.messages.success") - def test_form_valid_without_duplicate(self, mock_success): - self.request.user = self.user - self.view.setup(self.request, username=self.child.username) - form = self.view.get_form() - self.assertTrue(form.is_valid()) - response = self.view.form_valid(form) - self.assertTrue(mock_success.called) - self.assertEqual(response.status_code, 302) - relationship = InterpersonalRelationship.objects.get(person=self.parent) - self.assertEqual(relationship.created_by, self.user) - self.assertEqual(relationship.relation, "PC") - - # ModelFormMixin - def test_form_valid_with_duplicate(self): - # setup - InterpersonalRelationshipFactory(**self.relationship_data) - self.request.user = self.user - self.view.setup(self.request, username=self.child.username) - self.view.object = None - form = self.view.get_form() - self.assertTrue(form.is_valid()) - response = self.view.form_valid(form) - - # test - self.assertEqual(response.status_code, 200) - response.render() - error_message = "This interpersonal relationship already exists" - self.assertInHTML(error_message, str(response.content)) - - # SingleObjectMixin - def test_queryset(self): - self.view.setup(self.request) - with self.assertRaises(ImproperlyConfigured): - queryset = self.view.get_queryset() - self.assertEqual(list(queryset), []) - - def test_slug_field(self): - self.view.setup(self.request) - slug_field = self.view.get_slug_field() - self.assertEqual(slug_field, "slug") - - def test_object(self): - self.view.setup(self.request) - with self.assertRaises(ImproperlyConfigured): - obj = self.view.get_object() - self.assertIsNone(obj) - - def test_child_with_existing_person(self): - self.view.setup(self.request, username=self.child.username) - obj = self.view.get_child() - self.assertEqual(obj, self.child) - - def test_child_with_non_existent_person(self): - self.view.setup(self.request, username="non-existent-person") - with self.assertRaises(Http404): - self.view.get_child() - - def test_context_object_name(self): - self.view.setup(self.request) - with self.assertRaises(ImproperlyConfigured): - queryset = self.view.get_queryset() - context_object_name = self.view.get_context_object_name(queryset) - self.assertIsNone(context_object_name) - - def test_context_data(self): - self.view.setup(self.request, username=self.child.username) - self.view.object = None - context_data = self.view.get_context_data() - self.assertEqual(list(context_data.keys()), ["form", "view", "child"]) - self.assertEqual(context_data.get("child"), self.child) - - # SingleObjectTemplateResponseMixin - def test_template_name(self): - self.view.setup(self.request) - template_names = self.view.get_template_names() - self.assertIn("people/relationship_form.html", template_names) - - # LoginRequiredMixin - def test_login_required(self): - self.request.user = AnonymousUser() - self.view.setup(self.request) - response = self.view.dispatch(self.request) - self.assertEqual(response.status_code, 302) - self.assertIn(reverse("account_login"), response.url) - - # PermissionRequiredMixin - def test_permission_required(self): - self.request.user = UserFactory() - self.view.setup(self.request) - permission_required = self.view.get_permission_required() - self.assertEqual(permission_required, ()) - - # UserPassesTestMixin - def test_test_func_false(self): - self.request.user = UserFactory() - self.view.setup(self.request) - self.assertFalse(self.view.test_func()) - - def test_test_func_true(self): - self.request.user = self.user - self.view.setup(self.request) - self.assertTrue(self.view.test_func()) diff --git a/records/tests/test_views.py b/records/tests/test_views.py index 54e9fbbd..217aa41d 100644 --- a/records/tests/test_views.py +++ b/records/tests/test_views.py @@ -1,10 +1,15 @@ -from django.contrib.auth.models import Permission -from django.test import TestCase +from unittest.mock import patch + +from django.contrib.auth.models import AnonymousUser, Permission +from django.core.exceptions import ImproperlyConfigured +from django.http.response import Http404 +from django.test import RequestFactory, TestCase from django.urls import reverse from django.utils.module_loading import import_string from accounts.factories import UserFactory from people.factories import PersonFactory +from records import views from records.factories import TemperatureRecordFactory from records.models import TemperatureRecord @@ -16,70 +21,137 @@ class TemperatureRecordsListViewTestCase(TestCase): def setUpClass(cls): super().setUpClass() - cls.url = "/records/temperature/" - cls.table_head = """ + cls.authorized_user = cls.get_authorized_user() + + def setUp(self): + self.factory = RequestFactory() + self.request = self.build_get_request() + self.view_class = views.TemperatureRecordsListView + self.view_func = self.view_class.as_view() + self.view = self.view_class() + + def build_get_request(self, data=None): + return self.factory.get("dummy_path", data=data) + + @staticmethod + def get_authorized_user(): + view_temp = Permission.objects.filter(name="Can view temperature record") + return UserFactory(user_permissions=tuple(view_temp)) + + @property + def table_head(self): + thead = """ - # - Username - Temperature - Time + # + Username + Temperature + Time """ - # users - view_temp = Permission.objects.filter(name="Can view temperature record") - cls.user = UserFactory() - cls.authorized_user = UserFactory(user_permissions=tuple(view_temp)) - cls.staff_user = UserFactory(is_staff=True) - - def test_anonymous_user_response(self): - response = self.client.get(self.url) - self.assertRedirects(response, f"/accounts/login/?next={self.url}") - - def test_authenticated_user_response(self): - self.client.force_login(self.user) - response = self.client.get(self.url) - self.assertEqual(response.status_code, 403) - - def test_authorized_user_response(self): - self.client.force_login(self.authorized_user) - response = self.client.get(self.url) - self.assertEqual(response.status_code, 200) - - def test_staff_user_response(self): - self.client.force_login(self.staff_user) - response = self.client.get(self.url) - self.assertEqual(response.status_code, 403) - - def test_template_used(self): - self.client.force_login(self.authorized_user) - response = self.client.get(self.url) - self.assertTemplateUsed(response, "records/temperature_records_list.html") - - def test_context_data_contains_temperature_records(self): - self.client.force_login(self.authorized_user) - response = self.client.get(self.url) - self.assertIn("temperature_records", response.context) - - def test_is_paginated(self): - TemperatureRecordFactory.create_batch(11) - self.client.force_login(self.authorized_user) - response = self.client.get(self.url) - self.assertTrue(response.context.get("is_paginated")) - self.assertEqual(len(response.context.get("temperature_records")), 10) - - def test_pagination_lists_all_items(self): - TemperatureRecordFactory.create_batch(12) - self.client.force_login(self.authorized_user) - response = self.client.get(self.url + "?page=2") - expected_records = list(TemperatureRecord.objects.all())[-2:] - temp_records = list(response.context.get("temperature_records")) - self.assertEqual(temp_records, expected_records) - + return thead + + # MultipleObjectMixin + def test_allow_empty(self): + self.view.setup(self.request) + allow_empty = self.view.get_allow_empty() + self.assertTrue(allow_empty) + + def test_ordering(self): + self.view.setup(self.request) + ordering = self.view.get_ordering() + self.assertIsNone(ordering) + + # SearchableListMixin + def test_search_fields(self): + self.view.setup(self.request) + search_fields = self.view.get_search_fields_with_filters() + expected_search_fields = [ + ("person__username", "icontains"), + ("person__full_name", "icontains"), + ] + self.assertEqual(search_fields, expected_search_fields) + + def test_search_query(self): + search_term = "search query" + self.request = self.build_get_request({"q": search_term}) + self.view.setup(self.request) + search_query = self.view.get_search_query() + self.assertEqual(search_query, search_term) + + def test_queryset_without_search_query(self): + self.view.setup(self.request) + queryset = self.view.get_queryset() + self.assertQuerysetEqual(queryset, TemperatureRecord.objects.all()) + + def test_queryset_with_search_query(self): + temp_records = TemperatureRecordFactory.create_batch(10) + search_term = temp_records[0].person.full_name.split()[0] + self.request = self.build_get_request({"q": search_term}) + self.view.setup(self.request) + queryset = self.view.get_queryset() + self.assertQuerysetEqual(queryset, search_temperature_records(search_term)) + + # MultipleObjectMixin + def test_paginate_by(self): + self.view.setup(self.request) + queryset = self.view.get_queryset() + paginate_by = self.view.get_paginate_by(queryset) + self.assertEqual(paginate_by, 10) + + def test_context_object_name(self): + self.view.setup(self.request) + queryset = self.view.get_queryset() + context_object_name = self.view.get_context_object_name(queryset) + self.assertEqual(context_object_name, "temperature_records") + + def test_context_data(self): + self.view.setup(self.request) + queryset = self.view.get_queryset() + self.view.object_list = queryset + context_object_name = self.view.get_context_object_name(queryset) + context_data = self.view.get_context_data() + expected_context_data_keys = [ + "paginator", + "page_obj", + "is_paginated", + "object_list", + context_object_name, + "view", + ] + self.assertEqual(list(context_data.keys()), expected_context_data_keys) + + # MultipleObjectTemplateResponseMixin + def test_template_name(self): + self.view.setup(self.request) + self.view.object_list = self.view.get_queryset() + template_names = self.view.get_template_names() + self.assertIn("records/temperature_records_list.html", template_names) + + # LoginRequiredMixin + def test_login_required(self): + self.request.user = AnonymousUser() + self.view.setup(self.request) + response = self.view.dispatch(self.request) + self.assertEqual(response.status_code, 302) + self.assertIn(reverse("account_login"), response.url) + + # PermissionRequiredMixin + def test_permission_required(self): + self.request.user = UserFactory() + self.view.setup(self.request) + permission_required = self.view.get_permission_required() + self.assertEqual(permission_required, ("records.view_temperaturerecord",)) + + # template logic def test_response_with_no_temperature_records(self): - self.client.force_login(self.authorized_user) - response = self.client.get(self.url) + # setup + self.request.user = self.authorized_user + response = self.view_func(self.request) + response.render() + + # test with self.assertRaises(AssertionError): self.assertInHTML(self.table_head, response.content.decode()) self.assertInHTML( @@ -87,33 +159,28 @@ def test_response_with_no_temperature_records(self): ) def test_response_with_temperature_records(self): - TemperatureRecordFactory.create_batch(3) - self.client.force_login(self.authorized_user) - response = self.client.get(self.url) + # setup + TemperatureRecordFactory() + self.request.user = self.authorized_user + response = self.view_func(self.request) + response.render() + + # test with self.assertRaises(AssertionError): self.assertInHTML( "There are no temperature records yet!", response.content.decode() ) self.assertInHTML(self.table_head, response.content.decode()) - def test_search_results(self): + def test_response_with_no_search_results(self): # setup - temp_records = TemperatureRecordFactory.create_batch(10) - search_term = temp_records[0].person.full_name.split()[0] - self.client.force_login(self.authorized_user) + search_term = "does not exist" + self.request = self.build_get_request({"q": search_term}) + self.request.user = self.authorized_user + response = self.view_func(self.request) + response.render() # test - response = self.client.get(f"{self.url}?q={search_term}") - search_results = response.context.get("temperature_records") - self.assertQuerysetEqual( - search_results, search_temperature_records(search_term) - ) - - def test_response_with_no_search_results(self): - TemperatureRecordFactory.create_batch(10) - self.client.force_login(self.authorized_user) - response = self.client.get(self.url + "?q=Does not exist") - self.assertEqual(list(response.context.get("temperature_records")), []) with self.assertRaises(AssertionError): self.assertInHTML(self.table_head, response.content.decode()) self.assertInHTML( @@ -126,91 +193,155 @@ class TemperatureRecordCreateViewTestCase(TestCase): def setUpClass(cls): super().setUpClass() - # users - create_temp = Permission.objects.filter(name="Can add temperature record") - view_person = Permission.objects.filter(name="Can view person") - permissions = create_temp | view_person + cls.person = PersonFactory() cls.user = UserFactory() - cls.authorized_user = UserFactory(user_permissions=tuple(permissions)) - cls.staff_user = UserFactory(is_staff=True) + cls.temp_record = TemperatureRecordFactory.build(person=cls.person) + cls.form_data = {"body_temperature": cls.temp_record.body_temperature} + + def setUp(self): + self.factory = RequestFactory() + self.request = self.factory.post("dummy_path", data=self.form_data) + self.view_class = views.TemperatureRecordCreateView + self.view_func = self.view_class.as_view() + self.view = self.view_class() + + # FormMixin + def test_initial(self): + self.view.setup(self.request) + initial = self.view.get_initial() + self.assertEqual(initial, {}) + + def test_prefix(self): + self.view.setup(self.request) + prefix = self.view.get_prefix() + self.assertIsNone(prefix) - # person - cls.person = PersonFactory() - cls.url = f"/records/temperature/{cls.person.username}/add/" + def test_form_class(self): + self.view.setup(self.request) + form_class = self.view.get_form_class() + self.assertEqual( + form_class, import_string("records.forms.TemperatureRecordCreationForm") + ) - # POST data - cls.data = { - "body_temperature": TemperatureRecordFactory.build().body_temperature + def test_form_kwargs(self): + self.view.setup(self.request) + form_kwargs = { + "initial": self.view.get_initial(), + "prefix": self.view.get_prefix(), + "data": self.request.POST, + "files": self.request.FILES, } + self.assertEqual(self.view.get_form_kwargs(), form_kwargs) - def test_anonymous_user_response(self): - response = self.client.get(self.url) - self.assertRedirects(response, f"/accounts/login/?next={self.url}") - - def test_authenticated_user_response(self): - self.client.force_login(self.user) - response = self.client.get(self.url) - self.assertEqual(response.status_code, 403) - - def test_authorized_user_response(self): - self.client.force_login(self.authorized_user) - response = self.client.get(self.url) - self.assertEqual(response.status_code, 200) - - def test_staff_user_response(self): - self.client.force_login(self.staff_user) - response = self.client.get(self.url) - self.assertEqual(response.status_code, 403) - - def test_response_with_nonexistent_person(self): - self.client.force_login(self.authorized_user) - url = self.url.replace(self.person.username, "nonexistent-username") - response = self.client.get(url) - self.assertEqual(response.status_code, 404) - - def test_context_data_contains_person(self): - self.client.force_login(self.authorized_user) - response = self.client.get(self.url) - self.assertEqual(response.context.get("person"), self.person) - - def test_template_used(self): - self.client.force_login(self.authorized_user) - response = self.client.get(self.url) - self.assertTemplateUsed(response, "records/temperature_record_form.html") - - def test_form_class(self): - self.client.force_login(self.authorized_user) - response = self.client.get(self.url) - form = response.context.get("form") - self.assertEqual(form.__class__.__name__, "TemperatureRecordCreationForm") - self.assertIsInstance(form, import_string("django.forms.ModelForm")) - self.assertIsInstance( - form, import_string("records.forms.TemperatureRecordCreationForm") - ) + def test_success_url(self): + self.view.setup(self.request) + self.view.object = self.temp_record + success_url = self.view.get_success_url() + self.assertEqual(success_url, reverse("people:people_list")) def test_form_invalid(self): - # setup - data = self.data.copy() - data["person"] = self.person - TemperatureRecordFactory(**data) - self.client.force_login(self.authorized_user) + self.request.user = self.user + self.view.setup(self.request, username=self.person.username) + self.view.object = None + form = self.view.get_form() + response = self.view.form_invalid(form) + self.assertEqual(response.status_code, 200) - # test - response = self.client.post(self.url, self.data) - form = response.context.get("form") - self.assertFalse(form.is_valid()) + # SuccessMessageMixin + def test_success_message(self): + self.request.user = self.user + self.view.setup(self.request, username=self.person.username) + self.view.object = self.temp_record + success_message = self.view.get_success_message(self.form_data) self.assertEqual( - form.errors, - {"__all__": [f"{self.person}'s temperature record already exists"]}, + success_message, + f"A temperature record for {self.person} has been added successfully.", ) - def test_form_valid(self): - self.client.force_login(self.authorized_user) - self.client.post(self.url, self.data) + @patch("django.contrib.messages.success") + def test_form_valid_without_duplicate(self, mock_success): + self.request.user = self.user + self.view.setup(self.request, username=self.person.username) + form = self.view.get_form() + self.assertTrue(form.is_valid()) + response = self.view.form_valid(form) + self.assertTrue(mock_success.called) + self.assertEqual(response.status_code, 302) temp_record = TemperatureRecord.objects.get(person=self.person) - self.assertEqual(temp_record.created_by, self.authorized_user) - - def test_success_url(self): - self.client.force_login(self.authorized_user) - response = self.client.post(self.url, self.data) - self.assertRedirects(response, reverse("people:people_list")) + self.assertEqual(temp_record.created_by, self.user) + + # ModelFormMixin + def test_form_valid_with_duplicate(self): + TemperatureRecordFactory(person=self.person, **self.form_data) + self.request.user = self.user + self.view.setup(self.request, username=self.person.username) + self.view.object = None + form = self.view.get_form() + response = self.view.form_valid(form) + self.assertEqual(response.status_code, 200) + response.render() + error_message = f"{self.person}'s temperature record already exists" + self.assertInHTML(error_message, str(response.content)) + + # SingleObjectMixin + def test_queryset(self): + self.view.setup(self.request) + with self.assertRaises(ImproperlyConfigured): + queryset = self.view.get_queryset() + self.assertEqual(list(queryset), []) + + def test_slug_field(self): + self.view.setup(self.request) + slug_field = self.view.get_slug_field() + self.assertEqual(slug_field, "slug") + + def test_object(self): + self.view.setup(self.request, username=self.person.username) + with self.assertRaises(ImproperlyConfigured): + obj = self.view.get_object() + self.assertIsNone(obj) + + def test_person_with_existing_person(self): + self.view.setup(self.request, username=self.person.username) + obj = self.view.get_person() + self.assertEqual(obj, self.person) + + def test_person_with_non_existent_person(self): + self.view.setup(self.request, username="non-existent-person") + with self.assertRaises(Http404): + self.view.get_person() + + def test_context_object_name(self): + self.view.setup(self.request) + with self.assertRaises(ImproperlyConfigured): + queryset = self.view.get_queryset() + context_object_name = self.view.get_context_object_name(queryset) + self.assertIsNone(context_object_name) + + def test_context_data(self): + self.view.setup(self.request, username=self.person.username) + self.view.object = None + context_data = self.view.get_context_data() + self.assertEqual(list(context_data.keys()), ["form", "view", "person"]) + self.assertEqual(context_data.get("person"), self.person) + + # SingleObjectTemplateResponseMixin + def test_template_name(self): + self.view.setup(self.request) + template_names = self.view.get_template_names() + self.assertIn("records/temperature_record_form.html", template_names) + + # LoginRequiredMixin + def test_login_required(self): + self.request.user = AnonymousUser() + self.view.setup(self.request) + response = self.view.dispatch(self.request) + self.assertEqual(response.status_code, 302) + self.assertIn(reverse("account_login"), response.url) + + # PermissionRequiredMixin + def test_permission_required(self): + self.request.user = UserFactory() + self.view.setup(self.request) + permission_required = self.view.get_permission_required() + self.assertEqual(permission_required, ("records.add_temperaturerecord",)) diff --git a/records/tests/test_views_.py b/records/tests/test_views_.py deleted file mode 100644 index 217aa41d..00000000 --- a/records/tests/test_views_.py +++ /dev/null @@ -1,347 +0,0 @@ -from unittest.mock import patch - -from django.contrib.auth.models import AnonymousUser, Permission -from django.core.exceptions import ImproperlyConfigured -from django.http.response import Http404 -from django.test import RequestFactory, TestCase -from django.urls import reverse -from django.utils.module_loading import import_string - -from accounts.factories import UserFactory -from people.factories import PersonFactory -from records import views -from records.factories import TemperatureRecordFactory -from records.models import TemperatureRecord - -from .helpers import search_temperature_records - - -class TemperatureRecordsListViewTestCase(TestCase): - @classmethod - def setUpClass(cls): - super().setUpClass() - - cls.authorized_user = cls.get_authorized_user() - - def setUp(self): - self.factory = RequestFactory() - self.request = self.build_get_request() - self.view_class = views.TemperatureRecordsListView - self.view_func = self.view_class.as_view() - self.view = self.view_class() - - def build_get_request(self, data=None): - return self.factory.get("dummy_path", data=data) - - @staticmethod - def get_authorized_user(): - view_temp = Permission.objects.filter(name="Can view temperature record") - return UserFactory(user_permissions=tuple(view_temp)) - - @property - def table_head(self): - thead = """ - - - # - Username - Temperature - Time - - - """ - return thead - - # MultipleObjectMixin - def test_allow_empty(self): - self.view.setup(self.request) - allow_empty = self.view.get_allow_empty() - self.assertTrue(allow_empty) - - def test_ordering(self): - self.view.setup(self.request) - ordering = self.view.get_ordering() - self.assertIsNone(ordering) - - # SearchableListMixin - def test_search_fields(self): - self.view.setup(self.request) - search_fields = self.view.get_search_fields_with_filters() - expected_search_fields = [ - ("person__username", "icontains"), - ("person__full_name", "icontains"), - ] - self.assertEqual(search_fields, expected_search_fields) - - def test_search_query(self): - search_term = "search query" - self.request = self.build_get_request({"q": search_term}) - self.view.setup(self.request) - search_query = self.view.get_search_query() - self.assertEqual(search_query, search_term) - - def test_queryset_without_search_query(self): - self.view.setup(self.request) - queryset = self.view.get_queryset() - self.assertQuerysetEqual(queryset, TemperatureRecord.objects.all()) - - def test_queryset_with_search_query(self): - temp_records = TemperatureRecordFactory.create_batch(10) - search_term = temp_records[0].person.full_name.split()[0] - self.request = self.build_get_request({"q": search_term}) - self.view.setup(self.request) - queryset = self.view.get_queryset() - self.assertQuerysetEqual(queryset, search_temperature_records(search_term)) - - # MultipleObjectMixin - def test_paginate_by(self): - self.view.setup(self.request) - queryset = self.view.get_queryset() - paginate_by = self.view.get_paginate_by(queryset) - self.assertEqual(paginate_by, 10) - - def test_context_object_name(self): - self.view.setup(self.request) - queryset = self.view.get_queryset() - context_object_name = self.view.get_context_object_name(queryset) - self.assertEqual(context_object_name, "temperature_records") - - def test_context_data(self): - self.view.setup(self.request) - queryset = self.view.get_queryset() - self.view.object_list = queryset - context_object_name = self.view.get_context_object_name(queryset) - context_data = self.view.get_context_data() - expected_context_data_keys = [ - "paginator", - "page_obj", - "is_paginated", - "object_list", - context_object_name, - "view", - ] - self.assertEqual(list(context_data.keys()), expected_context_data_keys) - - # MultipleObjectTemplateResponseMixin - def test_template_name(self): - self.view.setup(self.request) - self.view.object_list = self.view.get_queryset() - template_names = self.view.get_template_names() - self.assertIn("records/temperature_records_list.html", template_names) - - # LoginRequiredMixin - def test_login_required(self): - self.request.user = AnonymousUser() - self.view.setup(self.request) - response = self.view.dispatch(self.request) - self.assertEqual(response.status_code, 302) - self.assertIn(reverse("account_login"), response.url) - - # PermissionRequiredMixin - def test_permission_required(self): - self.request.user = UserFactory() - self.view.setup(self.request) - permission_required = self.view.get_permission_required() - self.assertEqual(permission_required, ("records.view_temperaturerecord",)) - - # template logic - def test_response_with_no_temperature_records(self): - # setup - self.request.user = self.authorized_user - response = self.view_func(self.request) - response.render() - - # test - with self.assertRaises(AssertionError): - self.assertInHTML(self.table_head, response.content.decode()) - self.assertInHTML( - "There are no temperature records yet!", response.content.decode() - ) - - def test_response_with_temperature_records(self): - # setup - TemperatureRecordFactory() - self.request.user = self.authorized_user - response = self.view_func(self.request) - response.render() - - # test - with self.assertRaises(AssertionError): - self.assertInHTML( - "There are no temperature records yet!", response.content.decode() - ) - self.assertInHTML(self.table_head, response.content.decode()) - - def test_response_with_no_search_results(self): - # setup - search_term = "does not exist" - self.request = self.build_get_request({"q": search_term}) - self.request.user = self.authorized_user - response = self.view_func(self.request) - response.render() - - # test - with self.assertRaises(AssertionError): - self.assertInHTML(self.table_head, response.content.decode()) - self.assertInHTML( - "Your search didn't yield any results", response.content.decode() - ) - - -class TemperatureRecordCreateViewTestCase(TestCase): - @classmethod - def setUpClass(cls): - super().setUpClass() - - cls.person = PersonFactory() - cls.user = UserFactory() - cls.temp_record = TemperatureRecordFactory.build(person=cls.person) - cls.form_data = {"body_temperature": cls.temp_record.body_temperature} - - def setUp(self): - self.factory = RequestFactory() - self.request = self.factory.post("dummy_path", data=self.form_data) - self.view_class = views.TemperatureRecordCreateView - self.view_func = self.view_class.as_view() - self.view = self.view_class() - - # FormMixin - def test_initial(self): - self.view.setup(self.request) - initial = self.view.get_initial() - self.assertEqual(initial, {}) - - def test_prefix(self): - self.view.setup(self.request) - prefix = self.view.get_prefix() - self.assertIsNone(prefix) - - def test_form_class(self): - self.view.setup(self.request) - form_class = self.view.get_form_class() - self.assertEqual( - form_class, import_string("records.forms.TemperatureRecordCreationForm") - ) - - def test_form_kwargs(self): - self.view.setup(self.request) - form_kwargs = { - "initial": self.view.get_initial(), - "prefix": self.view.get_prefix(), - "data": self.request.POST, - "files": self.request.FILES, - } - self.assertEqual(self.view.get_form_kwargs(), form_kwargs) - - def test_success_url(self): - self.view.setup(self.request) - self.view.object = self.temp_record - success_url = self.view.get_success_url() - self.assertEqual(success_url, reverse("people:people_list")) - - def test_form_invalid(self): - self.request.user = self.user - self.view.setup(self.request, username=self.person.username) - self.view.object = None - form = self.view.get_form() - response = self.view.form_invalid(form) - self.assertEqual(response.status_code, 200) - - # SuccessMessageMixin - def test_success_message(self): - self.request.user = self.user - self.view.setup(self.request, username=self.person.username) - self.view.object = self.temp_record - success_message = self.view.get_success_message(self.form_data) - self.assertEqual( - success_message, - f"A temperature record for {self.person} has been added successfully.", - ) - - @patch("django.contrib.messages.success") - def test_form_valid_without_duplicate(self, mock_success): - self.request.user = self.user - self.view.setup(self.request, username=self.person.username) - form = self.view.get_form() - self.assertTrue(form.is_valid()) - response = self.view.form_valid(form) - self.assertTrue(mock_success.called) - self.assertEqual(response.status_code, 302) - temp_record = TemperatureRecord.objects.get(person=self.person) - self.assertEqual(temp_record.created_by, self.user) - - # ModelFormMixin - def test_form_valid_with_duplicate(self): - TemperatureRecordFactory(person=self.person, **self.form_data) - self.request.user = self.user - self.view.setup(self.request, username=self.person.username) - self.view.object = None - form = self.view.get_form() - response = self.view.form_valid(form) - self.assertEqual(response.status_code, 200) - response.render() - error_message = f"{self.person}'s temperature record already exists" - self.assertInHTML(error_message, str(response.content)) - - # SingleObjectMixin - def test_queryset(self): - self.view.setup(self.request) - with self.assertRaises(ImproperlyConfigured): - queryset = self.view.get_queryset() - self.assertEqual(list(queryset), []) - - def test_slug_field(self): - self.view.setup(self.request) - slug_field = self.view.get_slug_field() - self.assertEqual(slug_field, "slug") - - def test_object(self): - self.view.setup(self.request, username=self.person.username) - with self.assertRaises(ImproperlyConfigured): - obj = self.view.get_object() - self.assertIsNone(obj) - - def test_person_with_existing_person(self): - self.view.setup(self.request, username=self.person.username) - obj = self.view.get_person() - self.assertEqual(obj, self.person) - - def test_person_with_non_existent_person(self): - self.view.setup(self.request, username="non-existent-person") - with self.assertRaises(Http404): - self.view.get_person() - - def test_context_object_name(self): - self.view.setup(self.request) - with self.assertRaises(ImproperlyConfigured): - queryset = self.view.get_queryset() - context_object_name = self.view.get_context_object_name(queryset) - self.assertIsNone(context_object_name) - - def test_context_data(self): - self.view.setup(self.request, username=self.person.username) - self.view.object = None - context_data = self.view.get_context_data() - self.assertEqual(list(context_data.keys()), ["form", "view", "person"]) - self.assertEqual(context_data.get("person"), self.person) - - # SingleObjectTemplateResponseMixin - def test_template_name(self): - self.view.setup(self.request) - template_names = self.view.get_template_names() - self.assertIn("records/temperature_record_form.html", template_names) - - # LoginRequiredMixin - def test_login_required(self): - self.request.user = AnonymousUser() - self.view.setup(self.request) - response = self.view.dispatch(self.request) - self.assertEqual(response.status_code, 302) - self.assertIn(reverse("account_login"), response.url) - - # PermissionRequiredMixin - def test_permission_required(self): - self.request.user = UserFactory() - self.view.setup(self.request) - permission_required = self.view.get_permission_required() - self.assertEqual(permission_required, ("records.add_temperaturerecord",)) From 2602f36d79a2ed49abfe2b2a743eac8fbe6d387e Mon Sep 17 00:00:00 2001 From: Harison Gachuru Date: Fri, 4 Feb 2022 15:27:51 +0300 Subject: [PATCH 29/29] Update README --- README.md | 1 + 1 file changed, 1 insertion(+) diff --git a/README.md b/README.md index 0aef241e..f78febca 100644 --- a/README.md +++ b/README.md @@ -7,3 +7,4 @@ to store and retrieve church records online. [![Code style: black](https://img.shields.io/badge/code%20style-black-000000.svg)](https://github.com/psf/black) [![Imports: isort](https://img.shields.io/badge/%20imports-isort-%231674b1?style=flat&labelColor=ef8336)](https://pycqa.github.io/isort/) [![Documentation Status](https://readthedocs.org/projects/church-ims/badge/?version=latest)](https://church-ims.readthedocs.io/en/latest/?badge=latest) +[![Maintainability](https://api.codeclimate.com/v1/badges/669adf02ec70d3484662/maintainability)](https://codeclimate.com/github/harisonmg/church-ims/maintainability)