Skip to content
This repository has been archived by the owner on Aug 21, 2024. It is now read-only.

Commit

Permalink
feat: use a setting to control whether enrollments age is visible
Browse files Browse the repository at this point in the history
The test mixin structure here is somewhat inverted, where the most
abstract mixins have the tests and lower levels provide functions to
fill them in. I pushed one test definition down a bit to get actual
control of the test closer to where it is used. This structure reuses
a tiny amount of code at a high cost in readability, there is more
refactoring that could happen here.

Unfortunately nav items are class variables, so I had to introduce an
easy way to rerun their creation during test. Again, there is more
refactoring that could happen here to make nav construction less of a
weird mix between class variables and instance functions.

MST-1241
  • Loading branch information
ashultz0 committed Jan 13, 2022
1 parent 5330569 commit 05cf1cb
Show file tree
Hide file tree
Showing 10 changed files with 200 additions and 101 deletions.
10 changes: 10 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -112,6 +112,16 @@ The following flags are available:
|--------------------------------|-------------------------------------------------------|
| display_learner_analytics | Display Learner Analytics links |


Settings describe features which are not expected to be toggled on and off without significant system changes.

The following setting is available:

| Flag | Purpose |
|--------------------------------|-------------------------------------------------------|
| ENROLLMENT_AGE_AVAILABLE | Display age as part of enrollment demographics |


Authentication & Authorization
------------------------------
This section is only necessary if running I stand alone service OAuth2 is automatically configured by provisioning in devstack.
Expand Down
67 changes: 44 additions & 23 deletions analytics_dashboard/courses/tests/test_views/__init__.py
Original file line number Diff line number Diff line change
@@ -1,10 +1,11 @@
import json
import logging
from unittest import mock

from unittest.mock import Mock, patch
import httpretty
from analyticsclient.exceptions import NotFoundError
from ddt import data, ddt
from ddt import data, ddt, unpack
from django.conf import settings
from django.contrib.humanize.templatetags.humanize import intcomma
from django.core.cache import cache
Expand All @@ -22,6 +23,8 @@
get_mock_api_enrollment_data,
mock_course_name,
)
from analytics_dashboard.courses.views.enrollment import EnrollmentTemplateView, _enrollment_secondary_nav, \
EnrollmentDemographicsTemplateView, _enrollment_tertiary_nav

logger = logging.getLogger(__name__)

Expand Down Expand Up @@ -157,12 +160,6 @@ def path(self, **kwargs):


class NavAssertMixin:
def assertPrimaryNav(self, nav, course_id):
raise NotImplementedError

def assertSecondaryNavs(self, nav, course_id):
raise NotImplementedError

def assertNavs(self, actual_navs, expected_navs, active_nav_label):
for item in expected_navs:
if item['text'] == active_nav_label:
Expand All @@ -185,17 +182,6 @@ def test_invalid_course(self):
response = self.client.get(path, follow=True)
self.assertEqual(response.status_code, 404)

def getAndValidateView(self, course_id):
raise NotImplementedError

@httpretty.activate
@data(CourseSamples.DEMO_COURSE_ID, CourseSamples.DEPRECATED_DEMO_COURSE_ID)
@override_switch('enable_course_api', active=True)
@override_switch('display_course_name_in_nav', active=True)
def test_valid_course(self, course_id):
self.mock_course_detail(course_id)
self.getAndValidateView(course_id)

def assertValidMissingDataContext(self, context):
raise NotImplementedError

Expand All @@ -216,10 +202,31 @@ def assertValidCourseName(self, course_id, context):


# pylint: disable=abstract-method
@ddt
class CourseEnrollmentViewTestMixin(CourseViewTestMixin):
active_secondary_nav_label = None
api_method = 'analyticsclient.course.Course.enrollment'

@httpretty.activate
@data(
(CourseSamples.DEMO_COURSE_ID, True),
(CourseSamples.DEMO_COURSE_ID, False),
(CourseSamples.DEPRECATED_DEMO_COURSE_ID, True)
)
@unpack
@override_switch('enable_course_api', active=True)
@override_switch('display_course_name_in_nav', active=True)
def test_valid_course(self, course_id, age_available):
with mock.patch('analytics_dashboard.courses.views.enrollment.age_available', return_value=age_available):
# we have to rebuild nav according to setting since navs are on the class
EnrollmentTemplateView.secondary_nav_items = _enrollment_secondary_nav()
EnrollmentDemographicsTemplateView.tertiary_nav_items = _enrollment_tertiary_nav()
self.mock_course_detail(course_id)
self.getAndValidateView(course_id, age_available)
# put the navs back to default
EnrollmentTemplateView.secondary_nav_items = _enrollment_secondary_nav()
EnrollmentDemographicsTemplateView.tertiary_nav_items = _enrollment_tertiary_nav()

