Skip to content

Commit

Permalink
update unit tests and quality
Browse files Browse the repository at this point in the history
  • Loading branch information
Ali-D-Akbar committed Jan 24, 2025
1 parent 30f3ec1 commit 7d8b058
Show file tree
Hide file tree
Showing 6 changed files with 185 additions and 119 deletions.
2 changes: 1 addition & 1 deletion course_discovery/apps/tagging/mixins.py
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
from django.http import HttpResponseForbidden
from django.conf import settings
from django.http import HttpResponseForbidden


class VerticalTaggingAdministratorPermissionRequiredMixin:
Expand Down
5 changes: 1 addition & 4 deletions course_discovery/apps/tagging/templates/tagging/base.html
Original file line number Diff line number Diff line change
Expand Up @@ -12,12 +12,9 @@
<body>
<nav class="navbar navbar-expand-lg navbar-dark bg-dark">
<div class="container">
<a class="navbar-brand" href="{% url 'tagging:course_list' %}">Tagging App</a>
<a class="navbar-brand" href="{% url 'tagging:course_list' %}">Course Tagging</a>
<div class="collapse navbar-collapse" id="navbarNav">
<ul class="navbar-nav me-auto">
<li class="nav-item">
<a class="nav-link" href="{% url 'tagging:course_list' %}">Courses</a>
</li>
<li class="nav-item">
<a class="nav-link" href="{% url 'tagging:vertical_list' %}">Verticals</a>
</li>
Expand Down
66 changes: 66 additions & 0 deletions course_discovery/apps/tagging/tests/test_mixins.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,66 @@
from django.conf import settings
from django.contrib.auth.models import AnonymousUser, Group, User
from django.http.response import HttpResponse
from django.test import RequestFactory, TestCase
from django.views import View

from course_discovery.apps.core.tests.factories import UserFactory
from course_discovery.apps.tagging.mixins import VerticalTaggingAdministratorPermissionRequiredMixin


class MockView(VerticalTaggingAdministratorPermissionRequiredMixin, View):
"""A mock view to test the mixin."""

def get(self, request, *args, **kwargs):
return HttpResponse("Success!")


class VerticalTaggingAdministratorPermissionRequiredMixinTests(TestCase):
"""Tests for VerticalTaggingAdministratorPermissionRequiredMixin."""

def setUp(self):
self.factory = RequestFactory()
self.view = MockView.as_view()

self.superuser = UserFactory(is_staff=True, is_superuser=True)
self.vertical_admin = UserFactory(is_staff=True, is_superuser=False)
self.regular_user = UserFactory(is_staff=False, is_superuser=False)

self.allowed_group = Group.objects.create(name=settings.VERTICALS_MANAGEMENT_GROUPS[0])
self.vertical_admin.groups.add(self.allowed_group)

def test_user_not_authenticated(self):
"""Test that unauthenticated users are forbidden."""
request = self.factory.get("/")
request.user = AnonymousUser()

response = self.view(request)
self.assertEqual(response.status_code, 403)
self.assertEqual(response.content.decode(), "You need to be logged in to access this page.")

def test_regular_user(self):
"""Test that users not in the allowed group or superuser are forbidden."""
request = self.factory.get("/")
request.user = self.regular_user

response = self.view(request)
self.assertEqual(response.status_code, 403)
self.assertEqual(response.content.decode(), "You do not have permission to access this page.")

def test_user_in_allowed_group(self):
"""Test that users in the allowed group can access the view."""
request = self.factory.get("/")
request.user = self.vertical_admin

response = self.view(request)
self.assertEqual(response.status_code, 200)
self.assertEqual(response.content.decode(), "Success!")

def test_superuser_access(self):
"""Test that superusers can access the view."""
request = self.factory.get("/")
request.user = self.superuser

response = self.view(request)
self.assertEqual(response.status_code, 200)
self.assertEqual(response.content.decode(), "Success!")
221 changes: 114 additions & 107 deletions course_discovery/apps/tagging/tests/test_views.py
Original file line number Diff line number Diff line change
@@ -1,41 +1,53 @@
from django.http import JsonResponse
from ddt import data, ddt
from django.conf import settings
from django.contrib.auth.models import Group
from django.test import TestCase
from django.urls import reverse

from course_discovery.apps.core.tests.factories import UserFactory
from course_discovery.apps.course_metadata.tests.factories import CourseFactory
from course_discovery.apps.tagging.models import CourseVertical, SubVertical, Vertical
from course_discovery.apps.tagging.tests.factories import CourseVerticalFactory, SubVerticalFactory, VerticalFactory


