def setUp(self):
     super(TestOutcomeService, self).setUp()
     self.outcome_servce = OutcomeService(self.xblock)
 def setUp(self):
     super(TestOutcomeService, self).setUp()
     self.outcome_servce = OutcomeService(self.xblock)
class TestOutcomeService(TestLtiConsumerXBlock):
    """
    Unit tests for OutcomeService
    """
    def setUp(self):
        super(TestOutcomeService, self).setUp()
        self.outcome_servce = OutcomeService(self.xblock)

    @patch('lti_consumer.outcomes.verify_oauth_body_signature',
           Mock(return_value=True))
    @patch(
        'lti_consumer.lti_consumer.LtiConsumerXBlock.lti_provider_key_secret',
        PropertyMock(return_value=('t', 's')))
    @patch('lti_consumer.outcomes.parse_grade_xml_body',
           Mock(return_value=('', '', 0.5, 'replaceResultRequest')))
    def test_handle_replace_result_success(self):
        """
        Test replace result request returns with success indicator
        """
        request = make_request('')
        values = {
            'code': 'success',
            'description': 'Score for  is now 0.5',
            'msg_id': '',
            'response': '<replaceResultResponse/>'
        }

        self.assertEqual(
            self.outcome_servce.handle_request(request).strip(),
            RESPONSE_BODY_TEMPLATE.format(**values).strip())

    @patch('lti_consumer.lti_consumer.LtiConsumerXBlock.is_past_due',
           PropertyMock(return_value=True))
    def test_grade_past_due(self):
        """
        Test late grade returns failure response
        """
        request = make_request('')
        self.xblock.accept_grades_past_due = False
        response = self.outcome_servce.handle_request(request)

        self.assertIn('failure', response)
        self.assertIn('Grade is past due', response)

    @patch('lti_consumer.outcomes.parse_grade_xml_body')
    def test_xml_parse_lti_error(self, mock_parse):
        """
        Test XML parsing LtiError returns failure response
        """
        request = make_request('')

        mock_parse.side_effect = LtiError
        response = self.outcome_servce.handle_request(request)
        self.assertIn('failure', response)
        self.assertIn('Request body XML parsing error', response)

    @patch('lti_consumer.outcomes.verify_oauth_body_signature')
    @patch(
        'lti_consumer.lti_consumer.LtiConsumerXBlock.lti_provider_key_secret',
        PropertyMock(return_value=('t', 's')))
    @patch('lti_consumer.outcomes.parse_grade_xml_body',
           Mock(return_value=('', '', 0.5, 'replaceResultRequest')))
    def test_invalid_signature(self, mock_verify):
        """
        Test invalid oauth signature returns failure response
        """
        request = make_request('')

        mock_verify.side_effect = ValueError
        self.assertIn('failure', self.outcome_servce.handle_request(request))

        mock_verify.side_effect = LtiError
        self.assertIn('failure', self.outcome_servce.handle_request(request))

    @patch('lti_consumer.outcomes.verify_oauth_body_signature',
           Mock(return_value=True))
    @patch(
        'lti_consumer.lti_consumer.LtiConsumerXBlock.lti_provider_key_secret',
        PropertyMock(return_value=('t', 's')))
    @patch('lti_consumer.outcomes.parse_grade_xml_body',
           Mock(return_value=('', '', 0.5, 'replaceResultRequest')))
    def test_user_not_found(self):
        """
        Test user not found returns failure response
        """
        request = make_request('')
        self.xblock.runtime.get_real_user.return_value = None
        response = self.outcome_servce.handle_request(request)

        self.assertIn('failure', response)
        self.assertIn('User not found', response)

    @patch('lti_consumer.outcomes.verify_oauth_body_signature',
           Mock(return_value=True))
    @patch(
        'lti_consumer.lti_consumer.LtiConsumerXBlock.lti_provider_key_secret',
        PropertyMock(return_value=('t', 's')))
    @patch('lti_consumer.outcomes.parse_grade_xml_body',
           Mock(return_value=('', '', 0.5, 'unsupportedRequest')))
    def test_unsupported_action(self):
        """
        Test unsupported action returns unsupported response
        """
        request = make_request('')
        response = self.outcome_servce.handle_request(request)

        self.assertIn('unsupported', response)
        self.assertIn('Target does not support the requested operation.',
                      response)
