Skip to content

Commit

Permalink
test: add a JS unit test to verify filterSubVerticals
Browse files Browse the repository at this point in the history
  • Loading branch information
Ali-D-Akbar committed Feb 4, 2025
1 parent 2884cc5 commit 87dd832
Showing 1 changed file with 117 additions and 1 deletion.
118 changes: 117 additions & 1 deletion course_discovery/apps/tagging/tests/test_views.py
Original file line number Diff line number Diff line change
@@ -1,8 +1,12 @@
from ddt import data, ddt
from django.conf import settings
from django.contrib.auth.models import Group
from django.test import TestCase
from django.test import LiveServerTestCase, TestCase
from django.urls import reverse
from selenium import webdriver
from selenium.webdriver.common.by import By
from selenium.webdriver.firefox.options import Options
from selenium.webdriver.support.ui import Select, WebDriverWait

from course_discovery.apps.core.tests.factories import UserFactory
from course_discovery.apps.course_metadata.tests.factories import CourseFactory
Expand Down Expand Up @@ -68,6 +72,118 @@ def test_post_invalid_sub_vertical(self):
self.assertContains(response, 'Sub-vertical does not belong to the selected vertical.')


class CourseTaggingDetailViewJSTests(LiveServerTestCase):
"""
Functional tests using Selenium to verify the JS script filterSubVerticals behavior in the CourseTaggingDetailView.
"""

@classmethod
def setUpClass(cls):
super().setUpClass()
firefox_options = Options()
firefox_options.headless = True
cls.driver = webdriver.Firefox(options=firefox_options)
cls.driver.implicitly_wait(10)

@classmethod
def tearDownClass(cls):
cls.driver.quit()
super().tearDownClass()

def setUp(self):
"""
Create a superuser, a course, verticals and sub-verticals used for testing.
"""
self.user = UserFactory(username='superuser_func', is_superuser=True, is_staff=True)
self.user.set_password('password')
self.user.save()

self.course = CourseFactory(title='Advanced Python')

self.vertical = VerticalFactory(name='AI')
self.sub_vertical = SubVerticalFactory(name='Machine Learning', vertical=self.vertical)

self.other_vertical = VerticalFactory(name='Business')
self.other_sub_vertical = SubVerticalFactory(name='Innovation', vertical=self.other_vertical)

self.multi_vertical = VerticalFactory(name='Data')
self.multi_sub_vertical1 = SubVerticalFactory(name='Analytics', vertical=self.multi_vertical)
self.multi_sub_vertical2 = SubVerticalFactory(name='Visualization', vertical=self.multi_vertical)

self.url = self.live_server_url + reverse('tagging:course_tagging_detail', kwargs={'uuid': self.course.uuid})
self.login_url = self.live_server_url + reverse('admin:login')

# Login via the admin login page as it does not share cookies with Django's test client.
self.driver.get(self.login_url)
self.driver.find_element(By.NAME, 'username').send_keys(self.user.username)
self.driver.find_element(By.NAME, 'password').send_keys('password')
self.driver.find_element(By.XPATH, "//input[@type='submit']").click()

self.driver.get(self.url)

def get_visible_options(self, select_id):
"""
Returns a list of visible <option> elements for the given select element.
Visible options are defined as those with a 'data-vertical' attribute and no inline 'display: none' style.
"""
select_element = self.driver.find_element(By.ID, select_id)
options = select_element.find_elements(By.TAG_NAME, 'option')
visible_options = [
option for option in options
if option.get_attribute('data-vertical') is not None
and 'display: none' not in (option.get_attribute('style') or '')
]
return visible_options

def filter_sub_verticals(self, vertical_slug, expected_slugs):
"""
Selects the vertical with the given slug, triggers the JavaScript change event, and waits
until the expected sub-vertical options (by their slug values) are visible in the sub_vertical select.
Returns the list of visible option elements.
"""
vertical_select = Select(self.driver.find_element(By.ID, 'vertical'))
vertical_select.select_by_value(vertical_slug)
self.driver.execute_script(
"document.getElementById('vertical').dispatchEvent(new Event('change'));"
)
# Wait until the visible sub-vertical options match the expected set.
WebDriverWait(self.driver, 5).until(
lambda d: set(
option.get_attribute('value')
for option in self.get_visible_options('sub_vertical')
) == set(expected_slugs)
)
return self.get_visible_options('sub_vertical')

def test_filter_sub_verticals_javascript_single_option(self):
"""
Verify that selecting a vertical with one sub-vertical (AI and Business) shows the expected single sub-vertical.
"""
# Test for vertical 'AI' with one sub-vertical 'Machine Learning'
visible_options = self.filter_sub_verticals(self.vertical.slug, [self.sub_vertical.slug])
self.assertEqual(len(visible_options), 1)
self.assertEqual(visible_options[0].get_attribute('value'), self.sub_vertical.slug)

# Test for vertical 'Business' with one sub-vertical 'Innovation'
visible_options = self.filter_sub_verticals(self.other_vertical.slug, [self.other_sub_vertical.slug])
self.assertEqual(len(visible_options), 1)
self.assertEqual(visible_options[0].get_attribute('value'), self.other_sub_vertical.slug)

def test_filter_sub_verticals_javascript_multiple_options(self):
"""
Verify that selecting a vertical with two sub-verticals ('Data') shows both sub-verticals.
"""
# Test for vertical 'Data' with two sub-verticals: 'Analytics' and 'Visualization'
visible_options = self.filter_sub_verticals(
self.multi_vertical.slug,
[self.multi_sub_vertical1.slug, self.multi_sub_vertical2.slug]
)
option_values = sorted([option.get_attribute('value') for option in visible_options])
expected_values = sorted([self.multi_sub_vertical1.slug, self.multi_sub_vertical2.slug])
self.assertEqual(len(visible_options), 2)
self.assertEqual(option_values, expected_values)


@ddt
class CourseListViewTests(BaseViewsTestCase):
"""Tests for the CourseListView."""
Expand Down

0 comments on commit 87dd832

Please sign in to comment.