class CourseDetailViewTests(TestCase):
"""Tests for the course detail view."""
class BaseViewsTestCase(TestCase):
"""Base test class for views requiring superuser and VERTICALS_MANAGEMENT_GROUPS permissions."""

def setUp(self):
"""Sets up test data for course detail view tests."""
self.course_draft = CourseFactory(draft=True)
self.course = CourseFactory(draft=False, draft_version_id=self.course_draft.id)
self.vertical = VerticalFactory(name='AI')
self.sub_vertical = SubVerticalFactory(name='Machine Learning', vertical=self.vertical)
self.url = reverse('tagging:course_detail', kwargs={'uuid': self.course.uuid})

def test_get_course_detail(self):
"""Tests GET request to the course detail view."""
super().setUp()
self.superuser = UserFactory(is_staff=True, is_superuser=True)
self.regular_user = UserFactory(is_staff=True, is_superuser=False)

self.allowed_group = Group.objects.create(name=settings.VERTICALS_MANAGEMENT_GROUPS)
self.regular_user.groups.add(self.allowed_group)


class CourseTaggingDetailViewTests(BaseViewsTestCase):
"""Tests for the CourseTaggingDetailView."""

def setUp(self):
super().setUp()
self.client.force_login(self.superuser)
self.course = CourseFactory(title="Advanced Python")
self.vertical = VerticalFactory(name="AI")
self.sub_vertical = SubVerticalFactory(name="Machine Learning", vertical=self.vertical)
self.url = reverse("tagging:course_tagging_detail", kwargs={"uuid": self.course.uuid})

def test_get_course_tagging_detail(self):
"""Tests GET request to course tagging detail view."""
response = self.client.get(self.url)
self.assertEqual(response.status_code, 200)
self.assertTemplateUsed(response, 'tagging/course_detail.html')
self.assertIn('course', response.context)
self.assertIn('verticals', response.context)
self.assertIn('sub_vertical', response.context)
self.assertTemplateUsed(response, "tagging/course_tagging_detail.html")

def test_post_valid_vertical_assignment(self):
"""Tests POST request with valid vertical and sub-vertical assignment."""
"""Tests POST request to assign vertical and sub-vertical."""
data = {
'vertical': self.vertical.slug,
'sub_vertical': self.sub_vertical.slug,
"vertical": self.vertical.slug,
"sub_vertical": self.sub_vertical.slug,
}
response = self.client.post(self.url, data=data)
self.assertEqual(response.status_code, 200)
self.assertContains(response, 'Vertical and Sub-Vertical assigned successfully.')
self.assertContains(response, "Vertical and Sub-Vertical assigned successfully.")

course_vertical = CourseVertical.objects.get(course=self.course)
self.assertEqual(course_vertical.vertical, self.vertical)
Expand All @@ -55,40 +67,22 @@ def test_post_invalid_sub_vertical(self):
self.assertContains(response, 'Sub-vertical does not belong to the selected vertical.')


class LoadSubVerticalsViewTests(TestCase):
"""Tests for loading sub-verticals based on selected vertical."""

def setUp(self):
"""Sets up test data for sub-vertical loading."""
self.vertical = VerticalFactory(name='Business')
self.sub_vertical = SubVerticalFactory(name='Innovation', vertical=self.vertical)
self.url = reverse('tagging:load_sub_verticals')

def test_load_sub_verticals(self):
"""Tests GET request to load sub-verticals for a selected vertical."""
response = self.client.get(self.url, {'vertical': self.vertical.slug})
self.assertEqual(response.status_code, 200)
self.assertIsInstance(response, JsonResponse)
self.assertIn('html', response.json())


class CourseListViewTests(TestCase):
"""Tests for the course list view."""
@ddt
class CourseListViewTests(BaseViewsTestCase):
"""Tests for the CourseListView."""

def setUp(self):
"""Sets up test data for course list view tests."""
self.course1 = CourseFactory(title='Advanced Python')
self.course2 = CourseFactory(title='Python Basics')
self.url = reverse('tagging:course_list')
super().setUp()
self.client.force_login(self.superuser)
self.course1 = CourseFactory(title="Advanced Python")
self.course2 = CourseFactory(title="Python Basics")
self.url = reverse("tagging:course_list")

def test_get_course_list(self):
"""Tests GET request to the course list view."""
"""Tests GET request to course list view."""
response = self.client.get(self.url)
self.assertEqual(response.status_code, 200)
self.assertTemplateUsed(response, 'tagging/course_list.html')
self.assertIn('courses', response.context)
self.assertIn('Python Basics', response.context)
self.assertIn('Advanced Python', response.context)
self.assertTemplateUsed(response, "tagging/course_list.html")

