diff --git a/apps/contests/tests.py b/apps/contests/tests.py new file mode 100644 index 0000000..d0eba8a --- /dev/null +++ b/apps/contests/tests.py @@ -0,0 +1,136 @@ +from datetime import timedelta + +from django.contrib.admin import AdminSite +from django.forms import CharField, Textarea +from django.test import TestCase +from django.urls import resolve, reverse +from django.utils import timezone + +from apps.contests.admin import ContestAdmin, ContestModelForm +from apps.contests.enums import ContestStatus +from apps.contests.models import Contest + + +class ContestTestCase(TestCase): + def setUp(self) -> None: + self.contest = Contest( + title="Test Contest", + description="This is a test contest", + cancelled=False, + ) + + def test_status_pending(self) -> None: + self.contest.start_time = timezone.now() + timedelta(hours=1) + self.contest.end_time = timezone.now() + timedelta(hours=2) + self.assertEqual(self.contest.status, ContestStatus.PENDING) + + def test_status_running(self) -> None: + self.contest.start_time = timezone.now() - timedelta(hours=1) + self.contest.end_time = timezone.now() + timedelta(hours=1) + self.assertEqual(self.contest.status, ContestStatus.RUNNING) + + def test_status_finished(self) -> None: + self.contest.start_time = timezone.now() - timedelta(hours=2) + self.contest.end_time = timezone.now() - timedelta(hours=1) + self.assertEqual(self.contest.status, ContestStatus.FINISHED) + + def test_status_cancelled(self) -> None: + self.contest.cancelled = True + self.assertEqual(self.contest.status, ContestStatus.CANCELLED) + + +class ContestStatusTestCase(TestCase): + def test_pending(self) -> None: + self.assertEqual(ContestStatus.PENDING, "Pending") + + def test_running(self) -> None: + self.assertEqual(ContestStatus.RUNNING, "Running") + + def test_finished(self) -> None: + self.assertEqual(ContestStatus.FINISHED, "Finished") + + def test_cancelled(self) -> None: + self.assertEqual(ContestStatus.CANCELLED, "Cancelled") + + +class ContestModelFormTestCase(TestCase): + def test_description_field_widget(self) -> None: + form = ContestModelForm() + + description_field = form.fields["description"] + attrs = {"rows": 14, "cols": 80} + + self.assertIsInstance(description_field, CharField) + self.assertIsInstance(description_field.widget, Textarea) + self.assertEqual(description_field.widget.attrs, attrs) + + def test_form_model_to_be_contest(self) -> None: + self.assertEqual(ContestModelForm()._meta.model, Contest) + + +class ContestAdminTestCase(TestCase): + def setUp(self) -> None: + self.site = AdminSite() + self.admin = ContestAdmin(Contest, self.site) + + def test_list_display(self) -> None: + list_display = self.admin.list_display + expected = ("title", "start_time", "end_time", "status") + + self.assertEqual(list_display, expected) + + def test_list_filter(self) -> None: + list_filter = self.admin.list_filter + expected = ("start_time", "end_time") + + self.assertEqual(list_filter, expected) + + def test_fieldsets(self) -> None: + fieldsets = self.admin.fieldsets + expected = [ + (("General"), {"fields": ("title", "description")}), + (("Other"), {"fields": ("start_time", "end_time", "cancelled")}), + ] + + self.assertEqual(fieldsets, expected) + + +class ContestURLTestCase(TestCase): + def test_detail_url_to_view_name(self) -> None: + url = reverse("contests:detail", args=[1]) + + view_name = resolve(url).view_name + expected = "contests:detail" + + self.assertEqual(view_name, expected) + + def test_detail_url_reverse(self) -> None: + url = reverse("contests:detail", args=[1]) + expected = "/contests/1/" + + self.assertEqual(url, expected) + + +class ContestViewTestCase(TestCase): + def setUp(self) -> None: + now = timezone.now() + self.contest = Contest._default_manager.create( + title="Test Contest", + description="This is a test contest", + start_time=now, + end_time=now + timedelta(hours=1), + cancelled=False, + ) + + def test_index_view(self) -> None: + response = self.client.get(reverse("home")) + + self.assertEqual(response.status_code, 200) + self.assertContains(response, "Test Contest") + + def test_detail_view(self) -> None: + url = reverse("contests:detail", args=[self.contest.id]) + response = self.client.get(url) + + self.assertEqual(response.status_code, 200) + self.assertContains(response, "Test Contest") diff --git a/apps/problems/tests.py b/apps/problems/tests.py new file mode 100644 index 0000000..8ab9c8e --- /dev/null +++ b/apps/problems/tests.py @@ -0,0 +1,129 @@ +from datetime import timedelta + +from django.contrib.admin.sites import AdminSite + +# from django.forms import CharField, IntegerField +from django.test import TestCase +from django.urls import resolve, reverse +from django.utils import timezone + +from apps.contests.models import Contest +from apps.problems.admin import ProblemAdmin +from apps.problems.models import Problem +from apps.problems.views import DetailView + + +class ProblemTestCase(TestCase): + def test_problem_to_string(self) -> None: + problem = Problem(title="Test Problem") + self.assertEqual(str(problem), "Test Problem") + + def test_running_contest_is_accessible(self) -> None: + now = timezone.now() + + start_time = now - timedelta(hours=1) + end_time = now + timedelta(hours=1) + + contest = Contest(start_time=start_time, end_time=end_time) + problem = Problem(contest=contest) + + self.assertTrue(problem.is_accessible) + + def test_past_contest_is_accessible(self) -> None: + now = timezone.now() + + start_time = now - timedelta(hours=2) + end_time = now - timedelta(hours=1) + + contest = Contest(start_time=start_time, end_time=end_time) + problem = Problem(contest=contest) + + self.assertTrue(problem.is_accessible) + + def test_future_contest_is_not_accessible(self) -> None: + now = timezone.now() + + start_time = now + timedelta(hours=1) + end_time = now + timedelta(hours=2) + + contest = Contest(start_time=start_time, end_time=end_time) + problem = Problem(contest=contest) + + self.assertFalse(problem.is_accessible) + + def test_cancelled_contest_is_not_accessible(self) -> None: + now = timezone.now() + + start_time = now - timedelta(hours=1) + end_time = now + timedelta(hours=1) + + contest = Contest( + start_time=start_time, + end_time=end_time, + cancelled=True, + ) + problem = Problem(contest=contest) + + self.assertFalse(problem.is_accessible) + + +class ProblemAdminTestCase(TestCase): + def setUp(self) -> None: + now = timezone.now() + self.site = AdminSite() + self.admin = ProblemAdmin(Problem, self.site) + + self.contest = Contest._default_manager.create( + title="Test Contest 1", + description="This is a test contest", + start_time=now, + end_time=now + timedelta(hours=1), + cancelled=False, + ) + self.contest.save() + + def test_list_display(self) -> None: + list_display = self.admin.list_display + expected = ("title", "contest", "memory_limit", "time_limit") + + self.assertEqual(list_display, expected) + + def test_list_filter(self) -> None: + list_filter = self.admin.list_filter + expected = ("contest", "score") + + self.assertEqual(list_filter, expected) + + def test_fieldsets(self) -> None: + fieldsets = self.admin.fieldsets + expected = [ + (("General"), {"fields": ("title", "description")}), + (("Meta"), {"fields": ("contest", "score")}), + (("Limits"), {"fields": ("memory_limit", "time_limit")}), + ] + + self.assertEqual(fieldsets, expected) + + +class ProblemURLTestCase(TestCase): + def test_detail_url_to_view_name(self) -> None: + url = reverse("problems:detail", args=[1]) + + view_name = resolve(url).view_name + expected = "problems:detail" + + self.assertEqual(view_name, expected) + + def test_detail_url_reverse(self) -> None: + url = reverse("problems:detail", args=[1]) + expected = "/problems/1/" + + self.assertEqual(url, expected) + + +class DetailViewTestCase(TestCase): + def test_detail_view_model_is_problem(self) -> None: + self.assertEqual(DetailView.model, Problem) + + def test_detail_view_template_name_is_correct(self) -> None: + self.assertEqual(DetailView.template_name, "problems/detail.html") diff --git a/apps/users/tests.py b/apps/users/tests.py new file mode 100644 index 0000000..b509386 --- /dev/null +++ b/apps/users/tests.py @@ -0,0 +1,88 @@ +from django.test import TestCase +from django.utils.translation import gettext as _ + +from apps.users.admin import UserAdmin +from apps.users.models import User + + +class UserModelTestCase(TestCase): + def test_username_field_is_email(self) -> None: + self.assertEqual(User().USERNAME_FIELD, "email") + + def test_required_fields_include_username(self) -> None: + self.assertIn("username", User().REQUIRED_FIELDS) + + +class UserManagerTestCase(TestCase): + def test_create_user(self) -> None: + user = User.objects.create_user( + username="testuser", + email="test@example.com", + password="testpassword", + ) + + self.assertEqual(user.email, "test@example.com") + self.assertEqual(user.username, "testuser") + self.assertFalse(user.is_staff) + self.assertTrue(user.is_active) + + def test_create_superuser(self) -> None: + superuser = User.objects.create_superuser( + username="adminuser", + email="admin@example.com", + password="adminpassword", + ) + + self.assertEqual(superuser.email, "admin@example.com") + self.assertEqual(superuser.username, "adminuser") + self.assertTrue(superuser.is_staff) + self.assertTrue(superuser.is_superuser) + + +class UserAdminTestCase(TestCase): + def test_list_display(self) -> None: + list_display = UserAdmin.list_display + expected = ("username", "email", "is_staff", "is_active") + + self.assertEqual(list_display, expected) + + def test_list_filter(self) -> None: + list_filter = UserAdmin.list_filter + expected = ("is_staff", "is_superuser", "is_active", "groups") + + self.assertEqual(list_filter, expected) + + def test_fieldsets(self) -> None: + expected = [ + ( + _("Personal info"), + {"fields": ("username", "email", "password")}, + ), + ( + _("Permissions"), + { + "fields": ( + "user_permissions", + "groups", + "is_active", + "is_staff", + "is_superuser", + ) + }, + ), + ] + + self.assertEqual(UserAdmin.fieldsets, expected) + + def test_add_fieldsets(self) -> None: + expected_add_fieldsets = ( + ( + None, + { + "classes": ("wide",), + "fields": ("username", "email", "password1", "password2"), + }, + ), + ) + + self.assertEqual(UserAdmin.add_fieldsets, expected_add_fieldsets)