Skip to content

Commit

Permalink
feat: add audit_trial_length attribute to ChatSummaryView response (#143
Browse files Browse the repository at this point in the history
)

In order for the frontend to know the currently configured trial length of an audit trial in days, an audit_trial_length attribute is added to the ChatSummaryView response.

This property is supplied whether or not a learner has an audit trial. It represents the number of days in an audit trial as currently configured. It does not represent the number of days in the learner's current trial.
  • Loading branch information
MichaelRoytman authored Dec 11, 2024
1 parent ed0061e commit 39d2f21
Show file tree
Hide file tree
Showing 8 changed files with 103 additions and 29 deletions.
6 changes: 6 additions & 0 deletions CHANGELOG.rst
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,12 @@ Change Log
Unreleased
**********

4.6.0 - 2025-12-10
******************
* Add an audit_trial_length_days attribute to the response returned by the ChatSummaryView, representing the
number of days in an audit trial as currently configured. It does not necessarily represent the number of days in the
learner's current trial.

4.5.0 - 2024-12-04
******************
* Add local setup to readme
Expand Down
2 changes: 1 addition & 1 deletion learning_assistant/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,6 @@
Plugin for a learning assistant backend, intended for use within edx-platform.
"""

__version__ = '4.5.0'
__version__ = '4.6.0'

default_app_config = 'learning_assistant.apps.LearningAssistantConfig' # pylint: disable=invalid-name
13 changes: 2 additions & 11 deletions learning_assistant/api.py
Original file line number Diff line number Diff line change
Expand Up @@ -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()
Expand Down Expand Up @@ -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
Expand Down
25 changes: 25 additions & 0 deletions learning_assistant/utils.py
Original file line number Diff line number Diff line change
Expand Up @@ -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
11 changes: 7 additions & 4 deletions learning_assistant/views.py
Original file line number Diff line number Diff line change
Expand Up @@ -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__)

Expand Down Expand Up @@ -335,10 +335,11 @@ 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",
},
"audit_trial_length_days": 14
}
"""
try:
Expand Down Expand Up @@ -409,4 +410,6 @@ def get(self, request, course_run_id):

data['audit_trial'] = trial_data

data['audit_trial_length_days'] = get_audit_trial_length_days()

return Response(status=http_status.HTTP_200_OK, data=data)
26 changes: 14 additions & 12 deletions tests/test_api.py
Original file line number Diff line number Diff line change
Expand Up @@ -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):
Expand Down
31 changes: 30 additions & 1 deletion tests/test_utils.py
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down Expand Up @@ -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)
18 changes: 18 additions & 0 deletions tests/test_views.py
Original file line number Diff line number Diff line change
Expand Up @@ -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')
Expand All @@ -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,
Expand Down Expand Up @@ -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:
Expand Down Expand Up @@ -594,6 +599,7 @@ def test_chat_summary_with_access_instructor(
expected_trial_data['expiration_date'] = trial_start_date + timedelta(days=14)

self.assertEqual(response.data['audit_trial'], expected_trial_data)
self.assertEqual(response.data['audit_trial_length_days'], audit_trial_length_days_mock_value)

@ddt.data(
*product(
Expand All @@ -603,12 +609,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')
Expand All @@ -620,9 +628,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,
Expand Down Expand Up @@ -663,6 +673,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:
Expand Down Expand Up @@ -702,6 +713,7 @@ def test_chat_summary_with_full_access_student(
expected_trial_data['expiration_date'] = trial_start_date + timedelta(days=14)

self.assertEqual(response.data['audit_trial'], expected_trial_data)
self.assertEqual(response.data['audit_trial_length_days'], audit_trial_length_days_mock_value)

@ddt.data(
*product(
Expand All @@ -711,12 +723,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')
Expand All @@ -728,9 +742,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,
Expand Down Expand Up @@ -771,6 +787,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:
Expand Down Expand Up @@ -810,3 +827,4 @@ def test_chat_summary_with_trial_access_student(
expected_trial_data['expiration_date'] = trial_start_date + timedelta(days=14)

self.assertEqual(response.data['audit_trial'], expected_trial_data)
self.assertEqual(response.data['audit_trial_length_days'], audit_trial_length_days_mock_value)

0 comments on commit 39d2f21

Please sign in to comment.