def test_search_course(self):
"""Tests searching for courses in the course list view."""
Expand All @@ -97,98 +91,111 @@ def test_search_course(self):
self.assertContains(response, 'Python Basics')
self.assertNotContains(response, 'Advanced Python')

def test_sort_courses(self):
"""Tests sorting courses by title in descending order."""
response = self.client.get(self.url, {'sort': 'title', 'direction': 'desc'})
@data(('asc', ["Advanced Python", "Python Basics"]), ('desc', ["Python Basics", "Advanced Python"]))
def test_sort_courses(self, direction_and_order):
"""Tests sorting courses by title in ascending and descending order."""
direction, expected_order = direction_and_order
response = self.client.get(self.url, {'sort': 'title', 'direction': direction})
self.assertEqual(response.status_code, 200)
courses = response.context['courses'].object_list
self.assertEqual(list(courses), [self.course2, self.course1])
self.assertEqual([course.title for course in courses], expected_order)


class VerticalListViewTests(TestCase):
"""Tests for the vertical list view."""
@ddt
class VerticalListViewTests(BaseViewsTestCase):
"""Tests for the VerticalListView."""

def setUp(self):
"""Sets up test data for vertical list view tests."""
self.vertical1 = VerticalFactory(name='AI')
self.vertical2 = VerticalFactory(name='Business')
self.url = reverse('tagging:vertical_list')
super().setUp()
self.client.force_login(self.superuser)
self.vertical1 = VerticalFactory(name="AI")
self.vertical2 = VerticalFactory(name="Business")
self.url = reverse("tagging:vertical_list")

def test_get_vertical_list(self):
"""Tests GET request to the vertical list view."""
"""Tests GET request to vertical list view."""
response = self.client.get(self.url)
self.assertEqual(response.status_code, 200)
self.assertTemplateUsed(response, 'tagging/vertical_list.html')
self.assertIn('verticals', response.context)
self.assertTemplateUsed(response, "tagging/vertical_list.html")

def test_sort_verticals(self):
@data(('asc', ["AI", "Business"]), ('desc', ["Business", "AI"]))
def test_sort_verticals(self, direction_and_order):
"""Tests sorting verticals by name in descending order."""
response = self.client.get(self.url, {'sort': 'name', 'direction': 'desc'})
direction, expected_order = direction_and_order
response = self.client.get(self.url, {'sort': 'name', 'direction': direction})
self.assertEqual(response.status_code, 200)
verticals = response.context['verticals']
self.assertEqual(list(verticals), [self.vertical2, self.vertical1])
self.assertEqual([vertical.name for vertical in verticals], expected_order)


class SubVerticalListViewTests(TestCase):
"""Tests for the sub-vertical list view."""
class VerticalDetailViewTests(BaseViewsTestCase):
"""Tests for the VerticalDetailView."""

def setUp(self):
"""Sets up test data for sub-vertical list view tests."""
self.vertical = VerticalFactory(name='Technology')
self.sub_vertical1 = SubVerticalFactory(name='AI', vertical=self.vertical)
self.sub_vertical2 = SubVerticalFactory(name='IoT', vertical=self.vertical)
self.url = reverse('tagging:sub_vertical_list')
super().setUp()
self.client.force_login(self.superuser)
self.vertical = VerticalFactory(name="AI")
self.sub_vertical = SubVerticalFactory(name="Python", vertical=self.vertical)
self.course = CourseFactory(title="Machine Learning")
_ = CourseVerticalFactory(course=self.course, vertical=self.vertical, sub_vertical=self.sub_vertical)
self.url = reverse("tagging:vertical_detail", kwargs={"slug": self.vertical.slug})

def test_get_sub_vertical_list(self):
"""Tests GET request to the sub-vertical list view."""
def test_get_vertical_detail(self):
"""Tests GET request to vertical detail view."""
response = self.client.get(self.url)
self.assertEqual(response.status_code, 200)
self.assertTemplateUsed(response, 'tagging/sub_vertical_list.html')
self.assertIn('sub_verticals', response.context)
self.assertTemplateUsed(response, "tagging/vertical_detail.html")
self.assertContains(response, self.vertical.name)
self.assertContains(response, self.sub_vertical.name)
self.assertContains(response, self.course.title)

def test_sort_sub_verticals(self):
"""Tests sorting sub-verticals by name in descending order."""
response = self.client.get(self.url, {'sort': 'name', 'direction': 'desc'})
self.assertEqual(response.status_code, 200)
sub_verticals = response.context['sub_verticals']
self.assertEqual(list(sub_verticals), [self.sub_vertical2, self.sub_vertical1])