def assertPrimaryNav(self, nav, course_id):
expected = {
'icon': 'fa-child',
Expand All @@ -235,7 +242,7 @@ def assertPrimaryNav(self, nav, course_id):
}
self.assertDictEqual(nav, expected)

def assertSecondaryNavs(self, nav, course_id):
def assertSecondaryNavs(self, nav, course_id, age_available):
reverse_kwargs = {'course_id': course_id}
expected = [
{
Expand Down Expand Up @@ -270,6 +277,18 @@ def assertSecondaryNavs(self, nav, course_id):
}
]

if not age_available:
expected[1] = {
'name': 'demographics',
'text': 'Demographics',
'translated_text': _('Demographics'),
'href': reverse('courses:enrollment:demographics_education', kwargs=reverse_kwargs),
'scope': 'course',
'lens': 'enrollment',
'report': 'demographics',
'depth': 'education'
}

self.assertNavs(nav, expected, self.active_secondary_nav_label)

def get_mock_data(self, course_id):
Expand All @@ -288,12 +307,12 @@ def format_tip_percent(self, value):

return formatted_percent

def assertAllNavs(self, context, course_id):
def assertAllNavs(self, context, course_id, age_available):
self.assertPrimaryNav(context['primary_nav_item'], course_id)
self.assertSecondaryNavs(context['secondary_nav_items'], course_id)
self.assertTertiaryNavs(context['tertiary_nav_items'], course_id)
self.assertSecondaryNavs(context['secondary_nav_items'], course_id, age_available)
self.assertTertiaryNavs(context['tertiary_nav_items'], course_id, age_available)

def assertTertiaryNavs(self, nav, course_id):
def assertTertiaryNavs(self, nav, course_id, age_available):
reverse_kwargs = {'course_id': course_id}
expected = [
{
Expand Down Expand Up @@ -327,6 +346,8 @@ def assertTertiaryNavs(self, nav, course_id):
'depth': 'gender'
}
]
if not age_available:
expected.pop(0)
self.assertNavs(nav, expected, self.active_tertiary_nav_label)


