Skip to content

Commit

Permalink
Store and update the assignment / course relationship
Browse files Browse the repository at this point in the history
  • Loading branch information
marcospri committed Aug 6, 2024
1 parent 700b393 commit 437d9b2
Show file tree
Hide file tree
Showing 4 changed files with 33 additions and 10 deletions.
17 changes: 14 additions & 3 deletions lms/services/assignment.py
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@
Assignment,
AssignmentGrouping,
AssignmentMembership,
Course,
Grouping,
LTIRole,
Organization,
Expand Down Expand Up @@ -52,7 +53,14 @@ def create_assignment(self, tool_consumer_instance_guid, resource_link_id):

return assignment

def update_assignment(self, request, assignment, document_url, group_set_id):
def update_assignment( # noqa: PLR0913
self,
request,
assignment: Assignment,
document_url: str,
group_set_id,
course: Course,
):
"""Update an existing assignment."""
if self._misc_plugin.is_speed_grader_launch(request):
# SpeedGrader has a number of issues regarding the information it sends about the assignment
Expand All @@ -74,6 +82,7 @@ def update_assignment(self, request, assignment, document_url, group_set_id):
assignment.is_gradable = self._misc_plugin.is_assignment_gradable(
request.lti_params
)
assignment.course_id = course.id

return assignment

Expand Down Expand Up @@ -101,7 +110,7 @@ def _get_copied_from_assignment(self, lti_params) -> Assignment | None:

return None