class VerticalDetailViewTests(TestCase):
"""Tests for the vertical detail view."""
@ddt
class SubVerticalListViewTests(BaseViewsTestCase):
"""Tests for the SubVerticalListView."""

def setUp(self):
"""Sets up test data for vertical detail view tests."""
self.vertical = VerticalFactory(name='AI')
self.sub_vertical = SubVerticalFactory(name='Python', vertical=self.vertical)
self.course = CourseFactory()
CourseVerticalFactory(course=self.course, vertical=self.vertical, sub_vertical=self.sub_vertical)
self.url = reverse('tagging:vertical_detail', kwargs={'slug': self.vertical.slug})
super().setUp()
self.client.force_login(self.superuser)
self.vertical = VerticalFactory(name="Technology")
self.sub_vertical1 = SubVerticalFactory(name="AI", vertical=self.vertical)
self.sub_vertical2 = SubVerticalFactory(name="Business", vertical=self.vertical)
self.url = reverse("tagging:sub_vertical_list")

def test_get_vertical_detail(self):
"""Tests GET request to the vertical detail view."""
def test_get_sub_vertical_list(self):
"""Tests GET request to sub-vertical list view."""
response = self.client.get(self.url)
self.assertEqual(response.status_code, 200)
self.assertTemplateUsed(response, 'tagging/vertical_detail.html')
self.assertIn('vertical', response.context)
self.assertIn('courses', response.context)
self.assertTemplateUsed(response, "tagging/sub_vertical_list.html")
self.assertIn("sub_verticals", response.context)

@data(('asc', ["AI", "Business"]), ('desc', ["Business", "AI"]))
def test_sort_sub_verticals(self, direction_and_order):
"""Tests sorting sub-verticals by name in ascending and descending order."""
direction, expected_order = direction_and_order
response = self.client.get(self.url, {"sort": "name", "direction": direction})
self.assertEqual(response.status_code, 200)
sub_verticals = response.context["sub_verticals"]
self.assertEqual([sub_vertical.name for sub_vertical in sub_verticals], expected_order)


class SubVerticalDetailViewTests(TestCase):
"""Tests for the sub-vertical detail view."""
class SubVerticalDetailViewTests(BaseViewsTestCase):
"""Tests for the SubVerticalDetailView."""

def setUp(self):
"""Sets up test data for sub-vertical detail view tests."""
self.vertical = VerticalFactory(name='AI')
self.sub_vertical = SubVerticalFactory(name='Python', vertical=self.vertical)
self.course = CourseFactory()
CourseVerticalFactory(course=self.course, vertical=self.vertical, sub_vertical=self.sub_vertical)
self.url = reverse('tagging:sub_vertical_detail', kwargs={'slug': self.sub_vertical.slug})
super().setUp()
self.client.force_login(self.superuser)
self.vertical = VerticalFactory(name="AI")
self.sub_vertical = SubVerticalFactory(name="Python", vertical=self.vertical)
self.course = CourseFactory(title="Deep Learning")
_ = CourseVerticalFactory(course=self.course, vertical=self.vertical, sub_vertical=self.sub_vertical)
self.url = reverse("tagging:sub_vertical_detail", kwargs={"slug": self.sub_vertical.slug})

def test_get_sub_vertical_detail(self):
"""Tests GET request to the sub-vertical detail view."""
"""Tests GET request to sub-vertical detail view."""
response = self.client.get(self.url)
self.assertEqual(response.status_code, 200)
self.assertTemplateUsed(response, 'tagging/sub_vertical_detail.html')
self.assertIn('sub_vertical', response.context)
self.assertIn('courses', response.context)
self.assertTemplateUsed(response, "tagging/sub_vertical_detail.html")
self.assertContains(response, self.sub_vertical.name)
self.assertContains(response, self.vertical.name)
self.assertContains(response, self.course.title)
8 changes: 2 additions & 6 deletions course_discovery/apps/tagging/urls.py
Original file line number Diff line number Diff line change
@@ -1,12 +1,8 @@
from django.urls import path

from course_discovery.apps.tagging.views import (
CourseTaggingDetailView,
CourseListView,
SubVerticalDetailView,
SubVerticalListView,
VerticalDetailView,
VerticalListView,
CourseListView, CourseTaggingDetailView, SubVerticalDetailView, SubVerticalListView, VerticalDetailView,
VerticalListView
)

app_name = 'tagging'
Expand Down
Loading

0 comments on commit 7d8b058

Please sign in to comment.