Expand Down
10 changes: 9 additions & 1 deletion analytics_dashboard/courses/tests/test_views/test_engagement.py
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
from unittest.mock import Mock, patch
import analyticsclient.constants.activity_types as AT
import httpretty
from ddt import ddt
from ddt import ddt, data
from django.test import TestCase
from django.urls import reverse
from django.utils.translation import ugettext_lazy as _
Expand Down Expand Up @@ -88,6 +88,14 @@ class CourseEngagementContentViewTests(CourseViewTestMixin, CourseEngagementView
'analytics_dashboard.courses.presenters.engagement.CourseEngagementActivityPresenter.get_summary_and_trend_data'
active_secondary_nav_label = 'Content'

@httpretty.activate
@data(CourseSamples.DEMO_COURSE_ID, CourseSamples.DEPRECATED_DEMO_COURSE_ID)
@override_switch('enable_course_api', active=True)
@override_switch('display_course_name_in_nav', active=True)
def test_valid_course(self, course_id):
self.mock_course_detail(course_id)
self.getAndValidateView(course_id)

def get_expected_secondary_nav(self, course_id):
expected = super().get_expected_secondary_nav(course_id)
expected[1].update({
Expand Down
20 changes: 11 additions & 9 deletions analytics_dashboard/courses/tests/test_views/test_enrollment.py
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@ class CourseEnrollmentActivityViewTests(CourseEnrollmentViewTestMixin, TestCase)
presenter_method = \
'analytics_dashboard.courses.presenters.enrollment.CourseEnrollmentPresenter.get_summary_and_trend_data'

def getAndValidateView(self, course_id):
def getAndValidateView(self, course_id, age_available):
summary, enrollment_data = utils.get_mock_enrollment_summary_and_trend(course_id)
rv = summary, enrollment_data
with mock.patch(self.presenter_method, return_value=rv):
Expand All @@ -42,7 +42,7 @@ def getAndValidateView(self, course_id):
self.assertListEqual(trend_data, expected)

self.assertPrimaryNav(context['primary_nav_item'], course_id)
self.assertSecondaryNavs(context['secondary_nav_items'], course_id)
self.assertSecondaryNavs(context['secondary_nav_items'], course_id, age_available)
self.assertValidCourseName(course_id, response.context)

def assertValidMissingDataContext(self, context):
Expand All @@ -60,7 +60,7 @@ class CourseEnrollmentGeographyViewTests(CourseEnrollmentViewTestMixin, TestCase
def get_mock_data(self, course_id):
return utils.get_mock_api_enrollment_geography_data(course_id)

def getAndValidateView(self, course_id):
def getAndValidateView(self, course_id, age_available):
with mock.patch(self.presenter_method, return_value=utils.get_mock_presenter_enrollment_geography_data()):
response = self.client.get(self.path(course_id=course_id))
context = response.context
Expand All @@ -76,6 +76,8 @@ def getAndValidateView(self, course_id):
self.assertEqual(page_data['course']['enrollmentByCountry'], expected_data)

self.assertValidCourseName(course_id, response.context)
self.assertPrimaryNav(context['primary_nav_item'], course_id)
self.assertSecondaryNavs(context['secondary_nav_items'], course_id, age_available)

def assertValidMissingDataContext(self, context):
self.assertIsNone(context['update_message'])
Expand All @@ -89,7 +91,7 @@ class CourseEnrollmentDemographicsAge(CourseEnrollmentDemographicsMixin, TestCas
presenter_method = \
'analytics_dashboard.courses.presenters.enrollment.CourseEnrollmentDemographicsPresenter.get_ages'

def getAndValidateView(self, course_id):
def getAndValidateView(self, course_id, age_available):
last_updated, summary, binned_ages, known_percent = utils.get_presenter_ages()
rv = last_updated, summary, binned_ages, known_percent
with mock.patch(self.presenter_method, return_value=rv):
Expand All @@ -109,7 +111,7 @@ def getAndValidateView(self, course_id):
actual_ages = page_data['course']['ages']
self.assertListEqual(actual_ages, binned_ages)
self.assertDictEqual(context['summary'], summary)
self.assertAllNavs(context, course_id)
self.assertAllNavs(context, course_id, age_available)

self.assertValidCourseName(course_id, response.context)

Expand All @@ -128,7 +130,7 @@ class CourseEnrollmentDemographicsEducation(CourseEnrollmentDemographicsMixin, T
presenter_method = \
'analytics_dashboard.courses.presenters.enrollment.CourseEnrollmentDemographicsPresenter.get_education'

def getAndValidateView(self, course_id):
def getAndValidateView(self, course_id, age_available):
last_updated, summary, education_data, known_percent = utils.get_presenter_education()
rv = last_updated, summary, education_data, known_percent
with mock.patch(self.presenter_method, return_value=rv):
Expand All @@ -148,7 +150,7 @@ def getAndValidateView(self, course_id):
actual_education = page_data['course']['education']
self.assertListEqual(actual_education, education_data)
self.assertDictEqual(context['summary'], summary)
self.assertAllNavs(context, course_id)
self.assertAllNavs(context, course_id, age_available)

self.assertValidCourseName(course_id, response.context)

Expand All @@ -167,7 +169,7 @@ class CourseEnrollmentDemographicsGender(CourseEnrollmentDemographicsMixin, Test
presenter_method = \
'analytics_dashboard.courses.presenters.enrollment.CourseEnrollmentDemographicsPresenter.get_gender'

def getAndValidateView(self, course_id):
def getAndValidateView(self, course_id, age_available):
last_updated, gender_data, trend, known_percent = utils.get_presenter_gender(course_id)
rv = last_updated, gender_data, trend, known_percent
with mock.patch(self.presenter_method, return_value=rv):
Expand All @@ -190,7 +192,7 @@ def getAndValidateView(self, course_id):
actual_trends = page_data['course']['genderTrend']
self.assertListEqual(actual_trends, trend)

self.assertAllNavs(context, course_id)
self.assertAllNavs(context, course_id, age_available)
self.assertValidCourseName(course_id, response.context)

def get_mock_data(self, course_id):
Expand Down
8 changes: 8 additions & 0 deletions analytics_dashboard/courses/tests/test_views/test_pages.py
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,14 @@
class CourseHomeViewTests(CourseViewTestMixin, TestCase):
viewname = 'courses:home'

@httpretty.activate
@data(CourseSamples.DEMO_COURSE_ID, CourseSamples.DEPRECATED_DEMO_COURSE_ID)
@override_switch('enable_course_api', active=True)
@override_switch('display_course_name_in_nav', active=True)
def test_valid_course(self, course_id):
self.mock_course_detail(course_id)
self.getAndValidateView(course_id)

def getAndValidateView(self, course_id):
response = self.client.get(self.path(course_id=course_id))
self.assertEqual(response.status_code, 200)
Expand Down
Loading

0 comments on commit 05cf1cb

Please sign in to comment.