def get_assignment_for_launch(self, request) -> Assignment | None:
def get_assignment_for_launch(self, request, course: Course) -> Assignment | None:
"""
Get or create an assignment for the current launch.
Expand Down Expand Up @@ -157,7 +166,9 @@ def get_assignment_for_launch(self, request) -> Assignment | None:
# Always update the assignment configuration
# It often will be the same one while launching the assignment again but
# it might for example be an updated deep linked URL or similar.
return self.update_assignment(request, assignment, document_url, group_set_id)
return self.update_assignment(
request, assignment, document_url, group_set_id, course
)

def upsert_assignment_membership(
self, assignment: Assignment, user: User, lti_roles: list[LTIRole]
Expand Down
5 changes: 4 additions & 1 deletion lms/views/lti/basic_launch.py
Original file line number Diff line number Diff line change
Expand Up @@ -59,7 +59,9 @@ def __init__(self, context, request) -> None:
def lti_launch(self):
"""Handle regular LTI launches."""

assignment = self.assignment_service.get_assignment_for_launch(self.request)
assignment = self.assignment_service.get_assignment_for_launch(
self.request, self.course
)

if error_code := self.request.find_service(VitalSourceService).check_h_license(
self.request.lti_user, self.request.lti_params, assignment
Expand Down Expand Up @@ -263,6 +265,7 @@ def _configure_assignment(self, assignment):
assignment,
document_url=self.request.parsed_params["document_url"],
group_set_id=self.request.parsed_params.get("group_set"),
course=self.course,
)

def _configure_js_for_file_picker(
Expand Down
15 changes: 11 additions & 4 deletions tests/unit/lms/services/assignment_test.py
Original file line number Diff line number Diff line change
Expand Up @@ -39,6 +39,7 @@ def test_update_assignment(
resource_link_title,
title,
):
course = factories.Course()
pyramid_request.lti_params["resource_link_title"] = resource_link_title
misc_plugin.is_speed_grader_launch.return_value = is_speed_grader

Expand All @@ -47,9 +48,11 @@ def test_update_assignment(
factories.Assignment(),
sentinel.document_url,
sentinel.group_set_id,
course,
)

assignment.title = title
assignment.course_id = course.id
if is_speed_grader:
assert assignment.extra == {}
assert assignment.document_url != sentinel.document_url
Expand Down Expand Up @@ -100,13 +103,14 @@ def test_get_assignment_for_launch_existing(
get_assignment,
_get_copied_from_assignment,
):
course = factories.Course()
misc_plugin.get_assignment_configuration.return_value = {
"document_url": sentinel.document_url,
"group_set_id": sentinel.group_set_id,
}
get_assignment.return_value = factories.Assignment()

assignment = svc.get_assignment_for_launch(pyramid_request)
assignment = svc.get_assignment_for_launch(pyramid_request, course)

_get_copied_from_assignment.assert_not_called()
misc_plugin.get_assignment_configuration.assert_called_once_with(
Expand All @@ -123,13 +127,14 @@ def test_get_assignment_for_launch_existing(
"resource_link_description"
)
assert assignment.is_gradable == misc_plugin.is_assignment_gradable.return_value
assert assignment.course_id == course.id

def test_get_assignment_returns_None_with_when_no_document(
self, pyramid_request, svc, misc_plugin
):
misc_plugin.get_assignment_configuration.return_value = {"document_url": None}

assert not svc.get_assignment_for_launch(pyramid_request)
assert not svc.get_assignment_for_launch(pyramid_request, factories.Course())

@pytest.mark.parametrize("group_set_id", [None, "1"])
def test_get_assignment_creates_assignment(
Expand All @@ -142,6 +147,7 @@ def test_get_assignment_creates_assignment(
create_assignment,
group_set_id,
):
course = factories.Course()
misc_plugin.get_assignment_configuration.return_value = {
"document_url": sentinel.document_url,
"group_set_id": group_set_id,
Expand All @@ -150,13 +156,14 @@ def test_get_assignment_creates_assignment(
get_assignment.return_value = None
_get_copied_from_assignment.return_value = None

assignment = svc.get_assignment_for_launch(pyramid_request)
assignment = svc.get_assignment_for_launch(pyramid_request, course)

_get_copied_from_assignment.assert_called_once_with(pyramid_request.lti_params)
create_assignment.assert_called_once_with(
"TEST_TOOL_CONSUMER_INSTANCE_GUID", "TEST_RESOURCE_LINK_ID"
)
assert assignment.document_url == sentinel.document_url
assert assignment.course_id == course.id
if group_set_id:
assignment.extra["group_set_id"] = group_set_id
assert not assignment.copied_from
Expand All @@ -176,7 +183,7 @@ def test_get_assignment_created_assignments_point_to_copy(
get_assignment.return_value = None
_get_copied_from_assignment.return_value = sentinel.original_assignment

assignment = svc.get_assignment_for_launch(pyramid_request)
assignment = svc.get_assignment_for_launch(pyramid_request, factories.Course())

_get_copied_from_assignment.assert_called_once_with(pyramid_request.lti_params)
create_assignment.assert_called_once_with(
Expand Down
6 changes: 4 additions & 2 deletions tests/unit/lms/views/lti/basic_launch_test.py
Original file line number Diff line number Diff line change
Expand Up @@ -49,7 +49,7 @@ def test___init___(
)

def test_configure_assignment_callback(
self, svc, pyramid_request, _show_document, assignment_service
self, svc, pyramid_request, _show_document, assignment_service, course_service
):
pyramid_request.parsed_params = {
"document_url": sentinel.document_url,
Expand All @@ -67,6 +67,7 @@ def test_configure_assignment_callback(
assignment_service.create_assignment.return_value,
document_url=sentinel.document_url,
group_set_id=sentinel.group_set,
course=course_service.get_from_launch.return_value,
)
_show_document.assert_called_once_with(
assignment_service.create_assignment.return_value,
Expand Down Expand Up @@ -112,11 +113,12 @@ def test_lti_launch_configured(
pyramid_request,
_show_document,
LTIEvent,
course_service,
):
svc.lti_launch()

assignment_service.get_assignment_for_launch.assert_called_once_with(
pyramid_request
pyramid_request, course_service.get_from_launch.return_value
)

_show_document.assert_called_once_with(
Expand Down

0 comments on commit 437d9b2

Please sign in to comment.