From 017d025f2af2aa64be7c14a04aaeb5be469e5a94 Mon Sep 17 00:00:00 2001 From: michaelroytman Date: Tue, 10 Dec 2024 17:26:16 -0500 Subject: [PATCH] feat: add trial_length attribute to ChatSummaryView response In order for the frontend to know the trial length of an audit trial, a trial_length attribute is added to the ChatSummaryView response as an attribute of the audit_trial object. This property is supplied whether or not a learner has an audit trial. --- learning_assistant/api.py | 13 ++----------- learning_assistant/utils.py | 25 +++++++++++++++++++++++++ learning_assistant/views.py | 11 +++++++---- tests/test_api.py | 26 ++++++++++++++------------ tests/test_utils.py | 31 ++++++++++++++++++++++++++++++- tests/test_views.py | 27 ++++++++++++++++++++++++--- 6 files changed, 102 insertions(+), 31 deletions(-) diff --git a/learning_assistant/api.py b/learning_assistant/api.py index 9483888..3f1ff5c 100644 --- a/learning_assistant/api.py +++ b/learning_assistant/api.py @@ -34,6 +34,7 @@ traverse_block_pre_order, ) from learning_assistant.text_utils import html_to_text +from learning_assistant.utils import get_audit_trial_length_days log = logging.getLogger(__name__) User = get_user_model() @@ -247,17 +248,7 @@ def get_audit_trial_expiration_date(start_date): Returns: * expiration_date (datetime): the expiration date of the audit trial """ - default_trial_length_days = 14 - - trial_length_days = getattr(settings, 'LEARNING_ASSISTANT_AUDIT_TRIAL_LENGTH_DAYS', default_trial_length_days) - - if trial_length_days is None: - trial_length_days = default_trial_length_days - - # If LEARNING_ASSISTANT_AUDIT_TRIAL_LENGTH_DAYS is set to a negative number, assume it should be 0. - # pylint: disable=consider-using-max-builtin - if trial_length_days < 0: - trial_length_days = 0 + trial_length_days = get_audit_trial_length_days() expiration_datetime = start_date + timedelta(days=trial_length_days) return expiration_datetime diff --git a/learning_assistant/utils.py b/learning_assistant/utils.py index 79a9884..3a7ff59 100644 --- a/learning_assistant/utils.py +++ b/learning_assistant/utils.py @@ -112,3 +112,28 @@ def user_role_is_staff(role): * bool: whether the user's role is that of a staff member """ return role in ('staff', 'instructor') + + +def get_audit_trial_length_days(): + """ + Return the length of an audit trial in days. + + Arguments: + * None + + Returns: + * int: the length of an audit trial in days + """ + default_trial_length_days = 14 + + trial_length_days = getattr(settings, 'LEARNING_ASSISTANT_AUDIT_TRIAL_LENGTH_DAYS', default_trial_length_days) + + if trial_length_days is None: + trial_length_days = default_trial_length_days + + # If LEARNING_ASSISTANT_AUDIT_TRIAL_LENGTH_DAYS is set to a negative number, assume it should be 0. + # pylint: disable=consider-using-max-builtin + if trial_length_days < 0: + trial_length_days = 0 + + return trial_length_days diff --git a/learning_assistant/views.py b/learning_assistant/views.py index 58351e1..9f325e7 100644 --- a/learning_assistant/views.py +++ b/learning_assistant/views.py @@ -35,7 +35,7 @@ from learning_assistant.models import LearningAssistantMessage from learning_assistant.serializers import MessageSerializer from learning_assistant.toggles import chat_history_enabled -from learning_assistant.utils import get_chat_response, user_role_is_staff +from learning_assistant.utils import get_audit_trial_length_days, get_chat_response, user_role_is_staff log = logging.getLogger(__name__) @@ -335,9 +335,10 @@ def get(self, request, course_run_id): "timestamp": "2024-12-02T15:04:40.084584Z" } ], - "trial": { + "audit_trial": { "start_date": "2024-12-02T14:59:16.148236Z", - "expiration_date": "2024-12-16T14:59:16.148236Z" + "expiration_date": "2024-12-26T14:59:16.148236Z", + 'trial_length_days': 14, } } """ @@ -402,7 +403,9 @@ def get(self, request, course_run_id): # Get audit trial. trial = get_audit_trial(user) - trial_data = {} + trial_data = { + 'trial_length_days': get_audit_trial_length_days(), + } if trial: trial_data['start_date'] = trial.start_date trial_data['expiration_date'] = trial.expiration_date diff --git a/tests/test_api.py b/tests/test_api.py index eda7602..3937856 100644 --- a/tests/test_api.py +++ b/tests/test_api.py @@ -492,22 +492,24 @@ class GetAuditTrialExpirationDateTests(TestCase): Test suite for get_audit_trial_expiration_date. """ @ddt.data( - (datetime(2024, 1, 1, 0, 0, 0), datetime(2024, 1, 15, 0, 0, 0), None), - (datetime(2024, 1, 18, 0, 0, 0), datetime(2024, 2, 1, 0, 0, 0), None), + (datetime(2024, 1, 1, 0, 0, 0), datetime(2024, 1, 2, 0, 0, 0), 1), + (datetime(2024, 1, 18, 0, 0, 0), datetime(2024, 1, 19, 0, 0, 0), 1), + (datetime(2024, 1, 1, 0, 0, 0), datetime(2024, 1, 8, 0, 0, 0), 7), + (datetime(2024, 1, 18, 0, 0, 0), datetime(2024, 1, 25, 0, 0, 0), 7), (datetime(2024, 1, 1, 0, 0, 0), datetime(2024, 1, 15, 0, 0, 0), 14), (datetime(2024, 1, 18, 0, 0, 0), datetime(2024, 2, 1, 0, 0, 0), 14), - (datetime(2024, 1, 1, 0, 0, 0), datetime(2024, 1, 1, 0, 0, 0), -1), - (datetime(2024, 1, 18, 0, 0, 0), datetime(2024, 1, 18, 0, 0, 0), -1), - (datetime(2024, 1, 1, 0, 0, 0), datetime(2024, 1, 1, 0, 0, 0), 0), - (datetime(2024, 1, 18, 0, 0, 0), datetime(2024, 1, 18, 0, 0, 0), 0), - (datetime(2024, 1, 1, 0, 0, 0), datetime(2024, 1, 4, 0, 0, 0), 3), - (datetime(2024, 1, 18, 0, 0, 0), datetime(2024, 1, 21, 0, 0, 0), 3), ) @ddt.unpack - def test_expiration_date(self, start_date, expected_expiration_date, trial_length_days): - with override_settings(LEARNING_ASSISTANT_AUDIT_TRIAL_LENGTH_DAYS=trial_length_days): - expiration_date = get_audit_trial_expiration_date(start_date) - self.assertEqual(expected_expiration_date, expiration_date) + @patch('learning_assistant.api.get_audit_trial_length_days') + def test_expiration_date( + self, start_date, + expected_expiration_date, + trial_length_days, + mock_get_audit_trial_length_days + ): + mock_get_audit_trial_length_days.return_value = trial_length_days + expiration_date = get_audit_trial_expiration_date(start_date) + self.assertEqual(expected_expiration_date, expiration_date) class GetAuditTrialTests(TestCase): diff --git a/tests/test_utils.py b/tests/test_utils.py index b81830e..1ab0315 100644 --- a/tests/test_utils.py +++ b/tests/test_utils.py @@ -10,7 +10,12 @@ from django.test import TestCase, override_settings from requests.exceptions import ConnectTimeout -from learning_assistant.utils import get_chat_response, get_reduced_message_list, user_role_is_staff +from learning_assistant.utils import ( + get_audit_trial_length_days, + get_chat_response, + get_reduced_message_list, + user_role_is_staff, +) @ddt.ddt @@ -145,3 +150,27 @@ class UserRoleIsStaffTests(TestCase): @ddt.unpack def test_user_role_is_staff(self, role, expected_value): self.assertEqual(user_role_is_staff(role), expected_value) + + +@ddt.ddt +class GetAuditTrialLengthDaysTests(TestCase): + """ + Tests for the get_audit_trial_length_days helper function. + """ + @ddt.data( + (None, 14), + (0, 0), + (-7, 0), + (7, 7), + (14, 14), + (28, 28), + ) + @ddt.unpack + def test_get_audit_trial_length_days_with_value(self, setting_value, expected_value): + with patch.object(settings, 'LEARNING_ASSISTANT_AUDIT_TRIAL_LENGTH_DAYS', setting_value): + self.assertEqual(get_audit_trial_length_days(), expected_value) + + @override_settings() + def test_get_audit_trial_length_days_no_setting(self): + del settings.LEARNING_ASSISTANT_AUDIT_TRIAL_LENGTH_DAYS + self.assertEqual(get_audit_trial_length_days(), 14) diff --git a/tests/test_views.py b/tests/test_views.py index a70aad5..39ea88a 100644 --- a/tests/test_views.py +++ b/tests/test_views.py @@ -495,12 +495,14 @@ def test_invalid_course_id(self, mock_course_key): ['verified', 'credit', 'no-id', 'audit', None], # course mode [True, False], # trial available [True, False], # trial expired + [7, 14], # trial length ) ) @ddt.unpack @patch('learning_assistant.views.audit_trial_is_expired') @patch('learning_assistant.views.chat_history_enabled') @patch('learning_assistant.views.learning_assistant_enabled') + @patch('learning_assistant.views.get_audit_trial_length_days') @patch('learning_assistant.views.get_user_role') @patch('learning_assistant.views.CourseEnrollment') @patch('learning_assistant.views.CourseMode') @@ -512,9 +514,11 @@ def test_chat_summary_with_access_instructor( course_mode_mock_value, trial_available, audit_trial_is_expired_mock_value, + audit_trial_length_days_mock_value, mock_mode, mock_enrollment, mock_get_user_role, + mock_get_audit_trial_length_days, mock_learning_assistant_enabled, mock_chat_history_enabled, mock_audit_trial_is_expired, @@ -555,6 +559,7 @@ def test_chat_summary_with_access_instructor( # Set up audit trial data. mock_audit_trial_is_expired.return_value = audit_trial_is_expired_mock_value + mock_get_audit_trial_length_days.return_value = audit_trial_length_days_mock_value trial_start_date = datetime(2024, 1, 1, 0, 0, 0) if trial_available: @@ -588,7 +593,9 @@ def test_chat_summary_with_access_instructor( self.assertEqual(response.data['message_history'], []) # Assert trial data is correct. - expected_trial_data = {} + expected_trial_data = { + 'trial_length_days': audit_trial_length_days_mock_value, + } if trial_available: expected_trial_data['start_date'] = trial_start_date expected_trial_data['expiration_date'] = trial_start_date + timedelta(days=14) @@ -603,12 +610,14 @@ def test_chat_summary_with_access_instructor( ['verified', 'credit', 'no-id'], # course mode [True, False], # trial available [True, False], # trial expired + [7, 14], # trial length ) ) @ddt.unpack @patch('learning_assistant.views.audit_trial_is_expired') @patch('learning_assistant.views.chat_history_enabled') @patch('learning_assistant.views.learning_assistant_enabled') + @patch('learning_assistant.views.get_audit_trial_length_days') @patch('learning_assistant.views.get_user_role') @patch('learning_assistant.views.CourseEnrollment') @patch('learning_assistant.views.CourseMode') @@ -620,9 +629,11 @@ def test_chat_summary_with_full_access_student( course_mode_mock_value, trial_available, audit_trial_is_expired_mock_value, + audit_trial_length_days_mock_value, mock_mode, mock_enrollment, mock_get_user_role, + mock_get_audit_trial_length_days, mock_learning_assistant_enabled, mock_chat_history_enabled, mock_audit_trial_is_expired, @@ -663,6 +674,7 @@ def test_chat_summary_with_full_access_student( # Set up audit trial data. mock_audit_trial_is_expired.return_value = audit_trial_is_expired_mock_value + mock_get_audit_trial_length_days.return_value = audit_trial_length_days_mock_value trial_start_date = datetime(2024, 1, 1, 0, 0, 0) if trial_available: @@ -696,7 +708,9 @@ def test_chat_summary_with_full_access_student( self.assertEqual(response.data['message_history'], []) # Assert trial data is correct. - expected_trial_data = {} + expected_trial_data = { + 'trial_length_days': audit_trial_length_days_mock_value, + } if trial_available: expected_trial_data['start_date'] = trial_start_date expected_trial_data['expiration_date'] = trial_start_date + timedelta(days=14) @@ -711,12 +725,14 @@ def test_chat_summary_with_full_access_student( ['audit'], # course mode [True, False], # trial available [True, False], # trial expired + [7, 14], # trial length ) ) @ddt.unpack @patch('learning_assistant.views.audit_trial_is_expired') @patch('learning_assistant.views.chat_history_enabled') @patch('learning_assistant.views.learning_assistant_enabled') + @patch('learning_assistant.views.get_audit_trial_length_days') @patch('learning_assistant.views.get_user_role') @patch('learning_assistant.views.CourseEnrollment') @patch('learning_assistant.views.CourseMode') @@ -728,9 +744,11 @@ def test_chat_summary_with_trial_access_student( course_mode_mock_value, trial_available, audit_trial_is_expired_mock_value, + audit_trial_length_days_mock_value, mock_mode, mock_enrollment, mock_get_user_role, + mock_get_audit_trial_length_days, mock_learning_assistant_enabled, mock_chat_history_enabled, mock_audit_trial_is_expired, @@ -771,6 +789,7 @@ def test_chat_summary_with_trial_access_student( # Set up audit trial data. mock_audit_trial_is_expired.return_value = audit_trial_is_expired_mock_value + mock_get_audit_trial_length_days.return_value = audit_trial_length_days_mock_value trial_start_date = datetime(2024, 1, 1, 0, 0, 0) if trial_available: @@ -804,7 +823,9 @@ def test_chat_summary_with_trial_access_student( self.assertEqual(response.data['message_history'], []) # Assert trial data is correct. - expected_trial_data = {} + expected_trial_data = { + 'trial_length_days': audit_trial_length_days_mock_value, + } if trial_available: expected_trial_data['start_date'] = trial_start_date expected_trial_data['expiration_date'] = trial_start_date + timedelta(days=14)