class TestOutcomeService(TestLtiConsumerXBlock):
    """
    Unit tests for OutcomeService
    """

    def setUp(self):
        super(TestOutcomeService, self).setUp()
        self.outcome_servce = OutcomeService(self.xblock)

    @patch('lti_consumer.outcomes.verify_oauth_body_signature', Mock(return_value=True))
    @patch('lti_consumer.lti_consumer.LtiConsumerXBlock.lti_provider_key_secret', PropertyMock(return_value=('t', 's')))
    @patch('lti_consumer.outcomes.parse_grade_xml_body', Mock(return_value=('', '', 0.5, 'replaceResultRequest')))
    def test_handle_replace_result_success(self):
        """
        Test replace result request returns with success indicator
        """
        request = make_request('')
        values = {
            'code': 'success',
            'description': 'Score for  is now 0.5',
            'msg_id': '',
            'response': '<replaceResultResponse/>'
        }

        self.assertEqual(
            self.outcome_servce.handle_request(request).strip(),
            RESPONSE_BODY_TEMPLATE.format(**values).strip()
        )

    @patch('lti_consumer.lti_consumer.LtiConsumerXBlock.is_past_due', PropertyMock(return_value=True))
    def test_grade_past_due(self):
        """
        Test late grade returns failure response
        """
        request = make_request('')
        self.xblock.accept_grades_past_due = False
        response = self.outcome_servce.handle_request(request)

        self.assertIn('failure', response)
        self.assertIn('Grade is past due', response)

    @patch('lti_consumer.outcomes.parse_grade_xml_body')
    def test_xml_parse_lti_error(self, mock_parse):
        """
        Test XML parsing LtiError returns failure response
        """
        request = make_request('')

        mock_parse.side_effect = LtiError
        response = self.outcome_servce.handle_request(request)
        self.assertIn('failure', response)
        self.assertIn('Request body XML parsing error', response)

    @patch('lti_consumer.outcomes.verify_oauth_body_signature')
    @patch('lti_consumer.lti_consumer.LtiConsumerXBlock.lti_provider_key_secret', PropertyMock(return_value=('t', 's')))
    @patch('lti_consumer.outcomes.parse_grade_xml_body', Mock(return_value=('', '', 0.5, 'replaceResultRequest')))
    def test_invalid_signature(self, mock_verify):
        """
        Test invalid oauth signature returns failure response
        """
        request = make_request('')

        mock_verify.side_effect = ValueError
        self.assertIn('failure', self.outcome_servce.handle_request(request))

        mock_verify.side_effect = LtiError
        self.assertIn('failure', self.outcome_servce.handle_request(request))

    @patch('lti_consumer.outcomes.verify_oauth_body_signature', Mock(return_value=True))
    @patch('lti_consumer.lti_consumer.LtiConsumerXBlock.lti_provider_key_secret', PropertyMock(return_value=('t', 's')))
    @patch('lti_consumer.outcomes.parse_grade_xml_body', Mock(return_value=('', '', 0.5, 'replaceResultRequest')))
    def test_user_not_found(self):
        """
        Test user not found returns failure response
        """
        request = make_request('')
        self.xblock.runtime.get_real_user.return_value = None
        response = self.outcome_servce.handle_request(request)

        self.assertIn('failure', response)
        self.assertIn('User not found', response)

    @patch('lti_consumer.outcomes.verify_oauth_body_signature', Mock(return_value=True))
    @patch('lti_consumer.lti_consumer.LtiConsumerXBlock.lti_provider_key_secret', PropertyMock(return_value=('t', 's')))
    @patch('lti_consumer.outcomes.parse_grade_xml_body', Mock(return_value=('', '', 0.5, 'unsupportedRequest')))
    def test_unsupported_action(self):
        """
        Test unsupported action returns unsupported response
        """
        request = make_request('')
        response = self.outcome_servce.handle_request(request)

        self.assertIn('unsupported', response)
        self.assertIn('Target does not support the requested operation.', response)