""" Unit tests for the XQueueInterfaceSubmission class. """ import json from unittest.mock import Mock, patch import pytest from opaque_keys.edx.locator import BlockUsageLocator, CourseLocator from xblock.fields import ScopeIds from xmodule.capa.xqueue_submission import XQueueInterfaceSubmission @pytest.fixture def xqueue_service(): """ Fixture that returns an instance of XQueueInterfaceSubmission. """ location = BlockUsageLocator(CourseLocator("test_org", "test_course", "test_run"), "problem", "ExampleProblem") block = Mock(scope_ids=ScopeIds("user1", "problem", location, location)) block.max_score = Mock(return_value=10) return XQueueInterfaceSubmission(block) def test_get_submission_params(xqueue_service): # pylint: disable=redefined-outer-name """ Test extracting item data from an xqueue submission. """ header = json.dumps({"lms_callback_url": "http://example.com/callback", "queue_name": "default"}) payload = json.dumps( { "student_info": json.dumps({"anonymous_student_id": "student_id"}), "student_response": "student_answer", "grader_payload": json.dumps({"grader": "test.py"}), } ) student_item, student_answer, queue_name, grader_file_name, points_possible = xqueue_service.get_submission_params( header, payload ) assert student_item == { "item_id": "block-v1:test_org+test_course+test_run+type@problem+block@ExampleProblem", "item_type": "problem", "course_id": "course-v1:test_org+test_course+test_run", "student_id": "student_id", } assert student_answer == "student_answer" assert queue_name == "default" assert grader_file_name == "test.py" assert points_possible == 10 @pytest.mark.django_db @patch("submissions.api.create_external_grader_detail") def test_send_to_submission(mock_create_external_grader_detail, xqueue_service): # pylint: disable=redefined-outer-name """ Test sending a submission to the grading system. """ header = json.dumps( { "lms_callback_url": ( "http://example.com/courses/course-v1:test_org+test_course+test_run/xqueue/5/" "block-v1:test_org+test_course+test_run+type@problem+block@ExampleProblem/" ), } ) body = json.dumps( { "student_info": json.dumps({"anonymous_student_id": "student_id"}), "student_response": "student_answer", "grader_payload": json.dumps({"grader": "test.py"}), } ) mock_response = {"submission": "mock_submission"} mock_create_external_grader_detail.return_value = mock_response result = xqueue_service.send_to_submission(header, body, queue_key="default") assert result == mock_response mock_create_external_grader_detail.assert_called_once_with( { "item_id": "block-v1:test_org+test_course+test_run+type@problem+block@ExampleProblem", "item_type": "problem", "course_id": "course-v1:test_org+test_course+test_run", "student_id": "student_id", }, "student_answer", queue_name="default", queue_key="default", grader_file_name="test.py", points_possible=10, files=None, ) @pytest.mark.django_db @patch("submissions.api.create_external_grader_detail") def test_send_to_submission_with_missing_fields( mock_create_external_grader_detail, xqueue_service ): # pylint: disable=redefined-outer-name """ Test send_to_submission with missing required fields. """ header = json.dumps( { "lms_callback_url": ( "http://example.com/courses/course-v1:test_org+test_course+test_run/xqueue/5/" "block@item_id/" ) } ) body = json.dumps( { "student_info": json.dumps({"anonymous_student_id": "student_id"}), "grader_payload": json.dumps({"grader": "test.py"}), } ) result = xqueue_service.send_to_submission(header, body, queue_key="default") assert "error" in result assert "Validation error" in result["error"] mock_create_external_grader_detail.assert_not_called()